summaryrefslogtreecommitdiff
path: root/runtime/instrumentation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/instrumentation.cc')
-rw-r--r--runtime/instrumentation.cc65
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);