summaryrefslogtreecommitdiffstats
path: root/runtime/instrumentation.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-03-27 20:06:47 +0100
committerSebastien Hertz <shertz@google.com>2014-04-09 18:23:28 +0200
commit7ec2f1ca3cbd021848da75d5566f7239ce29676f (patch)
treefd2f221e9598fc7fa5066b2a9c746b228ef53faf /runtime/instrumentation.cc
parent2be6fc74bce10ac68d3d1b39a5019f520ad170ea (diff)
downloadart-7ec2f1ca3cbd021848da75d5566f7239ce29676f.zip
art-7ec2f1ca3cbd021848da75d5566f7239ce29676f.tar.gz
art-7ec2f1ca3cbd021848da75d5566f7239ce29676f.tar.bz2
Speed up single-stepping
During single-stepping sequence, we need to deoptimize everything when we register a single-step event and undeoptimize everything when it is done. This causes a slow pattern where we continuously deoptimize-undeoptimize everything for each single-step. This CL introduces a special handling of single-step undeoptimization. We now delay the undeoptimization to the next resume (one thread or all threads) or the end of the debugging session. Indeed, a single-step event registration is always followed by a resume command. At the "resume" point, we know if a single-step event is registered and if we really need to undeoptimize. At the "registration" point, we know we did not undeoptimized everything so we don't need to deoptimize everything again. Therefore, in a sequence of single-steps, we only do a full deoptimization for the first single-step and a full undeoptimization for the last single-step. We update logs at deoptimization points so we can track more precisely. Note they are verbose logs that still must be enabled with -verbose:jdwp option. We also make some improvement inside instrumentation: * updates Instrumentation::ShouldNotifyMethodEnterExitEvents to comply with its name. * compute frame id only once when looking for the corresponding instrumentation frame. * compute the OatMethod once in ClassLinker::GetPortableOatCodeFor to avoid looking for it again. Bug: 13577964 Change-Id: If6fa198a676b515cd474b8c4d7bf7ef3626f2dc7
Diffstat (limited to 'runtime/instrumentation.cc')
-rw-r--r--runtime/instrumentation.cc15
1 files changed, 8 insertions, 7 deletions
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 525e2b3..5233462 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -255,7 +255,7 @@ static void InstrumentationInstallStack(Thread* thread, void* arg)
visitor.WalkStack(true);
CHECK_EQ(visitor.dex_pcs_.size(), thread->GetInstrumentationStack()->size());
- if (!instrumentation->ShouldNotifyMethodEnterExitEvents()) {
+ if (instrumentation->ShouldNotifyMethodEnterExitEvents()) {
// Create method enter events for all methods currently on the thread's stack. We only do this
// if no debugger is attached to prevent from posting events twice.
typedef std::deque<InstrumentationStackFrame>::const_reverse_iterator It;
@@ -302,8 +302,9 @@ static void InstrumentationRestoreStack(Thread* thread, void* arg)
}
bool removed_stub = false;
// TODO: make this search more efficient?
- for (InstrumentationStackFrame instrumentation_frame : *instrumentation_stack_) {
- if (instrumentation_frame.frame_id_ == GetFrameId()) {
+ const size_t frameId = GetFrameId();
+ for (const InstrumentationStackFrame& instrumentation_frame : *instrumentation_stack_) {
+ if (instrumentation_frame.frame_id_ == frameId) {
if (kVerboseInstrumentation) {
LOG(INFO) << " Removing exit stub in " << DescribeLocation();
}
@@ -313,7 +314,7 @@ static void InstrumentationRestoreStack(Thread* thread, void* arg)
CHECK(m == instrumentation_frame.method_) << PrettyMethod(m);
}
SetReturnPc(instrumentation_frame.return_pc_);
- if (!instrumentation_->ShouldNotifyMethodEnterExitEvents()) {
+ if (instrumentation_->ShouldNotifyMethodEnterExitEvents()) {
// Create the method exit events. As the methods didn't really exit the result is 0.
// We only do this if no debugger is attached to prevent from posting events twice.
instrumentation_->MethodExitEvent(thread_, instrumentation_frame.this_object_, m,
@@ -439,7 +440,7 @@ void Instrumentation::ConfigureStubs(bool require_entry_exit_stubs, bool require
// We're already set.
return;
}
- Thread* self = Thread::Current();
+ Thread* const self = Thread::Current();
Runtime* runtime = Runtime::Current();
Locks::thread_list_lock_->AssertNotHeld(self);
if (desired_level > 0) {
@@ -451,7 +452,7 @@ void Instrumentation::ConfigureStubs(bool require_entry_exit_stubs, bool require
}
runtime->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, this);
instrumentation_stubs_installed_ = true;
- MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
runtime->GetThreadList()->ForEach(InstrumentationInstallStack, this);
} else {
interpreter_stubs_installed_ = false;
@@ -657,7 +658,7 @@ void Instrumentation::DisableDeoptimization() {
// Indicates if instrumentation should notify method enter/exit events to the listeners.
bool Instrumentation::ShouldNotifyMethodEnterExitEvents() const {
- return deoptimization_enabled_ || interpreter_stubs_installed_;
+ return !deoptimization_enabled_ && !interpreter_stubs_installed_;
}
void Instrumentation::DeoptimizeEverything() {