Update Test924 to filter for messages related to test thread am: 1989aa4b39

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

Change-Id: I3ed6ed400f4be25848af2df71b8c01b2fa919d29
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/compiler/art_standalone_compiler_tests.xml b/compiler/art_standalone_compiler_tests.xml
index bf450a5..4cf6e3d 100644
--- a/compiler/art_standalone_compiler_tests.xml
+++ b/compiler/art_standalone_compiler_tests.xml
@@ -16,19 +16,19 @@
 <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="push" value="art_standalone_compiler_tests->/data/local/tmp/art_standalone_compiler_tests/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" />
+        <option name="push" value="art-gtest-jars-ExceptionHandle.jar->/data/local/tmp/art_standalone_compiler_tests/art-gtest-jars-ExceptionHandle.jar" />
+        <option name="push" value="art-gtest-jars-Interfaces.jar->/data/local/tmp/art_standalone_compiler_tests/art-gtest-jars-Interfaces.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/art_standalone_compiler_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_compiler_tests" />
         <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" />
@@ -42,4 +42,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/compiler/optimizing/execution_subgraph.cc b/compiler/optimizing/execution_subgraph.cc
index 6d10566..66fdfcd 100644
--- a/compiler/optimizing/execution_subgraph.cc
+++ b/compiler/optimizing/execution_subgraph.cc
@@ -86,12 +86,6 @@
     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;
@@ -170,8 +164,11 @@
             << "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;
+        if (visiting.IsBitSet(id)) {
+          // TODO We should support infinite loops as well.
+          start_reaches_end = false;
+          break;
+        }
         std::bitset<kMaxFilterableSuccessors>& result = results[id];
         if (cur_block == graph_->GetExitBlock()) {
           start_reaches_end = true;
diff --git a/compiler/optimizing/load_store_elimination.h b/compiler/optimizing/load_store_elimination.h
index e73ef5e..6ad2eb2 100644
--- a/compiler/optimizing/load_store_elimination.h
+++ b/compiler/optimizing/load_store_elimination.h
@@ -27,7 +27,7 @@
  public:
   // Whether or not we should attempt partial Load-store-elimination which
   // requires additional blocks and predicated instructions.
-  static constexpr bool kEnablePartialLSE = true;
+  static constexpr bool kEnablePartialLSE = false;
 
   // Controls whether to enable VLOG(compiler) logs explaining the transforms taking place.
   static constexpr bool kVerboseLoggingMode = false;
diff --git a/dex2oat/art_standalone_dex2oat_tests.xml b/dex2oat/art_standalone_dex2oat_tests.xml
index 672066a..8f9689a 100644
--- a/dex2oat/art_standalone_dex2oat_tests.xml
+++ b/dex2oat/art_standalone_dex2oat_tests.xml
@@ -16,41 +16,41 @@
 <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="push" value="art_standalone_dex2oat_tests->/data/local/tmp/art_standalone_dex2oat_tests/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" />
+        <option name="push" value="art-gtest-jars-AbstractMethod.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-AbstractMethod.jar" />
+        <option name="push" value="art-gtest-jars-DefaultMethods.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-DefaultMethods.jar" />
+        <option name="push" value="art-gtest-jars-DexToDexDecompiler.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-DexToDexDecompiler.jar" />
+        <option name="push" value="art-gtest-jars-Dex2oatVdexPublicSdkDex.dex->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-Dex2oatVdexPublicSdkDex.dex" />
+        <option name="push" value="art-gtest-jars-Dex2oatVdexTestDex.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-Dex2oatVdexTestDex.jar" />
+        <option name="push" value="art-gtest-jars-ImageLayoutA.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-ImageLayoutA.jar" />
+        <option name="push" value="art-gtest-jars-ImageLayoutB.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-ImageLayoutB.jar" />
+        <option name="push" value="art-gtest-jars-LinkageTest.dex->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-LinkageTest.dex" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MainEmptyUncompressed.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MainEmptyUncompressed.jar" />
+        <option name="push" value="art-gtest-jars-MainEmptyUncompressedAligned.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MainEmptyUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MainStripped.jar" />
+        <option name="push" value="art-gtest-jars-MainUncompressedAligned.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MainUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-ManyMethods.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-ManyMethods.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-MyClassNatives.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-Nested.jar" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-ProfileTestMultiDex.jar" />
+        <option name="push" value="art-gtest-jars-StaticLeafMethods.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-StaticLeafMethods.jar" />
+        <option name="push" value="art-gtest-jars-Statics.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-Statics.jar" />
+        <option name="push" value="art-gtest-jars-StringLiterals.jar->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-StringLiterals.jar" />
+        <option name="push" value="art-gtest-jars-VerifierDeps.dex->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-VerifierDeps.dex" />
+        <option name="push" value="art-gtest-jars-VerifierDepsMulti.dex->/data/local/tmp/art_standalone_dex2oat_tests/art-gtest-jars-VerifierDepsMulti.dex" />
+        <option name="push" value="art-gtest-jars-VerifySoftFailDuringClinit.dex->/data/local/tmp/art_standalone_dex2oat_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_dex2oat_tests" />
         <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" />
@@ -64,4 +64,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml b/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
index ae112d4..62cfcd2 100644
--- a/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
+++ b/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
@@ -18,25 +18,25 @@
 
     <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="push" value="art_standalone_dexoptanalyzer_tests->/data/local/tmp/art_standalone_dexoptanalyzer_tests/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" />
+        <option name="push" value="art-gtest-jars-LinkageTest.dex->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-LinkageTest.dex" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-MainStripped.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-MyClassNatives.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-Nested.jar" />
+        <option name="push" value="art-gtest-jars-VerifierDeps.dex->/data/local/tmp/art_standalone_dexoptanalyzer_tests/art-gtest-jars-VerifierDeps.dex" />
+        <option name="push" value="art-gtest-jars-VerifierDepsMulti.dex->/data/local/tmp/art_standalone_dexoptanalyzer_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_dexoptanalyzer_tests" />
         <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" />
@@ -50,4 +50,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/libartbase/base/memfd.h b/libartbase/base/memfd.h
index 0bb336d..3c27dcb 100644
--- a/libartbase/base/memfd.h
+++ b/libartbase/base/memfd.h
@@ -53,6 +53,10 @@
 # define F_SEAL_FUTURE_WRITE  0x0010
 #endif
 
+#ifndef MFD_CLOEXEC
+# define MFD_CLOEXEC    0x0001U
+#endif
+
 #ifndef MFD_ALLOW_SEALING
 # define MFD_ALLOW_SEALING    0x0002U
 #endif
diff --git a/libartpalette/apex/palette.cc b/libartpalette/apex/palette.cc
index 71fd39d..75a3878 100644
--- a/libartpalette/apex/palette.cc
+++ b/libartpalette/apex/palette.cc
@@ -218,4 +218,28 @@
   return m(env);
 }
 
+palette_status_t PaletteReportLockContention(JNIEnv* env,
+                                             int32_t wait_ms,
+                                             const char* filename,
+                                             int32_t line_number,
+                                             const char* method_name,
+                                             const char* owner_filename,
+                                             int32_t owner_line_number,
+                                             const char* owner_method_name,
+                                             const char* proc_name,
+                                             const char* thread_name) {
+  PaletteReportLockContentionMethod m =
+      PaletteLoader::Instance().GetPaletteReportLockContentionMethod();
+  return m(env,
+           wait_ms,
+           filename,
+           line_number,
+           method_name,
+           owner_filename,
+           owner_line_number,
+           owner_method_name,
+           proc_name,
+           thread_name);
+}
+
 }  // extern "C"
diff --git a/libartpalette/include/palette/palette_method_list.h b/libartpalette/include/palette/palette_method_list.h
index 6a7822b..066f24f 100644
--- a/libartpalette/include/palette/palette_method_list.h
+++ b/libartpalette/include/palette/palette_method_list.h
@@ -53,5 +53,15 @@
   M(PaletteShouldReportJniInvocations, bool*)                               \
   M(PaletteNotifyBeginJniInvocation, JNIEnv* env)                           \
   M(PaletteNotifyEndJniInvocation, JNIEnv* env)                             \
+  M(PaletteReportLockContention, JNIEnv* env,                               \
+                                 int32_t wait_ms,                           \
+                                 const char* filename,                      \
+                                 int32_t line_number,                       \
+                                 const char* method_name,                   \
+                                 const char* owner_filename,                \
+                                 int32_t owner_line_number,                 \
+                                 const char* owner_method_name,             \
+                                 const char* proc_name,                     \
+                                 const char* thread_name)                   \
 
 #endif  // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
diff --git a/libartpalette/libartpalette.map.txt b/libartpalette/libartpalette.map.txt
index 9c846b1..6401010 100644
--- a/libartpalette/libartpalette.map.txt
+++ b/libartpalette/libartpalette.map.txt
@@ -35,6 +35,7 @@
     PaletteShouldReportJniInvocations; #apex
     PaletteNotifyBeginJniInvocation; #apex
     PaletteNotifyEndJniInvocation; #apex
+    PaletteReportLockContention; #apex
 
   local:
     *;
diff --git a/libartpalette/system/palette_fake.cc b/libartpalette/system/palette_fake.cc
index dbbbf89..bbf8f2d 100644
--- a/libartpalette/system/palette_fake.cc
+++ b/libartpalette/system/palette_fake.cc
@@ -128,3 +128,16 @@
 palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env ATTRIBUTE_UNUSED) {
   return PALETTE_STATUS_OK;
 }
+
+palette_status_t PaletteReportLockContention(JNIEnv* env ATTRIBUTE_UNUSED,
+                                             int32_t wait_ms ATTRIBUTE_UNUSED,
+                                             const char* filename ATTRIBUTE_UNUSED,
+                                             int32_t line_number ATTRIBUTE_UNUSED,
+                                             const char* method_name ATTRIBUTE_UNUSED,
+                                             const char* owner_filename ATTRIBUTE_UNUSED,
+                                             int32_t owner_line_number ATTRIBUTE_UNUSED,
+                                             const char* owner_method_name ATTRIBUTE_UNUSED,
+                                             const char* proc_name ATTRIBUTE_UNUSED,
+                                             const char* thread_name ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
+}
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 31cf197..47f2e29 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -162,6 +162,15 @@
 
 art_cc_library {
     name: "libdexfile",
+    visibility: [
+        // Allow libdexfile_support users to list this as a runtime_libs
+        // dependency - see comment for libdexfile_support. It shouldn't be used
+        // for any other purpose.
+        "//external/perfetto",
+        "//system/core/debuggerd",
+        "//system/extras/simpleperf",
+        "//system/unwinding/libunwindstack",
+    ],
     defaults: [
         "libdexfile_defaults",
         "libart_nativeunwind_defaults",
@@ -369,6 +378,14 @@
 // 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.
+//
+// IMPORTANT: When adding a static_libs dependency on this library, please
+// remember to also add a corresponding
+//
+//     runtime_libs: ["libdexfile"],
+//
+// That is necessary since Soong doesn't propagate dependencies transitively for
+// static libraries (b/169779783).
 art_cc_library_static {
     name: "libdexfile_support",
     visibility: ["//visibility:public"],
diff --git a/libdexfile/art_standalone_libdexfile_tests.xml b/libdexfile/art_standalone_libdexfile_tests.xml
index 57987fd..d00235a 100644
--- a/libdexfile/art_standalone_libdexfile_tests.xml
+++ b/libdexfile/art_standalone_libdexfile_tests.xml
@@ -16,21 +16,21 @@
 <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="push" value="art_standalone_libdexfile_tests->/data/local/tmp/art_standalone_libdexfile_tests/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" />
+        <option name="push" value="art-gtest-jars-GetMethodSignature.jar->/data/local/tmp/art_standalone_libdexfile_tests/art-gtest-jars-GetMethodSignature.jar" />
+        <option name="push" value="art-gtest-jars-Lookup.jar->/data/local/tmp/art_standalone_libdexfile_tests/art-gtest-jars-Lookup.jar" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/art_standalone_libdexfile_tests/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/art_standalone_libdexfile_tests/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/art_standalone_libdexfile_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_libdexfile_tests" />
         <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" />
@@ -44,4 +44,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 5363b00..e3027fc 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -738,7 +738,7 @@
   }
 
   // Used by oat writer.
-  void SetOatDexFile(OatDexFile* oat_dex_file) const {
+  void SetOatDexFile(const OatDexFile* oat_dex_file) const {
     oat_dex_file_ = oat_dex_file;
   }
 
diff --git a/libprofile/art_standalone_libprofile_tests.xml b/libprofile/art_standalone_libprofile_tests.xml
index 069f203..f113668 100644
--- a/libprofile/art_standalone_libprofile_tests.xml
+++ b/libprofile/art_standalone_libprofile_tests.xml
@@ -16,19 +16,19 @@
 <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="push" value="art_standalone_libprofile_tests->/data/local/tmp/art_standalone_libprofile_tests/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" />
+        <option name="push" value="art-gtest-jars-ManyMethods.jar->/data/local/tmp/art_standalone_libprofile_tests/art-gtest-jars-ManyMethods.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/art_standalone_libprofile_tests/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/art_standalone_libprofile_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_libprofile_tests" />
         <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" />
@@ -42,4 +42,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/oatdump/art_standalone_oatdump_tests.xml b/oatdump/art_standalone_oatdump_tests.xml
index e83d2a2..57e9163 100644
--- a/oatdump/art_standalone_oatdump_tests.xml
+++ b/oatdump/art_standalone_oatdump_tests.xml
@@ -16,17 +16,17 @@
 <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="push" value="art_standalone_oatdump_tests->/data/local/tmp/art_standalone_oatdump_tests/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" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/art_standalone_oatdump_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_oatdump_tests" />
         <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" />
@@ -40,4 +40,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index d64086d..9b514af 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -423,7 +423,6 @@
   art::Thread* thread;
   {
     thread = thread_list->SuspendThreadByPeer(jthread,
-                                              true,
                                               art::SuspendReason::kInternal,
                                               &timed_out);
   }
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index bb8fa3b..a9a6ee8 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -898,7 +898,6 @@
     bool timeout = true;
     art::Thread* ret_target = art::Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
         target_jthread,
-        /* request_suspension= */ true,
         art::SuspendReason::kForUserCode,
         &timeout);
     if (ret_target == nullptr && !timeout) {
diff --git a/profman/art_standalone_profman_tests.xml b/profman/art_standalone_profman_tests.xml
index 31bee91..1710942 100644
--- a/profman/art_standalone_profman_tests.xml
+++ b/profman/art_standalone_profman_tests.xml
@@ -18,17 +18,17 @@
 
     <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="push" value="art_standalone_profman_tests->/data/local/tmp/art_standalone_profman_tests/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" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/art_standalone_profman_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_profman_tests" />
         <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" />
@@ -51,4 +51,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/runtime/art_standalone_runtime_compiler_tests.xml b/runtime/art_standalone_runtime_compiler_tests.xml
index 0f6bb4b..2bacda1 100644
--- a/runtime/art_standalone_runtime_compiler_tests.xml
+++ b/runtime/art_standalone_runtime_compiler_tests.xml
@@ -16,19 +16,19 @@
 <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="push" value="art_standalone_runtime_compiler_tests->/data/local/tmp/art_standalone_runtime_compiler_tests/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" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/art_standalone_runtime_compiler_tests/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-NonStaticLeafMethods.jar->/data/local/tmp/art_standalone_runtime_compiler_tests/art-gtest-jars-NonStaticLeafMethods.jar" />
+        <option name="push" value="art-gtest-jars-StaticLeafMethods.jar->/data/local/tmp/art_standalone_runtime_compiler_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_runtime_compiler_tests" />
         <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" />
@@ -42,4 +42,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/runtime/art_standalone_runtime_tests.xml b/runtime/art_standalone_runtime_tests.xml
index 1267213..a46b7b4 100644
--- a/runtime/art_standalone_runtime_tests.xml
+++ b/runtime/art_standalone_runtime_tests.xml
@@ -16,53 +16,53 @@
 <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="push" value="art_standalone_runtime_tests->/data/local/tmp/art_standalone_runtime_tests/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" />
+        <option name="push" value="art-gtest-jars-AllFields.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-AllFields.jar" />
+        <option name="push" value="art-gtest-jars-ErroneousA.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ErroneousA.jar" />
+        <option name="push" value="art-gtest-jars-ErroneousB.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ErroneousB.jar" />
+        <option name="push" value="art-gtest-jars-ErroneousInit.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ErroneousInit.jar" />
+        <option name="push" value="art-gtest-jars-Extension1.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Extension1.jar" />
+        <option name="push" value="art-gtest-jars-Extension2.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Extension2.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderA.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ForClassLoaderA.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderB.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ForClassLoaderB.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderC.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ForClassLoaderC.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderD.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ForClassLoaderD.jar" />
+        <option name="push" value="art-gtest-jars-HiddenApiSignatures.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-HiddenApiSignatures.jar" />
+        <option name="push" value="art-gtest-jars-IMTA.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-IMTA.jar" />
+        <option name="push" value="art-gtest-jars-IMTB.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-IMTB.jar" />
+        <option name="push" value="art-gtest-jars-Instrumentation.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Instrumentation.jar" />
+        <option name="push" value="art-gtest-jars-Interfaces.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Interfaces.jar" />
+        <option name="push" value="art-gtest-jars-LinkageTest.dex->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-LinkageTest.dex" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MainStripped.jar" />
+        <option name="push" value="art-gtest-jars-MainUncompressedAligned.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MainUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-MethodTypes.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MethodTypes.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexUncompressedAligned.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MultiDexUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-MyClass.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MyClass.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-MyClassNatives.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Nested.jar" />
+        <option name="push" value="art-gtest-jars-Packages.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Packages.jar" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ProfileTestMultiDex.jar" />
+        <option name="push" value="art-gtest-jars-ProtoCompare.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ProtoCompare.jar" />
+        <option name="push" value="art-gtest-jars-ProtoCompare2.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-ProtoCompare2.jar" />
+        <option name="push" value="art-gtest-jars-StaticLeafMethods.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-StaticLeafMethods.jar" />
+        <option name="push" value="art-gtest-jars-Statics.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Statics.jar" />
+        <option name="push" value="art-gtest-jars-StaticsFromCode.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-StaticsFromCode.jar" />
+        <option name="push" value="art-gtest-jars-Transaction.jar->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-Transaction.jar" />
+        <option name="push" value="art-gtest-jars-VerifierDeps.dex->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-VerifierDeps.dex" />
+        <option name="push" value="art-gtest-jars-VerifierDepsMulti.dex->/data/local/tmp/art_standalone_runtime_tests/art-gtest-jars-VerifierDepsMulti.dex" />
+        <option name="push" value="art-gtest-jars-XandY.jar->/data/local/tmp/art_standalone_runtime_tests/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="native-test-device-path" value="/data/local/tmp/art_standalone_runtime_tests" />
         <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" />
@@ -108,4 +108,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b9751ab..e21a004 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2621,6 +2621,26 @@
   return ClassPathEntry(nullptr, nullptr);
 }
 
+// Helper macro to make sure each class loader lookup call handles the case the
+// class loader is not recognized, or the lookup threw an exception.
+#define RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(call_, result_, thread_) \
+do {                                                                          \
+  auto local_call = call_;                                                    \
+  if (!local_call) {                                                          \
+    return false;                                                             \
+  }                                                                           \
+  auto local_result = result_;                                                \
+  if (local_result != nullptr) {                                              \
+    return true;                                                              \
+  }                                                                           \
+  auto local_thread = thread_;                                                \
+  if (local_thread->IsExceptionPending()) {                                   \
+    /* Pending exception means there was an error other than */               \
+    /* ClassNotFound that must be returned to the caller. */                  \
+    return false;                                                             \
+  }                                                                           \
+} while (0)
+
 bool ClassLinker::FindClassInSharedLibraries(ScopedObjectAccessAlreadyRunnable& soa,
                                              Thread* self,
                                              const char* descriptor,
@@ -2640,12 +2660,10 @@
   MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
   for (auto loader : shared_libraries.Iterate<mirror::ClassLoader>()) {
     temp_loader.Assign(loader);
-    if (!FindClassInBaseDexClassLoader(soa, self, descriptor, hash, temp_loader, result)) {
-      return false;  // One of the shared libraries is not supported.
-    }
-    if (*result != nullptr) {
-      return true;  // Found the class up the chain.
-    }
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBaseDexClassLoader(soa, self, descriptor, hash, temp_loader, result),
+        *result,
+        self);
   }
   return true;
 }
@@ -2658,7 +2676,8 @@
                                                 /*out*/ ObjPtr<mirror::Class>* result) {
   // Termination case: boot class loader.
   if (IsBootClassLoader(soa, class_loader.Get())) {
-    *result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBootClassLoaderClassPath(self, descriptor, hash, result), *result, self);
     return true;
   }
 
@@ -2668,26 +2687,24 @@
     //    - shared libraries
     //    - class loader dex files
 
-    // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension).
+    // Create a handle as RegisterDexFile may allocate dex caches (and cause thread suspension).
     StackHandleScope<1> hs(self);
     Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent()));
-    if (!FindClassInBaseDexClassLoader(soa, self, descriptor, hash, h_parent, result)) {
-      return false;  // One of the parents is not supported.
-    }
-    if (*result != nullptr) {
-      return true;  // Found the class up the chain.
-    }
-
-    if (!FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result)) {
-      return false;  // One of the shared library loader is not supported.
-    }
-    if (*result != nullptr) {
-      return true;  // Found the class in a shared library.
-    }
-
-    // Search the current class loader classpath.
-    *result = FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader);
-    return !soa.Self()->IsExceptionPending();
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBaseDexClassLoader(soa, self, descriptor, hash, h_parent, result),
+        *result,
+        self);
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result),
+        *result,
+        self);
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader, result),
+        *result,
+        self);
+    // We did not find a class, but the class loader chain was recognized, so we
+    // return true.
+    return true;
   }
 
   if (IsDelegateLastClassLoader(soa, class_loader)) {
@@ -2696,37 +2713,27 @@
     //    - shared libraries
     //    - class loader dex files
     //    - parent
-    *result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
-    if (*result != nullptr) {
-      return true;  // The class is part of the boot class path.
-    }
-    if (self->IsExceptionPending()) {
-      // Pending exception means there was an error other than ClassNotFound that must be returned
-      // to the caller.
-      return false;
-    }
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBootClassLoaderClassPath(self, descriptor, hash, result), *result, self);
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result),
+        *result,
+        self);
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader, result),
+        *result,
+        self);
 
-    if (!FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result)) {
-      return false;  // One of the shared library loader is not supported.
-    }
-    if (*result != nullptr) {
-      return true;  // Found the class in a shared library.
-    }
-
-    *result = FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader);
-    if (*result != nullptr) {
-      return true;  // Found the class in the current class loader
-    }
-    if (self->IsExceptionPending()) {
-      // Pending exception means there was an error other than ClassNotFound that must be returned
-      // to the caller.
-      return false;
-    }
-
-    // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension).
+    // Create a handle as RegisterDexFile may allocate dex caches (and cause thread suspension).
     StackHandleScope<1> hs(self);
     Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent()));
-    return FindClassInBaseDexClassLoader(soa, self, descriptor, hash, h_parent, result);
+    RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+        FindClassInBaseDexClassLoader(soa, self, descriptor, hash, h_parent, result),
+        *result,
+        self);
+    // We did not find a class, but the class loader chain was recognized, so we
+    // return true.
+    return true;
   }
 
   // Unsupported class loader.
@@ -2734,6 +2741,8 @@
   return false;
 }
 
+#undef RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION
+
 namespace {
 
 // Matches exceptions caught in DexFile.defineClass.
@@ -2761,36 +2770,38 @@
 
 // Finds the class in the boot class loader.
 // If the class is found the method returns the resolved class. Otherwise it returns null.
-ObjPtr<mirror::Class> ClassLinker::FindClassInBootClassLoaderClassPath(Thread* self,
-                                                                       const char* descriptor,
-                                                                       size_t hash) {
-  ObjPtr<mirror::Class> result = nullptr;
+bool ClassLinker::FindClassInBootClassLoaderClassPath(Thread* self,
+                                                      const char* descriptor,
+                                                      size_t hash,
+                                                      /*out*/ ObjPtr<mirror::Class>* result) {
   ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_);
   if (pair.second != nullptr) {
     ObjPtr<mirror::Class> klass = LookupClass(self, descriptor, hash, nullptr);
     if (klass != nullptr) {
-      result = EnsureResolved(self, descriptor, klass);
+      *result = EnsureResolved(self, descriptor, klass);
     } else {
-      result = DefineClass(self,
-                           descriptor,
-                           hash,
-                           ScopedNullHandle<mirror::ClassLoader>(),
-                           *pair.first,
-                           *pair.second);
+      *result = DefineClass(self,
+                            descriptor,
+                            hash,
+                            ScopedNullHandle<mirror::ClassLoader>(),
+                            *pair.first,
+                            *pair.second);
     }
-    if (result == nullptr) {
+    if (*result == nullptr) {
       CHECK(self->IsExceptionPending()) << descriptor;
       FilterDexFileCaughtExceptions(self, this);
     }
   }
-  return result;
+  // The boot classloader is always a known lookup.
+  return true;
 }
 
-ObjPtr<mirror::Class> ClassLinker::FindClassInBaseDexClassLoaderClassPath(
+bool ClassLinker::FindClassInBaseDexClassLoaderClassPath(
     ScopedObjectAccessAlreadyRunnable& soa,
     const char* descriptor,
     size_t hash,
-    Handle<mirror::ClassLoader> class_loader) {
+    Handle<mirror::ClassLoader> class_loader,
+    /*out*/ ObjPtr<mirror::Class>* result) {
   DCHECK(IsPathOrDexClassLoader(soa, class_loader) ||
          IsInMemoryDexClassLoader(soa, class_loader) ||
          IsDelegateLastClassLoader(soa, class_loader))
@@ -2810,17 +2821,17 @@
   };
   VisitClassLoaderDexFiles(soa, class_loader, find_class_def);
 
-  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)) {
+    *result = DefineClass(soa.Self(), descriptor, hash, class_loader, *dex_file, *class_def);
+    if (UNLIKELY(*result == nullptr)) {
       CHECK(soa.Self()->IsExceptionPending()) << descriptor;
       FilterDexFileCaughtExceptions(soa.Self(), this);
     } else {
       DCHECK(!soa.Self()->IsExceptionPending());
     }
   }
-  return klass;
+  // A BaseDexClassLoader is always a known lookup.
+  return true;
 }
 
 ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self,
@@ -9814,22 +9825,16 @@
 }
 
 void ClassLinker::DumpForSigQuit(std::ostream& os) {
-  // 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_);
+  ScopedObjectAccess soa(Thread::Current());
+  ReaderMutexLock mu(soa.Self(), *Locks::classlinker_classes_lock_);
   os << "Zygote loaded classes=" << NumZygoteClasses() << " post zygote classes="
      << NumNonZygoteClasses() << "\n";
-  ReaderMutexLock mu2(self, *Locks::dex_lock_);
+  ReaderMutexLock mu2(soa.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(self->DecodeJObject(class_loader.weak_root));
+        ObjPtr<mirror::ClassLoader>::DownCast(soa.Self()->DecodeJObject(class_loader.weak_root));
     if (loader != nullptr) {
       os << "#" << class_loader_index++ << " " << loader->GetClass()->PrettyDescriptor() << ": [";
       bool saw_one_dex_file = false;
@@ -9848,7 +9853,7 @@
         size_t parent_index = 0;
         for (const ClassLoaderData& class_loader2 : class_loaders_) {
           ObjPtr<mirror::ClassLoader> loader2 = ObjPtr<mirror::ClassLoader>::DownCast(
-              self->DecodeJObject(class_loader2.weak_root));
+              soa.Self()->DecodeJObject(class_loader2.weak_root));
           if (loader2 == loader->GetParent()) {
             os << ", parent #" << parent_index;
             found_parent = true;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 547753a..5faf760 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -1024,20 +1024,26 @@
   // dex files and does not recurse into its parent.
   // The method checks that the provided class loader is either a PathClassLoader or a
   // DexClassLoader.
-  // If the class is found the method returns the resolved class. Otherwise it returns null.
-  ObjPtr<mirror::Class> FindClassInBaseDexClassLoaderClassPath(
+  // If the class is found the method updates `result`.
+  // The method always returns true, to notify to the caller a
+  // BaseDexClassLoader has a known lookup.
+  bool FindClassInBaseDexClassLoaderClassPath(
           ScopedObjectAccessAlreadyRunnable& soa,
           const char* descriptor,
           size_t hash,
-          Handle<mirror::ClassLoader> class_loader)
+          Handle<mirror::ClassLoader> class_loader,
+          /*out*/ ObjPtr<mirror::Class>* result)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
   // Finds the class in the boot class loader.
-  // If the class is found the method returns the resolved class. Otherwise it returns null.
-  ObjPtr<mirror::Class> FindClassInBootClassLoaderClassPath(Thread* self,
-                                                            const char* descriptor,
-                                                            size_t hash)
+  // If the class is found the method updates `result`.
+  // The method always returns true, to notify to the caller the
+  // boot class loader has a known lookup.
+  bool FindClassInBootClassLoaderClassPath(Thread* self,
+                                           const char* descriptor,
+                                           size_t hash,
+                                           /*out*/ ObjPtr<mirror::Class>* result)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 538d7be..936b919 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -1630,11 +1630,16 @@
     // for the last time before transitioning to the shared mark stack mode, which would process new
     // refs that may have been concurrently pushed onto the mark stack during the ProcessMarkStack()
     // call above. At the same time, disable weak ref accesses using a per-thread flag. It's
-    // important to do these together in a single checkpoint so that we can ensure that mutators
-    // won't newly gray objects and push new refs onto the mark stack due to weak ref accesses and
+    // important to do these together so that we can ensure that mutators won't
+    // newly gray objects and push new refs onto the mark stack due to weak ref accesses and
     // mutators safely transition to the shared mark stack mode (without leaving unprocessed refs on
     // the thread-local mark stacks), without a race. This is why we use a thread-local weak ref
     // access flag Thread::tls32_.weak_ref_access_enabled_ instead of the global ones.
+    // We must use a stop-the-world pause to disable weak ref access. A checkpoint may lead to a
+    // deadlock if one mutator acquires a low-level mutex and then gets blocked while accessing
+    // a weak-ref (after participating in the checkpoint), and another mutator indefinitely waits
+    // for the mutex before it participates in the checkpoint. Consequently, the gc-thread blocks
+    // forever as the checkpoint never finishes (See runtime/mutator_gc_coord.md).
     SwitchToSharedMarkStackMode();
     CHECK(!self->GetWeakRefAccessEnabled());
     // Now that weak refs accesses are disabled, once we exhaust the shared mark stack again here
@@ -2044,21 +2049,36 @@
 void ConcurrentCopying::RevokeThreadLocalMarkStacks(bool disable_weak_ref_access,
                                                     Closure* checkpoint_callback) {
   Thread* self = Thread::Current();
-  RevokeThreadLocalMarkStackCheckpoint check_point(this, disable_weak_ref_access);
+  Locks::mutator_lock_->AssertSharedHeld(self);
   ThreadList* thread_list = Runtime::Current()->GetThreadList();
-  gc_barrier_->Init(self, 0);
-  size_t barrier_count = thread_list->RunCheckpoint(&check_point, checkpoint_callback);
-  // If there are no threads to wait which implys that all the checkpoint functions are finished,
-  // then no need to release the mutator lock.
-  if (barrier_count == 0) {
-    return;
+  RevokeThreadLocalMarkStackCheckpoint check_point(this, disable_weak_ref_access);
+  if (disable_weak_ref_access) {
+    // We're the only thread that could possibly ask for exclusive access here.
+    Locks::mutator_lock_->SharedUnlock(self);
+    {
+      ScopedPause pause(this);
+      MutexLock mu(self, *Locks::thread_list_lock_);
+      checkpoint_callback->Run(self);
+      for (Thread* thread : thread_list->GetList()) {
+        check_point.Run(thread);
+      }
+    }
+    Locks::mutator_lock_->SharedLock(self);
+  } else {
+    gc_barrier_->Init(self, 0);
+    size_t barrier_count = thread_list->RunCheckpoint(&check_point, checkpoint_callback);
+    // If there are no threads to wait which implys that all the checkpoint functions are finished,
+    // then no need to release the mutator lock.
+    if (barrier_count == 0) {
+      return;
+    }
+    Locks::mutator_lock_->SharedUnlock(self);
+    {
+      ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
+      gc_barrier_->Increment(self, barrier_count);
+    }
+    Locks::mutator_lock_->SharedLock(self);
   }
-  Locks::mutator_lock_->SharedUnlock(self);
-  {
-    ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
-    gc_barrier_->Increment(self, barrier_count);
-  }
-  Locks::mutator_lock_->SharedLock(self);
 }
 
 void ConcurrentCopying::RevokeThreadLocalMarkStack(Thread* thread) {
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 5ee8871..876e120 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -1238,7 +1238,8 @@
       // Start with '/boot' and end with '.art' to match the pattern recognized
       // by android_os_Debug.cpp for boot images.
       const char* name = "/boot-image-methods.art";
-      unique_fd mem_fd = unique_fd(art::memfd_create(name, /* flags= */ MFD_ALLOW_SEALING));
+      unique_fd mem_fd =
+          unique_fd(art::memfd_create(name, /* flags= */ MFD_ALLOW_SEALING | MFD_CLOEXEC));
       if (mem_fd.get() == -1) {
         PLOG(WARNING) << "Could not create boot image methods file descriptor";
         return;
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc
index 58a4041..56407f5 100644
--- a/runtime/jit/jit_memory_region.cc
+++ b/runtime/jit/jit_memory_region.cc
@@ -20,6 +20,7 @@
 #include <unistd.h>
 
 #include <android-base/unique_fd.h>
+#include <log/log.h>
 #include "base/bit_utils.h"  // For RoundDown, RoundUp
 #include "base/globals.h"
 #include "base/logging.h"  // For VLOG.
@@ -64,7 +65,15 @@
   // File descriptor enabling dual-view mapping of code section.
   unique_fd mem_fd;
 
+
+  // The memory mappings we are going to create.
+  MemMap data_pages;
+  MemMap exec_pages;
+  MemMap non_exec_pages;
+  MemMap writable_data_pages;
+
   if (is_zygote) {
+    android_errorWriteLog(0x534e4554, "200284993");  // Report to SafetyNet.
     // Because we are not going to GC code generated by the zygote, just use all available.
     current_capacity_ = max_capacity;
     mem_fd = unique_fd(CreateZygoteMemory(capacity, error_msg));
@@ -92,17 +101,12 @@
     }
   }
 
+  // Map name specific for android_os_Debug.cpp accounting.
   std::string data_cache_name = is_zygote ? "zygote-data-code-cache" : "data-code-cache";
   std::string exec_cache_name = is_zygote ? "zygote-jit-code-cache" : "jit-code-cache";
 
   std::string error_str;
-  // Map name specific for android_os_Debug.cpp accounting.
-  // Map in low 4gb to simplify accessing root tables for x86_64.
-  // We could do PC-relative addressing to avoid this problem, but that
-  // would require reserving code and data area before submitting, which
-  // means more windows for the code memory to be RWX.
   int base_flags;
-  MemMap data_pages;
   if (mem_fd.get() >= 0) {
     // Dual view of JIT code cache case. Create an initial mapping of data pages large enough
     // for data and non-writable view of JIT code pages. We use the memory file descriptor to
@@ -131,7 +135,63 @@
     // Additionally, the zyzote will create a dual view of the data portion of
     // the cache. This mapping will be read-only, whereas the second mapping
     // will be writable.
+
     base_flags = MAP_SHARED;
+
+    // Create the writable mappings now, so that in case of the zygote, we can
+    // prevent any future writable mappings through sealing.
+    if (exec_capacity > 0) {
+      // For dual view, create the secondary view of code memory used for updating code. This view
+      // is never executable.
+      std::string name = exec_cache_name + "-rw";
+      non_exec_pages = MemMap::MapFile(exec_capacity,
+                                       kIsDebugBuild ? kProtR : kProtRW,
+                                       base_flags,
+                                       mem_fd,
+                                       /* start= */ data_capacity,
+                                       /* low_4GB= */ false,
+                                       name.c_str(),
+                                       &error_str);
+      if (!non_exec_pages.IsValid()) {
+        // This is unexpected.
+        *error_msg = "Failed to map non-executable view of JIT code cache";
+        return false;
+      }
+      // Create a dual view of the data cache.
+      name = data_cache_name + "-rw";
+      writable_data_pages = MemMap::MapFile(data_capacity,
+                                            kProtRW,
+                                            base_flags,
+                                            mem_fd,
+                                            /* start= */ 0,
+                                            /* low_4GB= */ false,
+                                            name.c_str(),
+                                            &error_str);
+      if (!writable_data_pages.IsValid()) {
+        std::ostringstream oss;
+        oss << "Failed to create dual data view: " << error_str;
+        *error_msg = oss.str();
+        return false;
+      }
+      if (writable_data_pages.MadviseDontFork() != 0) {
+        *error_msg = "Failed to MadviseDontFork the writable data view";
+        return false;
+      }
+      if (non_exec_pages.MadviseDontFork() != 0) {
+        *error_msg = "Failed to MadviseDontFork the writable code view";
+        return false;
+      }
+      // Now that we have created the writable and executable mappings, prevent creating any new
+      // ones.
+      if (is_zygote && !ProtectZygoteMemory(mem_fd.get(), error_msg)) {
+        return false;
+      }
+    }
+
+    // Map in low 4gb to simplify accessing root tables for x86_64.
+    // We could do PC-relative addressing to avoid this problem, but that
+    // would require reserving code and data area before submitting, which
+    // means more windows for the code memory to be RWX.
     data_pages = MemMap::MapFile(
         data_capacity + exec_capacity,
         kProtR,
@@ -172,9 +232,6 @@
     return false;
   }
 
-  MemMap exec_pages;
-  MemMap non_exec_pages;
-  MemMap writable_data_pages;
   if (exec_capacity > 0) {
     uint8_t* const divider = data_pages.Begin() + data_capacity;
     // Set initial permission for executable view to catch any SELinux permission problems early
@@ -193,59 +250,6 @@
       *error_msg = oss.str();
       return false;
     }
-
-    if (mem_fd.get() >= 0) {
-      // For dual view, create the secondary view of code memory used for updating code. This view
-      // is never executable.
-      std::string name = exec_cache_name + "-rw";
-      non_exec_pages = MemMap::MapFile(exec_capacity,
-                                       kIsDebugBuild ? kProtR : kProtRW,
-                                       base_flags,
-                                       mem_fd,
-                                       /* start= */ data_capacity,
-                                       /* low_4GB= */ false,
-                                       name.c_str(),
-                                       &error_str);
-      if (!non_exec_pages.IsValid()) {
-        static const char* kFailedNxView = "Failed to map non-executable view of JIT code cache";
-        if (rwx_memory_allowed) {
-          // Log and continue as single view JIT (requires RWX memory).
-          VLOG(jit) << kFailedNxView;
-        } else {
-          *error_msg = kFailedNxView;
-          return false;
-        }
-      }
-      // Create a dual view of the data cache.
-      name = data_cache_name + "-rw";
-      writable_data_pages = MemMap::MapFile(data_capacity,
-                                            kProtRW,
-                                            base_flags,
-                                            mem_fd,
-                                            /* start= */ 0,
-                                            /* low_4GB= */ false,
-                                            name.c_str(),
-                                            &error_str);
-      if (!writable_data_pages.IsValid()) {
-        std::ostringstream oss;
-        oss << "Failed to create dual data view: " << error_str;
-        *error_msg = oss.str();
-        return false;
-      }
-      if (writable_data_pages.MadviseDontFork() != 0) {
-        *error_msg = "Failed to madvise dont fork the writable data view";
-        return false;
-      }
-      if (non_exec_pages.MadviseDontFork() != 0) {
-        *error_msg = "Failed to madvise dont fork the writable code view";
-        return false;
-      }
-      // Now that we have created the writable and executable mappings, prevent creating any new
-      // ones.
-      if (is_zygote && !ProtectZygoteMemory(mem_fd.get(), error_msg)) {
-        return false;
-      }
-    }
   } else {
     // Profiling only. No memory for code required.
   }
@@ -552,7 +556,7 @@
       return false;
     }
   } else {
-    palette_status_t status = PaletteAshmemSetProtRegion(fd, PROT_READ);
+    palette_status_t status = PaletteAshmemSetProtRegion(fd, PROT_READ | PROT_EXEC);
     if (status != PALETTE_STATUS_OK) {
       CHECK_EQ(status, PALETTE_STATUS_CHECK_ERRNO);
       std::ostringstream oss;
diff --git a/runtime/jit/jit_memory_region_test.cc b/runtime/jit/jit_memory_region_test.cc
index 2049611..18f34fb 100644
--- a/runtime/jit/jit_memory_region_test.cc
+++ b/runtime/jit/jit_memory_region_test.cc
@@ -492,6 +492,62 @@
     munmap(addr, kPageSize);
     munmap(shared, kPageSize);
   }
+
+  // Test that a readable mapping created befire sealing future writes, can be
+  // changed into a writable mapping.
+  void TestVmMayWriteBefore() {
+    // Zygote JIT memory only works on kernels that don't segfault on flush.
+    TEST_DISABLED_FOR_KERNELS_WITH_CACHE_SEGFAULT();
+    std::string error_msg;
+    size_t size = kPageSize;
+    int32_t* addr = nullptr;
+    {
+      android::base::unique_fd fd(JitMemoryRegion::CreateZygoteMemory(size, &error_msg));
+      CHECK_NE(fd.get(), -1);
+
+      // Create a shared readable mapping.
+      addr = reinterpret_cast<int32_t*>(
+          mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, fd.get(), 0));
+      CHECK(addr != nullptr);
+      CHECK_NE(addr, MAP_FAILED);
+
+      // Protect the memory.
+      bool res = JitMemoryRegion::ProtectZygoteMemory(fd.get(), &error_msg);
+      CHECK(res);
+    }
+    // At this point, the fd has been dropped, but the memory mappings are still
+    // there.
+    int res = mprotect(addr, kPageSize, PROT_WRITE);
+    CHECK_EQ(res, 0);
+  }
+
+  // Test that we cannot create a writable mapping after sealing future writes.
+  void TestVmMayWriteAfter() {
+    // Zygote JIT memory only works on kernels that don't segfault on flush.
+    TEST_DISABLED_FOR_KERNELS_WITH_CACHE_SEGFAULT();
+    std::string error_msg;
+    size_t size = kPageSize;
+    int32_t* addr = nullptr;
+    {
+      android::base::unique_fd fd(JitMemoryRegion::CreateZygoteMemory(size, &error_msg));
+      CHECK_NE(fd.get(), -1);
+
+      // Protect the memory.
+      bool res = JitMemoryRegion::ProtectZygoteMemory(fd.get(), &error_msg);
+      CHECK(res);
+
+      // Create a shared readable mapping.
+      addr = reinterpret_cast<int32_t*>(
+          mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, fd.get(), 0));
+      CHECK(addr != nullptr);
+      CHECK_NE(addr, MAP_FAILED);
+    }
+    // At this point, the fd has been dropped, but the memory mappings are still
+    // there.
+    int res = mprotect(addr, kPageSize, PROT_WRITE);
+    CHECK_EQ(res, -1);
+    CHECK_EQ(errno, EACCES);
+  }
 };
 
 TEST_F(TestZygoteMemory, BasicTest) {
@@ -510,6 +566,14 @@
   TestFromSharedToPrivate();
 }
 
+TEST_F(TestZygoteMemory, TestVmMayWriteBefore) {
+  TestVmMayWriteBefore();
+}
+
+TEST_F(TestZygoteMemory, TestVmMayWriteAfter) {
+  TestVmMayWriteAfter();
+}
+
 #endif  // defined (__BIONIC__)
 
 }  // namespace jit
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 425eadc..b86badc 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -189,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 = options_.GetMinSavePeriodMs();
+      uint64_t min_save_period_ns = MsToNs(options_.GetMinSavePeriodMs());
       while (min_save_period_ns * 0.9 > sleep_time) {
         {
           MutexLock mu(self, wait_lock_);
diff --git a/runtime/monitor_android.cc b/runtime/monitor_android.cc
index 19e1f3d..f661631 100644
--- a/runtime/monitor_android.cc
+++ b/runtime/monitor_android.cc
@@ -24,6 +24,8 @@
 #include <log/log_event_list.h>
 
 #include "art_method.h"
+#include "jni/jni_env_ext.h"
+#include "palette/palette.h"
 #include "thread.h"
 
 #define EVENT_LOG_TAG_dvm_lock_sample 20003
@@ -41,14 +43,13 @@
   int32_t owner_line_number;
   TranslateLocation(owner_method, owner_dex_pc, &owner_filename, &owner_line_number);
 
-  // Emit the process name, <= 37 bytes.
+  // Emit the process name, <= 33 bytes.
+  char proc_name[33] = {};
   {
     int fd = open("/proc/self/cmdline", O_RDONLY  | O_CLOEXEC);
-    char procName[33];
-    memset(procName, 0, sizeof(procName));
-    read(fd, procName, sizeof(procName) - 1);
+    read(fd, proc_name, sizeof(proc_name) - 1);
     close(fd);
-    ctx << procName;
+    ctx << proc_name;
   }
 
   // Emit the sensitive thread ("main thread") status. We follow tradition that this corresponds
@@ -58,20 +59,19 @@
   ctx << (Thread::IsSensitiveThread() ? kIsSensitive : kIsNotSensitive);
 
   // Emit self thread name string.
-  {
-    std::string thread_name;
-    self->GetThreadName(thread_name);
-    ctx << thread_name;
-  }
+  std::string thread_name;
+  self->GetThreadName(thread_name);
+  ctx << thread_name;
 
   // Emit the wait time.
   ctx << wait_ms;
 
   const char* filename = nullptr;
+  int32_t line_number;
+  std::string method_name;
   {
     uint32_t pc;
     ArtMethod* m = self->GetCurrentMethod(&pc);
-    int32_t line_number;
     TranslateLocation(m, pc, &filename, &line_number);
 
     // Emit the source code file name.
@@ -81,7 +81,8 @@
     ctx << line_number;
 
     // Emit the method name.
-    ctx << ArtMethod::PrettyMethod(m);
+    method_name = ArtMethod::PrettyMethod(m);
+    ctx << method_name;
   }
 
   // Emit the lock owner source code file name.
@@ -97,12 +98,25 @@
   ctx << owner_line_number;
 
   // Emit the owner method name.
-  ctx << ArtMethod::PrettyMethod(owner_method);
+  std::string owner_method_name = ArtMethod::PrettyMethod(owner_method);
+  ctx << owner_method_name;
 
   // Emit the sample percentage.
   ctx << sample_percent;
 
   ctx << LOG_ID_EVENTS;
+
+  // Now report to other interested parties.
+  PaletteReportLockContention(self->GetJniEnv(),
+                              wait_ms,
+                              filename,
+                              line_number,
+                              method_name.c_str(),
+                              owner_filename,
+                              owner_line_number,
+                              owner_method_name.c_str(),
+                              proc_name,
+                              thread_name.c_str());
 }
 
 }  // namespace art
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 9d2dfac..e88516e 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -59,7 +59,6 @@
     ThreadList* thread_list = Runtime::Current()->GetThreadList();
     bool timed_out;
     Thread* thread = thread_list->SuspendThreadByPeer(peer,
-                                                      /* request_suspension= */ true,
                                                       SuspendReason::kInternal,
                                                       &timed_out);
     if (thread != nullptr) {
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index 37b3fe6..c3b4fe0 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -148,7 +148,6 @@
   bool timed_out;
   // Take suspend thread lock to avoid races with threads trying to suspend this one.
   Thread* thread = thread_list->SuspendThreadByPeer(peer,
-                                                    /* request_suspension= */ true,
                                                     SuspendReason::kInternal,
                                                     &timed_out);
   if (thread != nullptr) {
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 8f653c2..14e7a1b 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -168,7 +168,7 @@
 
   bool Setup(int zip_fd, ArrayRef<const std::string> dex_filenames, std::string* error_msg);
 
-  void Setup(const std::vector<const DexFile*>& dex_files);
+  bool Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg);
 
   // Setters exposed for ElfOatFile.
 
@@ -476,18 +476,71 @@
   return true;
 }
 
-void OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) {
+static bool ComputeAndCheckTypeLookupTableData(const DexFile::Header& header,
+                                               const uint8_t* type_lookup_table_start,
+                                               const VdexFile* vdex_file,
+                                               const uint8_t** type_lookup_table_data,
+                                               std::string* error_msg) {
+  if (type_lookup_table_start == nullptr ||
+      reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0] == 0) {
+    *type_lookup_table_data = nullptr;
+    return true;
+  }
+
+  *type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
+  size_t expected_table_size = TypeLookupTable::RawDataLength(header.class_defs_size_);
+  size_t found_size = reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0];
+  if (UNLIKELY(found_size != expected_table_size)) {
+    *error_msg =
+        StringPrintf("In vdex file '%s' unexpected type lookup table size: found %zu, expected %zu",
+                     vdex_file->GetName().c_str(),
+                     found_size,
+                     expected_table_size);
+    return false;
+  }
+  if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data))) {
+    *error_msg =
+        StringPrintf("In vdex file '%s' found invalid type lookup table pointer %p not in [%p, %p]",
+                     vdex_file->GetName().c_str(),
+                     type_lookup_table_data,
+                     vdex_file->Begin(),
+                     vdex_file->End());
+    return false;
+  }
+  if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data + expected_table_size - 1))) {
+    *error_msg =
+        StringPrintf("In vdex file '%s' found overflowing type lookup table %p not in [%p, %p]",
+                     vdex_file->GetName().c_str(),
+                     type_lookup_table_data + expected_table_size,
+                     vdex_file->Begin(),
+                     vdex_file->End());
+    return false;
+  }
+  if (UNLIKELY(!IsAligned<4>(type_lookup_table_start))) {
+    *error_msg =
+        StringPrintf("In vdex file '%s' found invalid type lookup table alignment %p",
+                     vdex_file->GetName().c_str(),
+                     type_lookup_table_start);
+    return false;
+  }
+  return true;
+}
+
+bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg) {
   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());
 
+    type_lookup_table_start = vdex_->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);
+    if (!ComputeAndCheckTypeLookupTableData(dex_file->GetHeader(),
+                                            type_lookup_table_start,
+                                            vdex_.get(),
+                                            &type_lookup_table_data,
+                                            error_msg)) {
+      return false;
     }
     // Create an OatDexFile and add it to the owning container.
     OatDexFile* oat_dex_file = new OatDexFile(
@@ -497,7 +550,6 @@
         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.
@@ -508,6 +560,11 @@
       oat_dex_files_.Put(canonical_key, oat_dex_file);
     }
   }
+  // Now that we've created all the OatDexFile, update the dex files.
+  for (i = 0; i < dex_files.size(); ++i) {
+    dex_files[i]->SetOatDexFile(oat_dex_files_storage_[i]);
+  }
+  return true;
 }
 
 bool OatFileBase::Setup(int zip_fd,
@@ -1583,7 +1640,11 @@
     oat_file->SetVdex(vdex_file.release());
     oat_file->SetupHeader(dex_files.size());
     // Initialize OatDexFiles.
-    oat_file->Setup(dex_files);
+    std::string error_msg;
+    if (!oat_file->Setup(dex_files, &error_msg)) {
+      LOG(WARNING) << "Could not create in-memory vdex file: " << error_msg;
+      return nullptr;
+    }
     return oat_file.release();
   }
 
@@ -1601,6 +1662,25 @@
       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)) {
+        const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_start);
+        if (UNLIKELY(!vdex_file->Contains(dex_file_start))) {
+          *error_msg =
+              StringPrintf("In vdex file '%s' found invalid dex file pointer %p not in [%p, %p]",
+                           dex_location.c_str(),
+                           dex_file_start,
+                           vdex_file->Begin(),
+                           vdex_file->End());
+          return nullptr;
+        }
+        if (UNLIKELY(!vdex_file->Contains(dex_file_start + header->file_size_ - 1))) {
+          *error_msg =
+              StringPrintf("In vdex file '%s' found overflowing dex file %p not in [%p, %p]",
+                           dex_location.c_str(),
+                           dex_file_start + header->file_size_,
+                           vdex_file->Begin(),
+                           vdex_file->End());
+          return nullptr;
+        }
         if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
           *error_msg =
               StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
@@ -1612,10 +1692,14 @@
         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);
+        if (!ComputeAndCheckTypeLookupTableData(*header,
+                                                type_lookup_table_start,
+                                                vdex_file,
+                                                &type_lookup_table_data,
+                                                error_msg)) {
+          return nullptr;
         }
+
         OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
                                                   dex_file_start,
                                                   vdex_file->GetLocationChecksum(i),
@@ -1656,7 +1740,9 @@
         return nullptr;
       }
       oat_file->SetupHeader(oat_file->external_dex_files_.size());
-      oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_));
+      if (!oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_), error_msg)) {
+        return nullptr;
+      }
     }
 
     return oat_file.release();
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 433f564..6c99c1f 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -410,7 +410,7 @@
     while (threads_being_born_ > 0) {
       shutdown_cond_->Wait(self);
     }
-    shutting_down_ = true;
+    SetShuttingDown();
   }
   // Shutdown and wait for the daemons.
   CHECK(self != nullptr);
@@ -641,7 +641,7 @@
   // May be coming from an unattached thread.
   if (Thread::Current() == nullptr) {
     Runtime* current = Runtime::Current();
-    if (current != nullptr && current->IsStarted() && !current->IsShuttingDown(nullptr)) {
+    if (current != nullptr && current->IsStarted() && !current->IsShuttingDownUnsafe()) {
       // We do not flag this to the unexpected-signal handler so that that may dump the stack.
       abort();
       UNREACHABLE();
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 68456cd..b2093a3 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -222,7 +222,13 @@
 
   bool IsShuttingDown(Thread* self);
   bool IsShuttingDownLocked() const REQUIRES(Locks::runtime_shutdown_lock_) {
-    return shutting_down_;
+    return shutting_down_.load(std::memory_order_relaxed);
+  }
+  bool IsShuttingDownUnsafe() const {
+    return shutting_down_.load(std::memory_order_relaxed);
+  }
+  void SetShuttingDown() REQUIRES(Locks::runtime_shutdown_lock_) {
+    shutting_down_.store(true, std::memory_order_relaxed);
   }
 
   size_t NumberOfThreadsBeingBorn() const REQUIRES(Locks::runtime_shutdown_lock_) {
@@ -1190,8 +1196,10 @@
   // Waited upon until no threads are being born.
   std::unique_ptr<ConditionVariable> shutdown_cond_ GUARDED_BY(Locks::runtime_shutdown_lock_);
 
-  // Set when runtime shutdown is past the point that new threads may attach.
-  bool shutting_down_ GUARDED_BY(Locks::runtime_shutdown_lock_);
+  // Set when runtime shutdown is past the point that new threads may attach.  Usually
+  // GUARDED_BY(Locks::runtime_shutdown_lock_). But we need to check it in Abort without the
+  // lock, because we may already own it.
+  std::atomic<bool> shutting_down_;
 
   // The runtime is starting to shutdown but is blocked waiting on shutdown_cond_.
   bool shutting_down_started_ GUARDED_BY(Locks::runtime_shutdown_lock_);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 46aa2b5..16a5f93 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -4468,6 +4468,12 @@
       WellKnownClasses::java_lang_Thread_systemDaemon)->GetBoolean(GetPeer());
 }
 
+std::string Thread::StateAndFlagsAsHexString() const {
+  std::stringstream result_stream;
+  result_stream << std::hex << tls32_.state_and_flags.as_atomic_int.load();
+  return result_stream.str();
+}
+
 ScopedExceptionStorage::ScopedExceptionStorage(art::Thread* self)
     : self_(self), hs_(self_), excp_(hs_.NewHandle<art::mirror::Throwable>(self_->GetException())) {
   self_->ClearException();
diff --git a/runtime/thread.h b/runtime/thread.h
index 7a40802..676bfd8 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -254,7 +254,7 @@
 
   bool IsSuspended() const {
     union StateAndFlags state_and_flags;
-    state_and_flags.as_int = tls32_.state_and_flags.as_int;
+    state_and_flags.as_int = tls32_.state_and_flags.as_atomic_int.load(std::memory_order_relaxed);
     return state_and_flags.as_struct.state != kRunnable &&
         (state_and_flags.as_struct.flags & kSuspendRequest) != 0;
   }
@@ -1517,6 +1517,9 @@
   };
   static_assert(sizeof(StateAndFlags) == sizeof(int32_t), "Weird state_and_flags size");
 
+  // Format state and flags as a hex string. For diagnostic output.
+  std::string StateAndFlagsAsHexString() const;
+
   static void ThreadExitCallback(void* arg);
 
   // Maximum number of suspend barriers.
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index f8e99e8..84b7384 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -874,10 +874,11 @@
 }
 
 Thread* ThreadList::SuspendThreadByPeer(jobject peer,
-                                        bool request_suspension,
                                         SuspendReason reason,
                                         bool* timed_out) {
+  bool request_suspension = true;
   const uint64_t start_time = NanoTime();
+  int self_suspend_count = 0;
   useconds_t sleep_us = kThreadSuspendInitialSleepUs;
   *timed_out = false;
   Thread* const self = Thread::Current();
@@ -926,6 +927,7 @@
             // We hold the suspend count lock but another thread is trying to suspend us. Its not
             // safe to try to suspend another thread in case we get a cycle. Start the loop again
             // which will allow this thread to be suspended.
+            ++self_suspend_count;
             continue;
           }
           CHECK(suspended_thread == nullptr);
@@ -957,20 +959,22 @@
         }
         const uint64_t total_delay = NanoTime() - start_time;
         if (total_delay >= thread_suspend_timeout_ns_) {
-          ThreadSuspendByPeerWarning(self,
-                                     ::android::base::FATAL,
-                                     "Thread suspension timed out",
-                                     peer);
-          if (suspended_thread != nullptr) {
+          if (suspended_thread == nullptr) {
+            ThreadSuspendByPeerWarning(self,
+                                       ::android::base::FATAL,
+                                       "Failed to issue suspend request",
+                                       peer);
+          } else {
             CHECK_EQ(suspended_thread, thread);
-            bool updated = suspended_thread->ModifySuspendCount(soa.Self(),
-                                                                -1,
-                                                                nullptr,
-                                                                reason);
-            DCHECK(updated);
+            LOG(WARNING) << "Suspended thread state_and_flags: "
+                         << suspended_thread->StateAndFlagsAsHexString()
+                         << ", self_suspend_count = " << self_suspend_count;
+            ThreadSuspendByPeerWarning(self,
+                                       ::android::base::FATAL,
+                                       "Thread suspension timed out",
+                                       peer);
           }
-          *timed_out = true;
-          return nullptr;
+          UNREACHABLE();
         } else if (sleep_us == 0 &&
             total_delay > static_cast<uint64_t>(kThreadSuspendMaxYieldUs) * 1000) {
           // We have spun for kThreadSuspendMaxYieldUs time, switch to sleeps to prevent
diff --git a/runtime/thread_list.h b/runtime/thread_list.h
index 87a4c8d..f5b58a0 100644
--- a/runtime/thread_list.h
+++ b/runtime/thread_list.h
@@ -81,11 +81,8 @@
 
   // Suspend a thread using a peer, typically used by the debugger. Returns the thread on success,
   // else null. The peer is used to identify the thread to avoid races with the thread terminating.
-  // If the thread should be suspended then value of request_suspension should be true otherwise
-  // the routine will wait for a previous suspend request. If the suspension times out then *timeout
-  // is set to true.
+  // If the suspension times out then *timeout is set to true.
   Thread* SuspendThreadByPeer(jobject peer,
-                              bool request_suspension,
                               SuspendReason reason,
                               bool* timed_out)
       REQUIRES(!Locks::mutator_lock_,
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 29efd40..9671679 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -192,7 +192,8 @@
   } 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);
+    // We don't check this here to be defensive against corrupted vdex files.
+    // Callers should check the returned value matches their expectations.
     return data;
   }
 }
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index eb8b817..a66ff88 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -157,8 +157,6 @@
     return size;
   }
 
-  bool IsDexSectionValid() const;
-
   bool HasDexSection() const {
     return GetSectionHeader(VdexSection::kDexFileSection).section_size != 0u;
   }
@@ -251,6 +249,9 @@
   const uint8_t* Begin() const { return mmap_.Begin(); }
   const uint8_t* End() const { return mmap_.End(); }
   size_t Size() const { return mmap_.Size(); }
+  bool Contains(const uint8_t* pointer) const {
+    return pointer >= Begin() && pointer < End();
+  }
 
   const VdexFileHeader& GetVdexFileHeader() const {
     return *reinterpret_cast<const VdexFileHeader*>(Begin());
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index 1935d45..8aa4760 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -405,7 +405,7 @@
     if (handler == SIG_IGN) {
       return;
     } else if (handler == SIG_DFL) {
-      fatal("exiting due to SIG_DFL handler for signal %d", signo);
+      fatal("exiting due to SIG_DFL handler for signal %d, ucontext %p", signo, ucontext);
     } else {
       handler(signo);
     }
diff --git a/test/2011-stack-walk-concurrent-instrument/stack_walk_concurrent.cc b/test/2011-stack-walk-concurrent-instrument/stack_walk_concurrent.cc
index a185446..a10fe2e 100644
--- a/test/2011-stack-walk-concurrent-instrument/stack_walk_concurrent.cc
+++ b/test/2011-stack-walk-concurrent-instrument/stack_walk_concurrent.cc
@@ -81,7 +81,7 @@
   }
   bool timed_out = false;
   Thread* other = Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
-      target, true, SuspendReason::kInternal, &timed_out);
+      target, SuspendReason::kInternal, &timed_out);
   CHECK(!timed_out);
   CHECK(other != nullptr);
   ScopedSuspendAll ssa(__FUNCTION__);
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 35f1dc2..a707a8a 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -3964,249 +3964,6 @@
     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) {
@@ -4613,19 +4370,5 @@
     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/639-checker-code-sinking/src/Main.java b/test/639-checker-code-sinking/src/Main.java
index 28fa57c..91c3ec4 100644
--- a/test/639-checker-code-sinking/src/Main.java
+++ b/test/639-checker-code-sinking/src/Main.java
@@ -110,8 +110,6 @@
   /// CHECK: <<Int42:i\d+>>       IntConstant 42
   /// CHECK:                      begin_block
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
-  /// CHECK:                      If
-  /// CHECK:                      begin_block
   /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
   /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
   /// CHECK:                      Throw
@@ -121,14 +119,14 @@
   /// CHECK-NOT:                  NewInstance
   /// CHECK:                      If
   /// CHECK:                      begin_block
+  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
+  /// CHECK-NOT:                  begin_block
   /// 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: <<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>>]
@@ -325,12 +323,7 @@
   /// CHECK: <<Int42:i\d+>>       IntConstant 42
   /// CHECK: <<Int43:i\d+>>       IntConstant 43
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
-  /// 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
@@ -342,14 +335,14 @@
   /// CHECK-NOT:                  NewInstance
   /// CHECK:                      If
   /// CHECK:                      begin_block
+  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
+  /// CHECK-NOT:                  begin_block
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
   /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
   /// CHECK-NOT:                  begin_block
   /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int42>>]
   /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int43>>]
   /// CHECK-NOT:                  begin_block
-  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
-  /// CHECK-NOT:                  begin_block
   /// CHECK:                      NewInstance [<<Error>>]
   /// CHECK:                      Throw
   /// CHECK-NOT:                  InstanceFieldSet
diff --git a/test/826-infinite-loop/expected-stderr.txt b/test/826-infinite-loop/expected-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/826-infinite-loop/expected-stderr.txt
diff --git a/test/826-infinite-loop/expected-stdout.txt b/test/826-infinite-loop/expected-stdout.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/826-infinite-loop/expected-stdout.txt
diff --git a/test/826-infinite-loop/info.txt b/test/826-infinite-loop/info.txt
new file mode 100644
index 0000000..13a89d8
--- /dev/null
+++ b/test/826-infinite-loop/info.txt
@@ -0,0 +1,2 @@
+Regression test for partial escape elimination, which used to crash when
+visiting an infinite loop.
diff --git a/test/826-infinite-loop/src/Main.java b/test/826-infinite-loop/src/Main.java
new file mode 100644
index 0000000..85bcb28
--- /dev/null
+++ b/test/826-infinite-loop/src/Main.java
@@ -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.
+ */
+
+final class Main {
+  public static void main(String[] args) {
+    Object o = new Object();
+    if (args.length == 0) {
+      while (true) {
+        System.out.println(new Object());
+      }
+    }
+  }
+}
diff --git a/test/828-partial-lse/expected-stderr.txt b/test/828-partial-lse/expected-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/828-partial-lse/expected-stderr.txt
diff --git a/test/828-partial-lse/expected-stdout.txt b/test/828-partial-lse/expected-stdout.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/828-partial-lse/expected-stdout.txt
diff --git a/test/828-partial-lse/info.txt b/test/828-partial-lse/info.txt
new file mode 100644
index 0000000..8d28cbd
--- /dev/null
+++ b/test/828-partial-lse/info.txt
@@ -0,0 +1,2 @@
+Regression test for the partial LSE pass, see
+https://issuetracker.google.com/197818595.
diff --git a/test/828-partial-lse/src/Main.java b/test/828-partial-lse/src/Main.java
new file mode 100644
index 0000000..2dde0ef
--- /dev/null
+++ b/test/828-partial-lse/src/Main.java
@@ -0,0 +1,53 @@
+/*
+ * 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 Main {
+
+  public static void $noinline$testMain(Main m) {
+    expectEquals(0, m.myField);
+  }
+
+  public static void main(String[] args) {
+    $noinline$doTest(true);
+    $noinline$doTest(false);
+  }
+
+  public static void $noinline$doTest(boolean testValue) {
+    Main m = new Main();
+    // LSE will find that this store can be removed, as both branches override the value with a new
+    // one.
+    m.myField = 42;
+    if (testValue) {
+      // LSE will remove this store as well, as it's the value after the store of 42 is removed.
+      m.myField = 0;
+      // This makes sure `m` gets materialized. At this point, the bug is that the partial LSE
+      // optimization thinks the value incoming this block for `m.myField` is 42, however that
+      // store, as well as the store to 0, have been removed.
+      $noinline$testMain(m);
+    } else {
+      m.myField = 3;
+      expectEquals(3, m.myField);
+    }
+  }
+
+  public static void expectEquals(int expected, int actual) {
+    if (expected != actual) {
+      throw new Error("Expected " + expected + ", got " + actual);
+    }
+  }
+
+  int myField = 0;
+}
diff --git a/test/831-unverified-bcp/expected-stderr.txt b/test/831-unverified-bcp/expected-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/831-unverified-bcp/expected-stderr.txt
diff --git a/test/831-unverified-bcp/expected-stdout.txt b/test/831-unverified-bcp/expected-stdout.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/831-unverified-bcp/expected-stdout.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/831-unverified-bcp/info.txt b/test/831-unverified-bcp/info.txt
new file mode 100644
index 0000000..b4f7aeb
--- /dev/null
+++ b/test/831-unverified-bcp/info.txt
@@ -0,0 +1,2 @@
+Regression test for class resolution, where the class linker would not check if
+an exception was pending after looking up a class in the boot classpath.
diff --git a/test/831-unverified-bcp/smali-ex/NonVerifiedClass.smali b/test/831-unverified-bcp/smali-ex/NonVerifiedClass.smali
new file mode 100644
index 0000000..986f70a
--- /dev/null
+++ b/test/831-unverified-bcp/smali-ex/NonVerifiedClass.smali
@@ -0,0 +1,23 @@
+# 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 LNonVerifiedClass;
+.super Ljava/util/Objects;
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/util/Objects;-><init>()V
+    return-void
+.end method
+
diff --git a/test/831-unverified-bcp/src/Main.java b/test/831-unverified-bcp/src/Main.java
new file mode 100644
index 0000000..853d8ed
--- /dev/null
+++ b/test/831-unverified-bcp/src/Main.java
@@ -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.
+ */
+
+import dalvik.system.PathClassLoader;
+import java.io.File;
+import java.lang.reflect.Constructor;
+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]);
+    appendToBootClassLoader(OTHER_DEX, /* isCorePlatform */ false);
+
+    try {
+      Class.forName("NonVerifiedClass");
+      throw new Error("Expected VerifyError");
+    } catch (VerifyError e) {
+      // Expected.
+    }
+  }
+
+  private static native int appendToBootClassLoader(String dexPath, boolean isCorePlatform);
+
+  private static final String OTHER_DEX =
+      new File(System.getenv("DEX_LOCATION"), "831-unverified-bcp-ex.jar").getAbsolutePath();
+}
+
+// Define the class also in the classpath, to trigger the AssertNoPendingException crash.
+class NonVerifiedClass {
+}
diff --git a/test/art-gtests-target-chroot.xml b/test/art-gtests-target-chroot.xml
index f274ff1..4768a3f 100644
--- a/test/art-gtests-target-chroot.xml
+++ b/test/art-gtests-target-chroot.xml
@@ -35,4 +35,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/test/art-gtests-target-install-apex.xml b/test/art-gtests-target-install-apex.xml
index 39c46fb..5ca51e8 100644
--- a/test/art-gtests-target-install-apex.xml
+++ b/test/art-gtests-target-install-apex.xml
@@ -36,4 +36,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/test/art-gtests-target-standalone-template.xml b/test/art-gtests-target-standalone-template.xml
index 4b2bdc1..015b60e 100644
--- a/test/art-gtests-target-standalone-template.xml
+++ b/test/art-gtests-target-standalone-template.xml
@@ -17,12 +17,12 @@
 <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="push" value="{MODULE}->/data/local/tmp/{MODULE}/{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="native-test-device-path" value="/data/local/tmp/{MODULE}" />
         <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" />
@@ -36,4 +36,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </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
index 7e7b592..6406626 100644
--- a/test/art-run-test-target-no-test-suite-tag-template.xml
+++ b/test/art-run-test-target-no-test-suite-tag-template.xml
@@ -35,4 +35,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/test/art-run-test-target-template.xml b/test/art-run-test-target-template.xml
index 4084afa..433654a 100644
--- a/test/art-run-test-target-template.xml
+++ b/test/art-run-test-target-template.xml
@@ -38,4 +38,7 @@
         <!-- ART Mainline Module (external (AOSP) version). -->
         <option name="mainline-module-package-name" value="com.android.art" />
     </object>
+
+    <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
 </configuration>
diff --git a/test/knownfailures.json b/test/knownfailures.json
index d9b089d..dc96854 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1142,6 +1142,7 @@
                   "820-vdex-multidex",
                   "821-many-args",
                   "822-hiddenapi-future",
+                  "831-unverified-bcp",
                   "999-redefine-hiddenapi",
                   "1000-non-moving-space-stress",
                   "1001-app-image-regions",