diff options
author | 2022-01-13 17:49:37 +0000 | |
---|---|---|
committer | 2022-01-14 09:03:20 +0000 | |
commit | b0f63c93e44bf53a34dda90c74b8725a932922da (patch) | |
tree | e3a62f7c90ed6aacbec3387558a2e077db91a522 | |
parent | 3ba3a77e4971b1ae411a18debc5e3507885c3b45 (diff) |
Revert "Use InitializeMethodsCode when we need to reinitialize a method entrypoint."
This reverts commit 82e525a4f5f08a72ea1b6907c0a10dacb77a8a87.
Reason for revert: Fails a test
Change-Id: Iab83b543b99fb6f6d5d9be22cd10d4eb88312d4b
-rw-r--r-- | compiler/common_compiler_test.cc | 10 | ||||
-rw-r--r-- | openjdkjvmti/events.cc | 2 | ||||
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 4 | ||||
-rw-r--r-- | runtime/class_linker.cc | 35 | ||||
-rw-r--r-- | runtime/class_linker.h | 4 | ||||
-rw-r--r-- | runtime/common_runtime_test.cc | 2 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 2 | ||||
-rw-r--r-- | runtime/instrumentation.cc | 28 | ||||
-rw-r--r-- | runtime/instrumentation.h | 8 | ||||
-rw-r--r-- | runtime/jit/jit_code_cache.cc | 11 | ||||
-rw-r--r-- | runtime/quick_exception_handler.cc | 5 | ||||
-rw-r--r-- | runtime/runtime.cc | 6 | ||||
-rw-r--r-- | runtime/runtime_callbacks_test.cc | 2 |
13 files changed, 81 insertions, 38 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index bbb2016566..1b69f2a1d4 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -149,18 +149,20 @@ const void* CommonCompilerTestImpl::MakeExecutable(ArrayRef<const uint8_t> code, void CommonCompilerTestImpl::MakeExecutable(ArtMethod* method, const CompiledMethod* compiled_method) { CHECK(method != nullptr); - const void* method_code = nullptr; // If the code size is 0 it means the method was skipped due to profile guided compilation. if (compiled_method != nullptr && compiled_method->GetQuickCode().size() != 0u) { const void* code_ptr = MakeExecutable(compiled_method->GetQuickCode(), compiled_method->GetVmapTable(), compiled_method->GetInstructionSet()); - method_code = + const void* method_code = CompiledMethod::CodePointer(code_ptr, compiled_method->GetInstructionSet()); LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code; + method->SetEntryPointFromQuickCompiledCode(method_code); + } else { + // No code? You must mean to go into the interpreter. + // Or the generic JNI... + GetClassLinker()->SetEntryPointsToInterpreter(method); } - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode( - method, /*aot_code=*/ method_code); } void CommonCompilerTestImpl::SetUp() { diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc index a6425af621..c69ee7b480 100644 --- a/openjdkjvmti/events.cc +++ b/openjdkjvmti/events.cc @@ -1260,7 +1260,7 @@ void EventHandler::HandleLocalAccessCapabilityAdded() { continue; } else if (!runtime_->GetClassLinker()->IsQuickToInterpreterBridge(code) && !runtime_->IsAsyncDeoptimizeable(reinterpret_cast<uintptr_t>(code))) { - runtime_->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr); + runtime_->GetInstrumentation()->UpdateMethodsCodeToInterpreterEntryPoint(&m); } } return true; diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index c234bd42fe..37a61d3c54 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -2116,7 +2116,7 @@ art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassOb } // Finish setting up methods. linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) { - driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(m, /* aot_code= */ nullptr); + linker->SetEntryPointsToInterpreter(m); m->SetNotIntrinsic(); DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get()) << m->PrettyMethod() @@ -2543,7 +2543,7 @@ void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> CHECK(method_id != nullptr); uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id); method.SetDexMethodIndex(dex_method_idx); - driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr); + linker->SetEntryPointsToInterpreter(&method); if (method.HasCodeItem()) { method.SetCodeItem( dex_file_->GetCodeItem(dex_file_->FindCodeItemOffset(class_def, dex_method_idx)), diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 62dd4d2110..d2ab81e7cf 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -201,6 +201,22 @@ static void HandleEarlierErroneousStateError(Thread* self, self->AssertPendingException(); } +static void ChangeInterpreterBridgeToNterp(ArtMethod* method, ClassLinker* class_linker) + REQUIRES_SHARED(Locks::mutator_lock_) { + Runtime* runtime = Runtime::Current(); + if (class_linker->IsQuickToInterpreterBridge(method->GetEntryPointFromQuickCompiledCode()) && + CanMethodUseNterp(method)) { + if (method->GetDeclaringClass()->IsVisiblyInitialized() || + !NeedsClinitCheckBeforeCall(method)) { + runtime->GetInstrumentation()->UpdateMethodsCode(method, interpreter::GetNterpEntryPoint()); + } else { + // Put the resolution stub, which will initialize the class and then + // call the method with nterp. + runtime->GetInstrumentation()->UpdateMethodsCode(method, GetQuickResolutionStub()); + } + } +} + static void UpdateClassAfterVerification(Handle<mirror::Class> klass, PointerSize pointer_size, verifier::FailureKind failure_kind) @@ -215,9 +231,7 @@ static void UpdateClassAfterVerification(Handle<mirror::Class> klass, // to methods that currently use the switch interpreter. if (interpreter::CanRuntimeUseNterp()) { for (ArtMethod& m : klass->GetMethods(pointer_size)) { - if (class_linker->IsQuickToInterpreterBridge(m.GetEntryPointFromQuickCompiledCode())) { - runtime->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/nullptr); - } + ChangeInterpreterBridgeToNterp(&m, class_linker); } } } @@ -1959,11 +1973,10 @@ bool ClassLinker::AddImageSpace( // reset it with the runtime value. method.ResetCounter(hotness_threshold); } + // Set image methods' entry point that point to the interpreter bridge to the + // nterp entry point. if (method.GetEntryPointFromQuickCompiledCode() == nterp_trampoline_) { if (can_use_nterp) { - // Set image methods' entry point that point to the nterp trampoline to the - // nterp entry point. This allows taking the fast path when doing a - // nterp->nterp call. DCHECK(!NeedsClinitCheckBeforeCall(&method) || method.GetDeclaringClass()->IsVisiblyInitialized()); method.SetEntryPointFromQuickCompiledCode(interpreter::GetNterpEntryPoint()); @@ -3340,7 +3353,6 @@ void ClassLinker::FixupStaticTrampolines(Thread* self, ObjPtr<mirror::Class> kla return; } - instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation(); // Link the code of methods skipped by LinkCode. for (size_t method_index = 0; method_index < num_direct_methods; ++method_index) { ArtMethod* method = klass->GetDirectMethod(method_index, pointer_size); @@ -3348,6 +3360,7 @@ void ClassLinker::FixupStaticTrampolines(Thread* self, ObjPtr<mirror::Class> kla // Only update static methods. continue; } + instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation(); instrumentation->UpdateMethodsCode(method, instrumentation->GetCodeForInvoke(method)); } // Ignore virtual methods on the iterator. @@ -9643,6 +9656,14 @@ const void* ClassLinker::GetRuntimeQuickGenericJniStub() const { return GetQuickGenericJniStub(); } +void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const { + if (!method->IsNative()) { + method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()); + } else { + method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub()); + } +} + void ClassLinker::SetEntryPointsForObsoleteMethod(ArtMethod* method) const { DCHECK(method->IsObsolete()); // We cannot mess with the entrypoints of native methods because they are used to determine how diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 7ba62f4e89..b0c02e538e 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -620,6 +620,10 @@ class ClassLinker { return intern_table_; } + // Set the entrypoints up for method to the enter the interpreter. + void SetEntryPointsToInterpreter(ArtMethod* method) const + REQUIRES_SHARED(Locks::mutator_lock_); + // Set the entrypoints up for an obsolete method. void SetEntryPointsForObsoleteMethod(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 6ff4f1a3f8..f949759df2 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -400,7 +400,7 @@ void CommonRuntimeTestImpl::SetUpRuntimeOptionsForFillHeap(RuntimeOptions *optio void CommonRuntimeTestImpl::MakeInterpreted(ObjPtr<mirror::Class> klass) { PointerSize pointer_size = class_linker_->GetImagePointerSize(); for (ArtMethod& method : klass->GetMethods(pointer_size)) { - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr); + class_linker_->SetEntryPointsToInterpreter(&method); } } diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 926d534496..027bda5299 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -1052,7 +1052,7 @@ extern "C" const void* artInstrumentationMethodEntryFromCode(ArtMethod* method, !jit->GetCodeCache()->ContainsPc(result)) << method->PrettyMethod() << " code will jump to possibly cleaned up jit code!"; - bool interpreter_entry = Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(result); + bool interpreter_entry = (result == GetQuickToInterpreterBridge()); bool is_static = method->IsStatic(); uint32_t shorty_len; const char* shorty = diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 65123ffe5a..71d48ee025 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -375,7 +375,7 @@ void Instrumentation::InitializeMethodsCode(ArtMethod* method, const void* aot_c } // Special case if we need an initialization check. - if (NeedsClinitCheckBeforeCall(method) && !method->GetDeclaringClass()->IsVisiblyInitialized()) { + if (NeedsClinitCheckBeforeCall(method)) { // If we have code but the method needs a class initialization check before calling // that code, install the resolution stub that will perform the check. // It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines @@ -397,17 +397,10 @@ void Instrumentation::InitializeMethodsCode(ArtMethod* method, const void* aot_c return; } - // We check if the class is verified as we need the slow interpreter for lock verification. - // If the class is not verified, This will be updated in - // ClassLinker::UpdateClassAfterVerification. - if (interpreter::CanRuntimeUseNterp() && - CanMethodUseNterp(method) && - method->GetDeclaringClass()->IsVerified()) { - UpdateEntryPoints(method, interpreter::GetNterpEntryPoint()); - return; - } - // Use default entrypoints. + // Note we cannot use the nterp entrypoint because we do not know if the + // method will need the slow interpreter for lock verification. This will + // be updated in ClassLinker::UpdateClassAfterVerification. UpdateEntryPoints( method, method->IsNative() ? GetQuickGenericJniStub() : GetQuickToInterpreterBridge()); } @@ -1107,6 +1100,19 @@ void Instrumentation::UpdateMethodsCode(ArtMethod* method, const void* new_code) UpdateMethodsCodeImpl(method, new_code); } +void Instrumentation::UpdateMethodsCodeToInterpreterEntryPoint(ArtMethod* method) { + UpdateMethodsCodeImpl(method, GetQuickToInterpreterBridge()); +} + +void Instrumentation::UpdateMethodsCodeForJavaDebuggable(ArtMethod* method, + const void* new_code) { + // When the runtime is set to Java debuggable, we may update the entry points of + // all methods of a class to the interpreter bridge. A method's declaring class + // might not be in resolved state yet in that case, so we bypass the DCHECK in + // UpdateMethodsCode. + UpdateMethodsCodeImpl(method, new_code); +} + bool Instrumentation::AddDeoptimizedMethod(ArtMethod* method) { if (IsDeoptimizedMethod(method)) { // Already in the map. Return. diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h index d4cb85bbd7..276d1ca2fc 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -312,6 +312,14 @@ class Instrumentation { void UpdateNativeMethodsCodeToJitCode(ArtMethod* method, const void* new_code) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock()); + // Update the code of a method to the interpreter respecting any installed stubs from debugger. + void UpdateMethodsCodeToInterpreterEntryPoint(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock()); + + // Update the code of a method respecting any installed stubs from debugger. + void UpdateMethodsCodeForJavaDebuggable(ArtMethod* method, const void* new_code) + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock()); + // Return the code that we can execute for an invoke including from the JIT. const void* GetCodeForInvoke(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 34ddfc4233..8b91f9eee1 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -793,7 +793,8 @@ bool JitCodeCache::RemoveMethod(ArtMethod* method, bool release_memory) { } ClearMethodCounter(method, /* was_warm= */ false); - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr); + Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( + method, GetQuickToInterpreterBridge()); VLOG(jit) << "JIT removed (osr=" << std::boolalpha << osr << std::noboolalpha << ") " << ArtMethod::PrettyMethod(method) << "@" << method @@ -1317,8 +1318,7 @@ void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) { OatQuickMethodHeader::FromEntryPoint(entry_point); if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr())) { info->GetMethod()->ResetCounter(warmup_threshold); - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode( - info->GetMethod(), /*aot_code=*/ nullptr); + info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()); } } } @@ -1744,7 +1744,7 @@ void JitCodeCache::InvalidateAllCompiledCode() { if (meth->IsObsolete()) { linker->SetEntryPointsForObsoleteMethod(meth); } else { - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(meth, /*aot_code=*/ nullptr); + linker->SetEntryPointsToInterpreter(meth); } } saved_compiled_methods_map_.clear(); @@ -1761,7 +1761,8 @@ void JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method, if (method_entrypoint == header->GetEntryPoint()) { // The entrypoint is the one to invalidate, so we just update it to the interpreter entry point // and clear the counter to get the method Jitted again. - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr); + Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( + method, GetQuickToInterpreterBridge()); ClearMethodCounter(method, /*was_warm=*/ true); } else { MutexLock mu(Thread::Current(), *Locks::jit_lock_); diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index c3722484ca..ac5065b2a6 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -606,8 +606,9 @@ void QuickExceptionHandler::DeoptimizeSingleFrame(DeoptimizationKind kind) { Runtime::Current()->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor( deopt_method, visitor.GetSingleFrameDeoptQuickMethodHeader()); } else { - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode( - deopt_method, /*aot_code=*/ nullptr); + // Transfer the code to interpreter. + Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( + deopt_method, GetQuickToInterpreterBridge()); } PrepareForLongJumpToInvokeStubOrInterpreterBridge(); diff --git a/runtime/runtime.cc b/runtime/runtime.cc index afa8504389..54e9d38b3c 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -3095,21 +3095,21 @@ class UpdateEntryPointsClassVisitor : public ClassVisitor { if (Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) && !m.IsNative() && !m.IsProxyMethod()) { - instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr); + instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge()); } if (Runtime::Current()->GetJit() != nullptr && Runtime::Current()->GetJit()->GetCodeCache()->IsInZygoteExecSpace(code) && !m.IsNative()) { DCHECK(!m.IsProxyMethod()); - instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr); + instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge()); } if (m.IsPreCompiled()) { // Precompilation is incompatible with debuggable, so clear the flag // and update the entrypoint in case it has been compiled. m.ClearPreCompiled(); - instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr); + instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge()); } } return true; diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc index 7f64721a4f..7619750032 100644 --- a/runtime/runtime_callbacks_test.cc +++ b/runtime/runtime_callbacks_test.cc @@ -80,7 +80,7 @@ class RuntimeCallbacksTest : public CommonRuntimeTest { PointerSize pointer_size = class_linker_->GetImagePointerSize(); for (auto& m : klass->GetMethods(pointer_size)) { if (!m.IsAbstract()) { - Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr); + class_linker_->SetEntryPointsToInterpreter(&m); } } } |