Delay entrypoint update until visibly initialized.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing --jit
Test: aosp_taimen-userdebug boots.
Test: run-gtests.sh
Test: testrunner.py --target --optimizing --jit
Bug: 18161648
Change-Id: Idde0cbc848f19236319426bc82ac10b8b8bb9ee9
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index ff23385..e1db1f6 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -119,6 +119,21 @@
code_ = code;
}
+ void UpdateEntryPoints(const void* entrypoint) REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(IsCompiled());
+ DCHECK(entrypoint == OatQuickMethodHeader::FromCodePointer(GetCode())->GetEntryPoint());
+ instrumentation::Instrumentation* instrum = Runtime::Current()->GetInstrumentation();
+ for (ArtMethod* m : GetMethods()) {
+ // Because `m` might be in the process of being deleted:
+ // - Call the dedicated method instead of the more generic UpdateMethodsCode
+ // - Check the class status without a read barrier.
+ // TODO: Use ReadBarrier::IsMarked() if not null to check the class status.
+ if (!m->NeedsInitializationCheck<kWithoutReadBarrier>()) {
+ instrum->UpdateNativeMethodsCodeToJitCode(m, entrypoint);
+ }
+ }
+ }
+
const void* GetCode() const {
return code_;
}
@@ -705,15 +720,7 @@
DCHECK(ContainsElement(data->GetMethods(), method))
<< "Entry inserted in NotifyCompilationOf() should contain this method.";
data->SetCode(code_ptr);
- instrumentation::Instrumentation* instrum = Runtime::Current()->GetInstrumentation();
- for (ArtMethod* m : data->GetMethods()) {
- // Because `m` might be in the process of being deleted:
- // - Call the dedicated method instead of the more generic UpdateMethodsCode
- // - Check the class status without a read barrier.
- if (!m->NeedsInitializationCheck<kWithoutReadBarrier>()) {
- instrum->UpdateNativeMethodsCodeToJitCode(m, method_header->GetEntryPoint());
- }
- }
+ data->UpdateEntryPoints(method_header->GetEntryPoint());
} else {
if (method->IsPreCompiled() && IsSharedRegion(*region)) {
zygote_map_.Put(code_ptr, method);
@@ -1555,6 +1562,12 @@
if (method->NeedsInitializationCheck() && !prejit) {
// Unless we're pre-jitting, we currently don't save the JIT compiled code if we cannot
// update the entrypoint due to needing an initialization check.
+ if (method->GetDeclaringClass()->IsInitialized()) {
+ // Request visible initialization but do not block to allow compiling other methods.
+ // Hopefully, this will complete by the time the method becomes hot again.
+ Runtime::Current()->GetClassLinker()->MakeInitializedClassesVisiblyInitialized(
+ self, /*wait=*/ false);
+ }
VLOG(jit) << "Not compiling "
<< method->PrettyMethod()
<< " because it has the resolution stub";
@@ -1587,15 +1600,7 @@
// changed these entrypoints to GenericJNI in preparation for a full GC, we may
// as well change them back as this stub shall not be collected anyway and this
// can avoid a few expensive GenericJNI calls.
- instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
- for (ArtMethod* m : data->GetMethods()) {
- // Because `m` might be in the process of being deleted:
- // - Call the dedicated method instead of the more generic UpdateMethodsCode
- // - Check the class status without a read barrier.
- if (!m->NeedsInitializationCheck<kWithoutReadBarrier>()) {
- instrumentation->UpdateNativeMethodsCodeToJitCode(m, entrypoint);
- }
- }
+ data->UpdateEntryPoints(entrypoint);
if (collection_in_progress_) {
if (!IsInZygoteExecSpace(data->GetCode())) {
GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(data->GetCode()));