diff options
63 files changed, 827 insertions, 605 deletions
diff --git a/compiler/art_standalone_compiler_tests.xml b/compiler/art_standalone_compiler_tests.xml index bf450a52d1..4cf6e3d514 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 6d105668c0..66fdfcda5b 100644 --- a/compiler/optimizing/execution_subgraph.cc +++ b/compiler/optimizing/execution_subgraph.cc @@ -86,12 +86,6 @@ void ExecutionSubgraph::Prune() { 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 @@ void ExecutionSubgraph::Prune() { << "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 e73ef5ef34..6ad2eb2c51 100644 --- a/compiler/optimizing/load_store_elimination.h +++ b/compiler/optimizing/load_store_elimination.h @@ -27,7 +27,7 @@ class LoadStoreElimination : public HOptimization { public: // Whether or not we should attempt partial Load-store-elimination which // requires additional blocks and predicated instructions. - static constexpr bool kEnablePartialLSE = true; + 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 672066ac2e..8f9689afd0 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 ae112d49e9..62cfcd2af6 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 0bb336d45a..3c27dcb9e3 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 71fd39ddb4..75a3878028 100644 --- a/libartpalette/apex/palette.cc +++ b/libartpalette/apex/palette.cc @@ -218,4 +218,28 @@ palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env) { 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 6a7822b1a2..066f24fb54 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 9c846b160b..6401010abe 100644 --- a/libartpalette/libartpalette.map.txt +++ b/libartpalette/libartpalette.map.txt @@ -35,6 +35,7 @@ LIBARTPALETTE_1 { PaletteShouldReportJniInvocations; #apex PaletteNotifyBeginJniInvocation; #apex PaletteNotifyEndJniInvocation; #apex + PaletteReportLockContention; #apex local: *; diff --git a/libartpalette/system/palette_fake.cc b/libartpalette/system/palette_fake.cc index dbbbf89dfa..bbf8f2dd8c 100644 --- a/libartpalette/system/palette_fake.cc +++ b/libartpalette/system/palette_fake.cc @@ -128,3 +128,16 @@ palette_status_t PaletteNotifyBeginJniInvocation(JNIEnv* env ATTRIBUTE_UNUSED) { 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 31cf19711d..47f2e29a58 100644 --- a/libdexfile/Android.bp +++ b/libdexfile/Android.bp @@ -162,6 +162,15 @@ gensrcs { 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 @@ art_cc_test { // 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 57987fd232..d00235a55f 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 5363b00c24..e3027fc95f 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -738,7 +738,7 @@ class DexFile { } // 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 069f2036be..f113668ae2 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 e83d2a27b5..57e91636f0 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 d64086d43c..9b514af452 100644 --- a/openjdkjvm/OpenjdkJvm.cc +++ b/openjdkjvm/OpenjdkJvm.cc @@ -423,7 +423,6 @@ JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring jav 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 bb8fa3b694..a9a6ee8895 100644 --- a/openjdkjvmti/ti_thread.cc +++ b/openjdkjvmti/ti_thread.cc @@ -898,7 +898,6 @@ jvmtiError ThreadUtil::SuspendOther(art::Thread* self, 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 31bee91d5f..1710942259 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 0f6bb4bf23..2bacda1965 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 1267213f20..a46b7b4fb9 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 8b9e42a572..e21a004e33 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2621,6 +2621,26 @@ ClassPathEntry FindInClassPath(const char* descriptor, 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 @@ bool ClassLinker::FindClassInSharedLibraries(ScopedObjectAccessAlreadyRunnable& 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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl /*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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl // - 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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl // - 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; - } - - 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). + 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); + + // 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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl return false; } +#undef RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION + namespace { // Matches exceptions caught in DexFile.defineClass. @@ -2761,36 +2770,38 @@ ALWAYS_INLINE void FilterDexFileCaughtExceptions(Thread* self, ClassLinker* clas // 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); - } - if (result == nullptr) { + *result = DefineClass(self, + descriptor, + hash, + ScopedNullHandle<mirror::ClassLoader>(), + *pair.first, + *pair.second); + } + 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 @@ ObjPtr<mirror::Class> ClassLinker::FindClassInBaseDexClassLoaderClassPath( }; 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, diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 547753a6d6..5faf7602cb 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -1024,20 +1024,26 @@ class ClassLinker { // 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 538d7bef7c..936b9199b5 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -1630,11 +1630,16 @@ void ConcurrentCopying::CopyingPhase() { // 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 @@ class ConcurrentCopying::AssertToSpaceInvariantFieldVisitor { 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; - } - Locks::mutator_lock_->SharedUnlock(self); - { - ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun); - gc_barrier_->Increment(self, barrier_count); + 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_->SharedLock(self); } void ConcurrentCopying::RevokeThreadLocalMarkStack(Thread* thread) { diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index 5ee88718dc..876e12091c 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -1238,7 +1238,8 @@ void Jit::CreateThreadPool() { // 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 58a4041abe..56407f58c0 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, // 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, } } + // 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, // 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, *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 @@ bool JitMemoryRegion::ProtectZygoteMemory(int fd, std::string* error_msg) { 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 20496118db..18f34fb229 100644 --- a/runtime/jit/jit_memory_region_test.cc +++ b/runtime/jit/jit_memory_region_test.cc @@ -492,6 +492,62 @@ class TestZygoteMemory : public testing::Test { 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 @@ TEST_F(TestZygoteMemory, TestFromSharedToPrivate) { 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 425eadca41..b86badcba5 100644 --- a/runtime/jit/profile_saver.cc +++ b/runtime/jit/profile_saver.cc @@ -189,7 +189,7 @@ void ProfileSaver::Run() { // 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 19e1f3d2c4..f661631789 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 @@ void Monitor::LogContentionEvent(Thread* self, 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 @@ void Monitor::LogContentionEvent(Thread* self, 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 @@ void Monitor::LogContentionEvent(Thread* self, 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 @@ void Monitor::LogContentionEvent(Thread* self, 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 9d2dfac069..e88516e248 100644 --- a/runtime/native/dalvik_system_VMStack.cc +++ b/runtime/native/dalvik_system_VMStack.cc @@ -59,7 +59,6 @@ static ResultT GetThreadStack(const ScopedFastNativeObjectAccess& soa, 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 37b3fe642e..c3b4fe09de 100644 --- a/runtime/native/java_lang_Thread.cc +++ b/runtime/native/java_lang_Thread.cc @@ -148,7 +148,6 @@ static void Thread_setNativeName(JNIEnv* env, jobject peer, jstring java_name) { 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.h b/runtime/oat.h index ab45b84888..31a328d979 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,8 +32,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } }; - // Last oat version changed reason: Apex versions in key/value store. - static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '9', '5', '\0' } }; + // Last oat version changed reason: Disable partial LSE b/197818595. + static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '9', '9', '\0' } }; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; static constexpr const char* kDebuggableKey = "debuggable"; diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 8f653c2282..14e7a1b60e 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -168,7 +168,7 @@ class OatFileBase : public OatFile { 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 @@ static bool ReadIndexBssMapping(OatFile* oat_file, 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 @@ void OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) { 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 @@ void OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) { 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 @@ class OatFileBackedByVdex final : public OatFileBase { 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 @@ class OatFileBackedByVdex final : public OatFileBase { 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 @@ class OatFileBackedByVdex final : public OatFileBase { 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 @@ class OatFileBackedByVdex final : public OatFileBase { 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 433f564b2d..6c99c1fa8d 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -410,7 +410,7 @@ Runtime::~Runtime() { 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 @@ void Runtime::Abort(const char* msg) { // 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 68456cd37b..b2093a303c 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -222,7 +222,13 @@ class Runtime { 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 @@ class Runtime { // 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 46aa2b59ad..16a5f93be4 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -4468,6 +4468,12 @@ bool Thread::IsSystemDaemon() const { 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 7a408021c1..676bfd81de 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -254,7 +254,7 @@ class Thread { 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 @@ class Thread { }; 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 f8e99e8f62..84b7384c46 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -874,10 +874,11 @@ static void ThreadSuspendByPeerWarning(Thread* self, } 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 @@ Thread* ThreadList::SuspendThreadByPeer(jobject peer, // 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 @@ Thread* ThreadList::SuspendThreadByPeer(jobject peer, } 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 87a4c8dc61..f5b58a0c54 100644 --- a/runtime/thread_list.h +++ b/runtime/thread_list.h @@ -81,11 +81,8 @@ class ThreadList { // 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 29efd4016f..967167961c 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -192,7 +192,8 @@ const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor, } 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 eb8b81742b..a66ff88fb2 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -157,8 +157,6 @@ class VdexFile { return size; } - bool IsDexSectionValid() const; - bool HasDexSection() const { return GetSectionHeader(VdexSection::kDexFileSection).section_size != 0u; } @@ -251,6 +249,9 @@ class VdexFile { 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 1935d454f8..8aa47600bf 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -405,7 +405,7 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { 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 a185446ca5..a10fe2e905 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 @@ extern "C" JNIEXPORT void JNICALL Java_Main_waitAndDeopt(JNIEnv*, jobject, jobje } 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 35f1dc2ee4..a707a8ae5c 100644 --- a/test/530-checker-lse/src/Main.java +++ b/test/530-checker-lse/src/Main.java @@ -3964,249 +3964,6 @@ public class Main { 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 @@ public class Main { 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 28fa57cfbf..91c3ec48ab 100644 --- a/test/639-checker-code-sinking/src/Main.java +++ b/test/639-checker-code-sinking/src/Main.java @@ -110,8 +110,6 @@ public class Main { /// 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 @@ public class Main { /// 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 @@ public class Main { /// 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 @@ public class Main { /// 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 0000000000..e69de29bb2 --- /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 0000000000..e69de29bb2 --- /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 0000000000..13a89d8ca2 --- /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 0000000000..85bcb28baf --- /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 0000000000..e69de29bb2 --- /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 0000000000..e69de29bb2 --- /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 0000000000..8d28cbdbfa --- /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 0000000000..2dde0eff95 --- /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 0000000000..e69de29bb2 --- /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 0000000000..6a5618ebc6 --- /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 0000000000..b4f7aebcad --- /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 0000000000..986f70a5cf --- /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 0000000000..853d8ed8d2 --- /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 f274ff18f1..4768a3f94e 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 39c46fbc23..5ca51e82fd 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 4b2bdc14c2..015b60ea9d 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 7e7b592aa6..6406626bc0 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 4084afa6c3..433654a9a0 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 d9b089d17a..dc968541cd 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", |