diff options
Diffstat (limited to 'runtime/instrumentation.cc')
| -rw-r--r-- | runtime/instrumentation.cc | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 4ea1130947..f11e2cba10 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -88,11 +88,11 @@ Instrumentation::Instrumentation() } void Instrumentation::InstallStubsForClass(mirror::Class* klass) { - if (klass->IsErroneous()) { - // We can't execute code in a erroneous class: do nothing. - } else if (!klass->IsResolved()) { + if (!klass->IsResolved()) { // We need the class to be resolved to install/uninstall stubs. Otherwise its methods // could not be initialized or linked with regards to class inheritance. + } else if (klass->IsErroneousResolved()) { + // We can't execute code in a erroneous class: do nothing. } else { for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) { InstallStubsForMethod(&method); @@ -105,10 +105,9 @@ static void UpdateEntrypoints(ArtMethod* method, const void* quick_code) method->SetEntryPointFromQuickCompiledCode(quick_code); } -bool Instrumentation::NeedDebugVersionForBootImageCode(ArtMethod* method, const void* code) const - REQUIRES_SHARED(Locks::mutator_lock_) { +bool Instrumentation::NeedDebugVersionFor(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_) { return Dbg::IsDebuggerActive() && - Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) && + Runtime::Current()->IsJavaDebuggable() && !method->IsNative() && !method->IsProxyMethod(); } @@ -132,9 +131,10 @@ void Instrumentation::InstallStubsForMethod(ArtMethod* method) { if ((forced_interpret_only_ || IsDeoptimized(method)) && !method->IsNative()) { new_quick_code = GetQuickToInterpreterBridge(); } else if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) { - new_quick_code = class_linker->GetQuickOatCodeFor(method); - if (NeedDebugVersionForBootImageCode(method, new_quick_code)) { + if (NeedDebugVersionFor(method)) { new_quick_code = GetQuickToInterpreterBridge(); + } else { + new_quick_code = class_linker->GetQuickOatCodeFor(method); } } else { new_quick_code = GetQuickResolutionStub(); @@ -148,13 +148,14 @@ void Instrumentation::InstallStubsForMethod(ArtMethod* method) { // class, all its static methods code will be set to the instrumentation entry point. // For more details, see ClassLinker::FixupStaticTrampolines. if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) { - new_quick_code = class_linker->GetQuickOatCodeFor(method); - if (NeedDebugVersionForBootImageCode(method, new_quick_code)) { + if (NeedDebugVersionFor(method)) { // Oat code should not be used. Don't install instrumentation stub and // use interpreter for instrumentation. new_quick_code = GetQuickToInterpreterBridge(); } else if (entry_exit_stubs_installed_) { new_quick_code = GetQuickInstrumentationEntryPoint(); + } else { + new_quick_code = class_linker->GetQuickOatCodeFor(method); } } else { new_quick_code = GetQuickResolutionStub(); @@ -557,10 +558,8 @@ void Instrumentation::RemoveListener(InstrumentationListener* listener, uint32_t } Instrumentation::InstrumentationLevel Instrumentation::GetCurrentInstrumentationLevel() const { - if (interpreter_stubs_installed_ && interpret_only_) { + if (interpreter_stubs_installed_) { return InstrumentationLevel::kInstrumentWithInterpreter; - } else if (interpreter_stubs_installed_) { - return InstrumentationLevel::kInstrumentWithInterpreterAndJit; } else if (entry_exit_stubs_installed_) { return InstrumentationLevel::kInstrumentWithInstrumentationStubs; } else { @@ -569,11 +568,8 @@ Instrumentation::InstrumentationLevel Instrumentation::GetCurrentInstrumentation } bool Instrumentation::RequiresInstrumentationInstallation(InstrumentationLevel new_level) const { - // We need to reinstall instrumentation if we go to a different level or if the current level is - // kInstrumentWithInterpreterAndJit since that level does not force all code to always use the - // interpreter and so we might have started running optimized code again. - return new_level == InstrumentationLevel::kInstrumentWithInterpreterAndJit || - GetCurrentInstrumentationLevel() != new_level; + // We need to reinstall instrumentation if we go to a different level. + return GetCurrentInstrumentationLevel() != new_level; } void Instrumentation::ConfigureStubs(const char* key, InstrumentationLevel desired_level) { @@ -604,7 +600,7 @@ void Instrumentation::ConfigureStubs(const char* key, InstrumentationLevel desir Locks::mutator_lock_->AssertExclusiveHeld(self); Locks::thread_list_lock_->AssertNotHeld(self); if (requested_level > InstrumentationLevel::kInstrumentNothing) { - if (requested_level >= InstrumentationLevel::kInstrumentWithInterpreterAndJit) { + if (requested_level == InstrumentationLevel::kInstrumentWithInterpreter) { interpreter_stubs_installed_ = true; entry_exit_stubs_installed_ = true; } else { @@ -731,10 +727,12 @@ void Instrumentation::UpdateMethodsCode(ArtMethod* method, const void* quick_cod UpdateMethodsCodeImpl(method, quick_code); } -void Instrumentation::UpdateMethodsCodeFromDebugger(ArtMethod* method, const void* quick_code) { - // When debugger attaches, 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. +void Instrumentation::UpdateMethodsCodeForJavaDebuggable(ArtMethod* method, + const void* quick_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, quick_code); } @@ -819,10 +817,9 @@ void Instrumentation::Undeoptimize(ArtMethod* method) { !method->GetDeclaringClass()->IsInitialized()) { UpdateEntrypoints(method, GetQuickResolutionStub()); } else { - const void* quick_code = class_linker->GetQuickOatCodeFor(method); - if (NeedDebugVersionForBootImageCode(method, quick_code)) { - quick_code = GetQuickToInterpreterBridge(); - } + const void* quick_code = NeedDebugVersionFor(method) + ? GetQuickToInterpreterBridge() + : class_linker->GetQuickOatCodeFor(method); UpdateEntrypoints(method, quick_code); } @@ -879,14 +876,6 @@ bool Instrumentation::ShouldNotifyMethodEnterExitEvents() const { return !deoptimization_enabled_ && !interpreter_stubs_installed_; } -// TODO we don't check deoptimization_enabled_ because currently there isn't really any support for -// multiple users of instrumentation. Since this is just a temporary state anyway pending work to -// ensure that the current_method doesn't get kept across suspend points this should be okay. -// TODO Remove once b/33630159 is resolved. -void Instrumentation::ReJitEverything(const char* key) { - ConfigureStubs(key, InstrumentationLevel::kInstrumentWithInterpreterAndJit); -} - void Instrumentation::DeoptimizeEverything(const char* key) { CHECK(deoptimization_enabled_); ConfigureStubs(key, InstrumentationLevel::kInstrumentWithInterpreter); @@ -1114,7 +1103,7 @@ TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self, uintpt bool deoptimize = (visitor.caller != nullptr) && (interpreter_stubs_installed_ || IsDeoptimized(visitor.caller) || Dbg::IsForcedInterpreterNeededForUpcall(self, visitor.caller)); - if (deoptimize && Runtime::Current()->IsDeoptimizeable(*return_pc)) { + if (deoptimize && Runtime::Current()->IsAsyncDeoptimizeable(*return_pc)) { if (kVerboseInstrumentation) { LOG(INFO) << "Deoptimizing " << visitor.caller->PrettyMethod() @@ -1132,6 +1121,10 @@ TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self, uintpt return GetTwoWordSuccessValue(*return_pc, reinterpret_cast<uintptr_t>(GetQuickDeoptimizationEntryPoint())); } else { + if (deoptimize && !Runtime::Current()->IsAsyncDeoptimizeable(*return_pc)) { + LOG(WARNING) << "Got a deoptimization request on un-deoptimizable " << method->PrettyMethod() + << " at PC " << reinterpret_cast<void*>(*return_pc); + } if (kVerboseInstrumentation) { LOG(INFO) << "Returning from " << method->PrettyMethod() << " to PC " << reinterpret_cast<void*>(*return_pc); |