summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-11-17 15:57:28 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-11-17 16:14:05 +0000
commit786b0d588ae72cefea69731c517c8c446a5e5d19 (patch)
treea0f8322798dce8f92a9298340a606bdd257df81f
parentc46296ca738801d1e7bbfcffb7873ed72ef80e10 (diff)
parent3cb3670d162285c6e4304f1f9f85f7c3ff78150d (diff)
downloadart-android12-mainline-art-release.tar.gz
Make change and version bump to aml_art_311310000 for mainline module file: build/apex/manifest-art.jsonandroid-mainline-12.0.0_r42android12-mainline-art-release
Change-Id: I74e9ef32d76376ff9640c7876c1805bdd0b90dfc
-rw-r--r--build/Android.bp4
-rw-r--r--build/apex/Android.bp2
-rw-r--r--build/apex/manifest-art.json2
-rw-r--r--cmdline/Android.bp2
-rw-r--r--compiler/optimizing/code_generator_arm64.cc1
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc1
-rw-r--r--compiler/optimizing/code_generator_x86.cc1
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc1
-rw-r--r--compiler/optimizing/load_store_elimination.cc2
-rw-r--r--compiler/optimizing/load_store_elimination_test.cc6
-rw-r--r--compiler/optimizing/nodes.h13
-rw-r--r--dexoptanalyzer/Android.bp2
-rw-r--r--disassembler/Android.bp2
-rw-r--r--dt_fd_forward/export/Android.bp2
-rw-r--r--libartbase/Android.bp2
-rw-r--r--libdexfile/Android.bp6
-rw-r--r--libnativebridge/Android.bp2
-rw-r--r--libnativeloader/Android.bp2
-rw-r--r--openjdkjvmti/Android.bp2
-rw-r--r--runtime/Android.bp2
-rw-r--r--runtime/jit/jit_memory_region.cc128
-rw-r--r--runtime/jit/jit_memory_region_test.cc64
-rw-r--r--test/099-vmdebug/expected-stdout.txt2
-rw-r--r--test/099-vmdebug/src/Main.java167
-rw-r--r--test/530-checker-lse/src/Main.java2
-rw-r--r--test/832-cha-recursive/expected-stderr.txt0
-rw-r--r--test/832-cha-recursive/expected-stdout.txt1
-rw-r--r--test/832-cha-recursive/info.txt2
-rw-r--r--test/832-cha-recursive/src/Main.java53
-rw-r--r--test/834-lse/expected-stderr.txt0
-rw-r--r--test/834-lse/expected-stdout.txt0
-rw-r--r--test/834-lse/info.txt2
-rw-r--r--test/834-lse/src/Main.java40
-rw-r--r--tools/Android.bp2
-rw-r--r--tools/cpp-define-generator/Android.bp2
35 files changed, 438 insertions, 84 deletions
diff --git a/build/Android.bp b/build/Android.bp
index 21858db130..d4be1e2a09 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -257,7 +257,7 @@ art_module_art_global_defaults {
"-extra-arg=-Wno-unreachable-code",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
// Used to generate binaries that can be backed by transparent hugepages.
@@ -326,7 +326,7 @@ art_debug_defaults {
},
},
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
// Use this to enable a cc_* module only when building ART from sources.
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index c5acc915d4..dfef28df62 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -271,7 +271,7 @@ apex_defaults {
enabled: false,
},
},
- min_sdk_version: "S",
+ min_sdk_version: "31",
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
diff --git a/build/apex/manifest-art.json b/build/apex/manifest-art.json
index 8136f1b2be..f23b9f3769 100644
--- a/build/apex/manifest-art.json
+++ b/build/apex/manifest-art.json
@@ -1,6 +1,6 @@
{
"name": "com.android.art",
- "version": 311214000,
+ "version": 311310000,
"provideNativeLibs": [
"libjdwp.so"
],
diff --git a/cmdline/Android.bp b/cmdline/Android.bp
index fdc762caaa..b68c23cff6 100644
--- a/cmdline/Android.bp
+++ b/cmdline/Android.bp
@@ -33,7 +33,7 @@ cc_library_headers {
"com.android.art.debug",
"com.android.art",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
art_cc_defaults {
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index e1a4718140..92b43fb927 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4636,6 +4636,7 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(
switch (invoke->GetCodePtrLocation()) {
case CodePtrLocation::kCallSelf:
{
+ DCHECK(!GetGraph()->HasShouldDeoptimizeFlag());
// Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
ExactAssemblyScope eas(GetVIXLAssembler(),
kInstructionSize,
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index bca093606d..b24dca9cb2 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -9253,6 +9253,7 @@ void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
switch (invoke->GetCodePtrLocation()) {
case CodePtrLocation::kCallSelf:
{
+ DCHECK(!GetGraph()->HasShouldDeoptimizeFlag());
// Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
ExactAssemblyScope aas(GetVIXLAssembler(),
vixl32::k32BitT32InstructionSizeInBytes,
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 4fc29fcb0c..099d84d9a6 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -5280,6 +5280,7 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(
switch (invoke->GetCodePtrLocation()) {
case CodePtrLocation::kCallSelf:
+ DCHECK(!GetGraph()->HasShouldDeoptimizeFlag());
__ call(GetFrameEntryLabel());
RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
break;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index d54484c065..9541933a2d 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1077,6 +1077,7 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(
switch (invoke->GetCodePtrLocation()) {
case CodePtrLocation::kCallSelf:
+ DCHECK(!GetGraph()->HasShouldDeoptimizeFlag());
__ call(&frame_entry_label_);
RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
break;
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 722cc83872..b7670329e6 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -3889,7 +3889,7 @@ bool LoadStoreElimination::Run(bool enable_partial_lse) {
stats_,
&allocator,
enable_partial_lse ? LoadStoreAnalysisType::kFull
- : LoadStoreAnalysisType::kNoPredicatedInstructions);
+ : LoadStoreAnalysisType::kBasic);
lsa.Run();
const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
if (heap_location_collector.GetNumberOfHeapLocations() == 0) {
diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc
index 812a32aeec..01a00d0c4a 100644
--- a/compiler/optimizing/load_store_elimination_test.cc
+++ b/compiler/optimizing/load_store_elimination_test.cc
@@ -4532,7 +4532,8 @@ TEST_F(LoadStoreEliminationTest, PartialLoadPreserved3) {
// // DO NOT ELIMINATE
// return obj.field;
// EXIT
-TEST_F(LoadStoreEliminationTest, PartialLoadPreserved4) {
+// Disabled due to b/205813546.
+TEST_F(LoadStoreEliminationTest, DISABLED_PartialLoadPreserved4) {
ScopedObjectAccess soa(Thread::Current());
VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
@@ -4724,7 +4725,8 @@ TEST_F(LoadStoreEliminationTest, PartialLoadPreserved5) {
// EXIT
// ELIMINATE
// return obj.field
-TEST_F(LoadStoreEliminationTest, PartialLoadPreserved6) {
+// Disabled due to b/205813546.
+TEST_F(LoadStoreEliminationTest, DISABLED_PartialLoadPreserved6) {
CreateGraph();
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 939c49f9a6..5a62580fac 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4932,7 +4932,18 @@ class HInvokeStaticOrDirect final : public HInvoke {
}
MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
- CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; }
+ CodePtrLocation GetCodePtrLocation() const {
+ // We do CHA analysis after sharpening. When a method has CHA inlining, it
+ // cannot call itself, as if the CHA optmization is invalid we want to make
+ // sure the method is never executed again. So, while sharpening can return
+ // kCallSelf, we bypass it here if there is a CHA optimization.
+ if (dispatch_info_.code_ptr_location == CodePtrLocation::kCallSelf &&
+ GetBlock()->GetGraph()->HasShouldDeoptimizeFlag()) {
+ return CodePtrLocation::kCallArtMethod;
+ } else {
+ return dispatch_info_.code_ptr_location;
+ }
+ }
bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kJitDirectAddress; }
diff --git a/dexoptanalyzer/Android.bp b/dexoptanalyzer/Android.bp
index a66bd290fb..c72ab8a9a2 100644
--- a/dexoptanalyzer/Android.bp
+++ b/dexoptanalyzer/Android.bp
@@ -50,7 +50,7 @@ cc_library_headers {
"com.android.art.debug",
"com.android.art",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
art_cc_binary {
diff --git a/disassembler/Android.bp b/disassembler/Android.bp
index 71ad051927..cafa83d1c2 100644
--- a/disassembler/Android.bp
+++ b/disassembler/Android.bp
@@ -131,5 +131,5 @@ cc_library_headers {
"com.android.art.debug",
"com.android.art",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
diff --git a/dt_fd_forward/export/Android.bp b/dt_fd_forward/export/Android.bp
index a4e96732cb..405e558415 100644
--- a/dt_fd_forward/export/Android.bp
+++ b/dt_fd_forward/export/Android.bp
@@ -33,5 +33,5 @@ cc_library_headers {
"com.android.art.debug",
"com.android.art",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 8bd3bd12aa..3aae1b90fa 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -341,5 +341,5 @@ cc_library_headers {
"com.android.art",
"com.android.art.debug",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 47f2e29a58..658dbc407b 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -333,7 +333,7 @@ cc_library_headers {
"com.android.media",
"com.android.runtime",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
// Make dex_instruction_list.h available for tools/jvmti-agents/titrace
@@ -347,7 +347,7 @@ cc_library_headers {
"com.android.art",
"com.android.art.debug",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
art_cc_test {
@@ -409,7 +409,7 @@ art_cc_library_static {
"com.android.media.swcodec",
"com.android.runtime",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
art_cc_defaults {
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 8e87997b00..9b988e1187 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -32,7 +32,7 @@ cc_library_headers {
"com.android.art.debug",
"com.android.media",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
art_cc_library {
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 3f13506e33..87d21afb97 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -102,7 +102,7 @@ cc_library_headers {
"com.android.art.debug",
"com.android.media",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
visibility: [
"//art:__subpackages__",
// TODO(b/133140750): Clean this up.
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index 841a964657..988d4597b3 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -58,7 +58,7 @@ cc_library_headers {
"com.android.art",
"com.android.art.debug",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
cc_defaults {
diff --git a/runtime/Android.bp b/runtime/Android.bp
index e9343e7315..8d2a321cae 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -888,7 +888,7 @@ cc_library_headers {
"com.android.art",
"com.android.art.debug",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
genrule {
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc
index 1592767f98..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.
}
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/test/099-vmdebug/expected-stdout.txt b/test/099-vmdebug/expected-stdout.txt
index b8d72f66f8..4a1b63dc6c 100644
--- a/test/099-vmdebug/expected-stdout.txt
+++ b/test/099-vmdebug/expected-stdout.txt
@@ -15,8 +15,10 @@ Test tracing with empty filename
Got expected exception
Test tracing with bogus (< 1024 && != 0) filesize
Got expected exception
+Got expected exception
Test sampling with bogus (<= 0) interval
Got expected exception
+Got expected exception
Instances of ClassA 2
Instances of ClassB 1
Instances of null 0
diff --git a/test/099-vmdebug/src/Main.java b/test/099-vmdebug/src/Main.java
index 8fed123852..aa240b6dc2 100644
--- a/test/099-vmdebug/src/Main.java
+++ b/test/099-vmdebug/src/Main.java
@@ -35,6 +35,9 @@ public class Main {
testCountInstances();
testRuntimeStat();
testRuntimeStats();
+ testGetAllocCount();
+ testGetVmFeatureList();
+ testDebuggerDetails();
}
private static File createTempFile() throws Exception {
@@ -117,6 +120,13 @@ public class Main {
System.out.println("Got expected exception");
}
+ try {
+ VMDebug.startMethodTracingDdms(1000, 0, false, 0);
+ System.out.println("Should have thrown an exception");
+ } catch (Exception e) {
+ System.out.println("Got expected exception");
+ }
+
System.out.println("Test sampling with bogus (<= 0) interval");
try {
VMDebug.startMethodTracing(tempFileName, 0, 0, true, 0);
@@ -124,6 +134,12 @@ public class Main {
} catch (Exception e) {
System.out.println("Got expected exception");
}
+ try {
+ VMDebug.startMethodTracingDdms(0, 0, true, 0);
+ System.out.println("Should have thrown an exception");
+ } catch (Exception e) {
+ System.out.println("Got expected exception");
+ }
tempFile.delete();
}
@@ -139,6 +155,18 @@ public class Main {
}
}
+ private static void checkBiggerThanZero(int i) throws Exception {
+ if (i <= 0) {
+ System.out.println("Got zero or smaller " + i);
+ }
+ }
+
+ private static void checkZero(int i) throws Exception {
+ if (i != 0) {
+ System.out.println("Got non-zero result after reset " + i);
+ }
+ }
+
private static void checkHistogram(String s) throws Exception {
if (s == null || s.length() == 0) {
System.out.println("Got null or empty string");
@@ -224,6 +252,67 @@ public class Main {
checkHistogram(blocking_gc_count_rate_histogram);
}
+ /* constants for getAllocCount */
+ private static final int KIND_ALLOCATED_OBJECTS = 1<<0;
+ private static final int KIND_ALLOCATED_BYTES = 1<<1;
+ private static final int KIND_FREED_OBJECTS = 1<<2;
+ private static final int KIND_FREED_BYTES = 1<<3;
+ private static final int RESET_ALL = 0xffffffff;
+
+ private static void testGetAllocCount() throws Exception {
+ VMDebug.startAllocCounting();
+
+ ClassA a1 = new ClassA();
+ Object obj1 = new Object();
+ Runtime.getRuntime().gc();
+
+ int alloc_objects = VMDebug.getAllocCount(KIND_ALLOCATED_OBJECTS);
+ int alloc_bytes = VMDebug.getAllocCount(KIND_ALLOCATED_BYTES);
+ int freed_objects = VMDebug.getAllocCount(KIND_FREED_OBJECTS);
+ int freed_bytes = VMDebug.getAllocCount(KIND_FREED_BYTES);
+ checkBiggerThanZero(alloc_objects);
+ checkBiggerThanZero(alloc_bytes);
+ checkBiggerThanZero(freed_objects);
+ checkBiggerThanZero(freed_bytes);
+
+ VMDebug.stopAllocCounting();
+ VMDebug.resetAllocCount(RESET_ALL);
+ checkZero(VMDebug.getAllocCount(KIND_ALLOCATED_OBJECTS));
+ checkZero(VMDebug.getAllocCount(KIND_ALLOCATED_BYTES));
+ checkZero(VMDebug.getAllocCount(KIND_FREED_OBJECTS));
+ checkZero(VMDebug.getAllocCount(KIND_FREED_BYTES));
+
+ // Even if we create new classes the count should remain 0.
+ ClassA a2 = new ClassA();
+ Object obj2 = new Object();
+
+ checkZero(VMDebug.getAllocCount(KIND_ALLOCATED_OBJECTS));
+ }
+
+ private static void testGetVmFeatureList() throws Exception {
+ String[] feature_list = VMDebug.getVmFeatureList();
+ if (feature_list.length == 0) {
+ System.out.println("Got empty feature list");
+ }
+ }
+
+ private static void testDebuggerDetails() throws Exception {
+ boolean debugger_connected = VMDebug.isDebuggerConnected();
+ boolean debugging_enabled = VMDebug.isDebuggingEnabled();
+ long last_activity = VMDebug.lastDebuggerActivity();
+ if (debugger_connected && last_activity < 0) {
+ System.out.println("Last debugging activity expected but not found");
+ }
+ if (!debugger_connected && last_activity != -1) {
+ System.out.println("Found unexpected last activity");
+ }
+ if (VMDebug.threadCpuTimeNanos() <= 0) {
+ System.out.println("Could not get CPU thread time");
+ }
+ VMDebug.dumpHprofDataDdms();
+ VMDebug.dumpReferenceTables();
+ }
+
static class ClassA { }
static class ClassB { }
static class ClassC extends ClassA { }
@@ -247,6 +336,8 @@ public class Main {
System.out.println("Array counts " + Arrays.toString(counts));
counts = VMDebug.countInstancesofClasses(classes, true);
System.out.println("Array counts assignable " + Arrays.toString(counts));
+ int class_count = VMDebug.getLoadedClassCount();
+ checkBiggerThanZero(class_count);
}
static class ClassD {
@@ -265,17 +356,33 @@ public class Main {
private static class VMDebug {
private static final Method startMethodTracingMethod;
+ private static final Method startMethodTracingDdmsMethod;
private static final Method stopMethodTracingMethod;
private static final Method getMethodTracingModeMethod;
private static final Method getRuntimeStatMethod;
private static final Method getRuntimeStatsMethod;
private static final Method countInstancesOfClassMethod;
private static final Method countInstancesOfClassesMethod;
+ private static final Method getAllocCountMethod;
+ private static final Method startAllocCountingMethod;
+ private static final Method stopAllocCountingMethod;
+ private static final Method setAllocTrackerStackDepthMethod;
+ private static final Method resetAllocCountMethod;
+ private static final Method getLoadedClassCountMethod;
+ private static final Method getVmFeatureListMethod;
+ private static final Method isDebuggerConnectedMethod;
+ private static final Method isDebuggingEnabledMethod;
+ private static final Method lastDebuggerActivityMethod;
+ private static final Method threadCpuTimeNanosMethod;
+ private static final Method dumpHprofDataDdmsMethod;
+ private static final Method dumpReferenceTablesMethod;
static {
try {
Class<?> c = Class.forName("dalvik.system.VMDebug");
startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class,
Integer.TYPE, Integer.TYPE, Boolean.TYPE, Integer.TYPE);
+ startMethodTracingDdmsMethod = c.getDeclaredMethod("startMethodTracingDdms",
+ Integer.TYPE, Integer.TYPE, Boolean.TYPE, Integer.TYPE);
stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing");
getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode");
getRuntimeStatMethod = c.getDeclaredMethod("getRuntimeStat", String.class);
@@ -284,6 +391,22 @@ public class Main {
Class.class, Boolean.TYPE);
countInstancesOfClassesMethod = c.getDeclaredMethod("countInstancesOfClasses",
Class[].class, Boolean.TYPE);
+ getAllocCountMethod = c.getDeclaredMethod("getAllocCount",
+ Integer.TYPE);
+ startAllocCountingMethod = c.getDeclaredMethod("startAllocCounting");
+ stopAllocCountingMethod = c.getDeclaredMethod("stopAllocCounting");
+ setAllocTrackerStackDepthMethod = c.getDeclaredMethod("setAllocTrackerStackDepth",
+ Integer.TYPE);
+ resetAllocCountMethod = c.getDeclaredMethod("resetAllocCount",
+ Integer.TYPE);
+ getLoadedClassCountMethod = c.getDeclaredMethod("getLoadedClassCount");
+ getVmFeatureListMethod = c.getDeclaredMethod("getVmFeatureList");
+ isDebuggerConnectedMethod = c.getDeclaredMethod("isDebuggerConnected");
+ isDebuggingEnabledMethod = c.getDeclaredMethod("isDebuggingEnabled");
+ lastDebuggerActivityMethod = c.getDeclaredMethod("lastDebuggerActivity");
+ threadCpuTimeNanosMethod = c.getDeclaredMethod("threadCpuTimeNanos");
+ dumpHprofDataDdmsMethod = c.getDeclaredMethod("dumpHprofDataDdms");
+ dumpReferenceTablesMethod = c.getDeclaredMethod("dumpReferenceTables");
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -294,6 +417,11 @@ public class Main {
startMethodTracingMethod.invoke(null, filename, bufferSize, flags, samplingEnabled,
intervalUs);
}
+ public static void startMethodTracingDdms(int bufferSize, int flags,
+ boolean samplingEnabled, int intervalUs) throws Exception {
+ startMethodTracingDdmsMethod.invoke(null, bufferSize, flags, samplingEnabled,
+ intervalUs);
+ }
public static void stopMethodTracing() throws Exception {
stopMethodTracingMethod.invoke(null);
}
@@ -314,5 +442,44 @@ public class Main {
return (long[]) countInstancesOfClassesMethod.invoke(
null, new Object[]{classes, assignable});
}
+ public static int getAllocCount(Integer kind) throws Exception {
+ return (int) getAllocCountMethod.invoke(null, kind);
+ }
+ public static void startAllocCounting() throws Exception {
+ startAllocCountingMethod.invoke(null);
+ }
+ public static void stopAllocCounting() throws Exception {
+ stopAllocCountingMethod.invoke(null);
+ }
+ public static void setAllocTrackerStackDepth(Integer stackDepth) throws Exception {
+ setAllocTrackerStackDepthMethod.invoke(null, stackDepth);
+ }
+ public static void resetAllocCount(Integer kind) throws Exception {
+ resetAllocCountMethod.invoke(null, kind);
+ }
+ public static int getLoadedClassCount() throws Exception {
+ return (int) getLoadedClassCountMethod.invoke(null);
+ }
+ public static String[] getVmFeatureList() throws Exception {
+ return (String[]) getVmFeatureListMethod.invoke(null);
+ }
+ public static boolean isDebuggerConnected() throws Exception {
+ return (boolean) isDebuggerConnectedMethod.invoke(null);
+ }
+ public static boolean isDebuggingEnabled() throws Exception {
+ return (boolean) isDebuggingEnabledMethod.invoke(null);
+ }
+ public static long lastDebuggerActivity() throws Exception {
+ return (long) lastDebuggerActivityMethod.invoke(null);
+ }
+ public static long threadCpuTimeNanos() throws Exception {
+ return (long) threadCpuTimeNanosMethod.invoke(null);
+ }
+ public static void dumpHprofDataDdms() throws Exception {
+ dumpHprofDataDdmsMethod.invoke(null);
+ }
+ public static void dumpReferenceTables() throws Exception {
+ dumpReferenceTablesMethod.invoke(null);
+ }
}
}
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index a707a8ae5c..3d97049f2c 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -3942,6 +3942,8 @@ public class Main {
/// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
/// CHECK: InstanceFieldSet
//
+ // TODO: We should be able to remove this setter by realizing `i` only escapes in a branch.
+ /// CHECK: InstanceFieldSet
/// CHECK-NOT: InstanceFieldSet
//
/// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
diff --git a/test/832-cha-recursive/expected-stderr.txt b/test/832-cha-recursive/expected-stderr.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/832-cha-recursive/expected-stderr.txt
diff --git a/test/832-cha-recursive/expected-stdout.txt b/test/832-cha-recursive/expected-stdout.txt
new file mode 100644
index 0000000000..6a5618ebc6
--- /dev/null
+++ b/test/832-cha-recursive/expected-stdout.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/832-cha-recursive/info.txt b/test/832-cha-recursive/info.txt
new file mode 100644
index 0000000000..4913993c63
--- /dev/null
+++ b/test/832-cha-recursive/info.txt
@@ -0,0 +1,2 @@
+Regression test for the optimization compiler which used to have a bug when a
+recursive method was doing CHA inlining.
diff --git a/test/832-cha-recursive/src/Main.java b/test/832-cha-recursive/src/Main.java
new file mode 100644
index 0000000000..ed865a78f1
--- /dev/null
+++ b/test/832-cha-recursive/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.
+ */
+
+public class Main {
+ int mainField = 42;
+
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ ensureJitCompiled(Main.class, "$noinline$callRecursiveMethod");
+ $noinline$callRecursiveMethod(true);
+ }
+
+ public static void expectEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new Error("Expected " + expected + ", got " + actual);
+ }
+ }
+
+ public static void $noinline$callRecursiveMethod(boolean firstEntry) throws Exception {
+ Class<?> cls = Class.forName("LoadedLater");
+ Main m = (Main)cls.newInstance();
+ if (firstEntry) {
+ $noinline$callRecursiveMethod(false);
+ } else {
+ expectEquals(0, m.getField());
+ }
+ }
+
+ public int getField() {
+ return mainField;
+ }
+
+ public static native void ensureJitCompiled(Class<?> cls, String methodName);
+}
+
+class LoadedLater extends Main {
+ public int getField() {
+ return 0;
+ }
+}
diff --git a/test/834-lse/expected-stderr.txt b/test/834-lse/expected-stderr.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/834-lse/expected-stderr.txt
diff --git a/test/834-lse/expected-stdout.txt b/test/834-lse/expected-stdout.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/834-lse/expected-stdout.txt
diff --git a/test/834-lse/info.txt b/test/834-lse/info.txt
new file mode 100644
index 0000000000..8229be934f
--- /dev/null
+++ b/test/834-lse/info.txt
@@ -0,0 +1,2 @@
+Regression test for the load-store-elimination pass, which used to remove stores
+too agressively.
diff --git a/test/834-lse/src/Main.java b/test/834-lse/src/Main.java
new file mode 100644
index 0000000000..65139696bc
--- /dev/null
+++ b/test/834-lse/src/Main.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Main {
+ int myField;
+ static boolean test;
+
+ static void $noinline$assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new Error("Expected " + expected + ", got " + actual);
+ }
+ }
+
+ static void $noinline$empty() {}
+ static void $noinline$escape(Object m) {}
+
+ public static void main(String[] args) {
+ Main m = new Main();
+ if (test) {
+ $noinline$escape(m);
+ } else {
+ m.myField = 42;
+ }
+ $noinline$empty();
+ $noinline$assertEquals(42, m.myField);
+ }
+}
diff --git a/tools/Android.bp b/tools/Android.bp
index 9b9d3a765d..85648e555e 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -122,6 +122,6 @@ python_binary_host {
},
test_suites: [
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tools/cpp-define-generator/Android.bp b/tools/cpp-define-generator/Android.bp
index a436430c16..28d4dc5d0a 100644
--- a/tools/cpp-define-generator/Android.bp
+++ b/tools/cpp-define-generator/Android.bp
@@ -111,7 +111,7 @@ cc_library_headers {
"com.android.art",
"com.android.art.debug",
],
- min_sdk_version: "S",
+ min_sdk_version: "31",
}
python_binary_host {