Fix ClearEntryPointsInZygoteExecSpace.
Methods allocated in the shared region now don't have a profiling
info.
Also move test 689-zygote-jit-deopt to now use proper ZygoteHooks APIs
to fork from zygote, and have non-bionic build create a shared region.
Test: 689-zygote-jit-deopt
Bug: 119800099
Change-Id: I400618673a0b5b2ba7389e46d692ea6a58dbeea8
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 8f4d0d4..960018c 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -917,19 +917,11 @@
void JitCodeCache::ClearEntryPointsInZygoteExecSpace() {
MutexLock mu(Thread::Current(), *Locks::jit_lock_);
- // Iterate over profiling infos to know which methods may have been JITted. Note that
- // to be JITted, a method must have a profiling info.
- for (ProfilingInfo* info : profiling_infos_) {
- ArtMethod* method = info->GetMethod();
+ for (const auto& it : method_code_map_) {
+ ArtMethod* method = it.second;
if (IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode())) {
method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
}
- // If zygote does method tracing, or in some configuration where
- // the JIT zygote does GC, we also need to clear the saved entry point
- // in the profiling info.
- if (IsInZygoteExecSpace(info->GetSavedEntryPoint())) {
- info->SetSavedEntryPoint(nullptr);
- }
}
}
@@ -1742,13 +1734,6 @@
return;
}
- if (private_region_.IsValid()) {
- // In case the zygote was running with its own private region (happens for
- // unit tests), move the region to the shared one.
- CHECK(!shared_region_.IsValid());
- std::swap(shared_region_, private_region_);
- }
-
// Reset all statistics to be specific to this process.
number_of_compilations_ = 0;
number_of_osr_compilations_ = 0;
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc
index 9092695..d2d8f7c 100644
--- a/runtime/jit/jit_memory_region.cc
+++ b/runtime/jit/jit_memory_region.cc
@@ -546,10 +546,24 @@
#else
-// When running on non-bionic configuration, this is not supported.
-int JitMemoryRegion::CreateZygoteMemory(size_t capacity ATTRIBUTE_UNUSED,
- std::string* error_msg ATTRIBUTE_UNUSED) {
- return -1;
+int JitMemoryRegion::CreateZygoteMemory(size_t capacity, std::string* error_msg) {
+ // To simplify host building, we don't rely on the latest memfd features.
+ LOG(WARNING) << "Returning un-sealable region on non-bionic";
+ static const char* kRegionName = "/jit-zygote-cache";
+ int fd = art::memfd_create(kRegionName, 0);
+ if (fd == -1) {
+ std::ostringstream oss;
+ oss << "Failed to create zygote mapping: " << strerror(errno);
+ *error_msg = oss.str();
+ return -1;
+ }
+ if (ftruncate(fd, capacity) != 0) {
+ std::ostringstream oss;
+ oss << "Failed to create zygote mapping: " << strerror(errno);
+ *error_msg = oss.str();
+ return -1;
+ }
+ return fd;
}
bool JitMemoryRegion::ProtectZygoteMemory(int fd ATTRIBUTE_UNUSED,
diff --git a/test/689-zygote-jit-deopt/run b/test/689-zygote-jit-deopt/run
new file mode 100644
index 0000000..7b4b7eb
--- /dev/null
+++ b/test/689-zygote-jit-deopt/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+./default-run "$@" --zygote
diff --git a/test/689-zygote-jit-deopt/src/Main.java b/test/689-zygote-jit-deopt/src/Main.java
index 330663e..fbdc728 100644
--- a/test/689-zygote-jit-deopt/src/Main.java
+++ b/test/689-zygote-jit-deopt/src/Main.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import dalvik.system.ZygoteHooks;
+
public class Main {
public static void main(String[] args) {
System.loadLibrary(args[0]);
@@ -21,7 +23,10 @@
return;
}
ensureJitCompiled(Object.class, "toString");
- transitionJitFromZygote();
+ ZygoteHooks.preFork();
+ ZygoteHooks.postForkChild(
+ /*flags=*/0, /*is_system_server=*/false, /*is_zygote=*/false, /*instruction_set=*/null);
+ ZygoteHooks.postForkCommon();
deoptimizeBootImage();
if (hasJitCompiledEntrypoint(Object.class, "toString")) {
throw new Error("Expected Object.toString to be deoptimized");
@@ -32,5 +37,4 @@
private static native void ensureJitCompiled(Class<?> cls, String name);
private static native boolean hasJitCompiledEntrypoint(Class<?> cls, String name);
private static native void deoptimizeBootImage();
- private static native void transitionJitFromZygote();
}
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 7b023de..88d7a9f 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -241,7 +241,7 @@
// Sleep to yield to the compiler thread.
usleep(1000);
ScopedObjectAccess soa(self);
- if (!native) {
+ if (!native && jit->GetCodeCache()->CanAllocateProfilingInfo()) {
// Make sure there is a profiling info, required by the compiler.
ProfilingInfo::Create(self, method, /* retry_allocation */ true);
}
@@ -365,17 +365,6 @@
return (jit != nullptr) ? jit->HotMethodThreshold() : 0;
}
-extern "C" JNIEXPORT void JNICALL Java_Main_transitionJitFromZygote(JNIEnv*, jclass) {
- jit::Jit* jit = Runtime::Current()->GetJit();
- if (jit == nullptr) {
- return;
- }
- // Mimic the transition behavior a zygote fork would have.
- jit->PreZygoteFork();
- jit->GetCodeCache()->PostForkChildAction(/*is_system_server=*/ false, /*is_zygote=*/ false);
- jit->PostForkChildAction(/*is_system_server=*/ false, /*is_zygote=*/ false);
-}
-
extern "C" JNIEXPORT void JNICALL Java_Main_deoptimizeBootImage(JNIEnv*, jclass) {
ScopedSuspendAll ssa(__FUNCTION__);
Runtime::Current()->DeoptimizeBootImage();