Support for deoptimization needed for debugging.
The deoptimization code is untested, and some sanity checks in the
instrumentation are disabled because they need debugging.
Change-Id: I1b60a65a60bddc9b107ad4659da097b55ce901c3
diff --git a/src/instrumentation.cc b/src/instrumentation.cc
index 28f8cb2..bcf7c5d 100644
--- a/src/instrumentation.cc
+++ b/src/instrumentation.cc
@@ -72,28 +72,83 @@
return true;
}
-static void InstrumentationRestoreStack(Thread* self, void*) NO_THREAD_SAFETY_ANALYSIS {
- struct RestoreStackVisitor : public StackVisitor {
- RestoreStackVisitor(Thread* self)
- : StackVisitor(self->GetManagedStack(), self->GetInstrumentationStack(), NULL), self_(self) {}
+void InstrumentationInstallStack(Thread* self, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ struct InstallStackVisitor : public StackVisitor {
+ InstallStackVisitor(Thread* self, uintptr_t instrumentation_exit_pc)
+ : StackVisitor(self->GetManagedStack(), self->GetInstrumentationStack(), NULL),
+ self_(self), instrumentation_exit_pc_(instrumentation_exit_pc) {}
- virtual bool VisitFrame() {
+ virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (GetCurrentQuickFrame() == NULL) {
+ return true; // Ignore shadow frames.
+ }
+ AbstractMethod* m = GetMethod();
+ if (m == NULL) {
+ return true; // Ignore upcalls.
+ }
+ if (m->GetDexMethodIndex() == DexFile::kDexNoIndex16) {
+ return true; // Ignore unresolved methods since they will be instrumented after resolution.
+ }
+ uintptr_t pc = GetReturnPc();
+ InstrumentationStackFrame instrumentation_frame(m, pc, GetFrameId());
+ self_->PushBackInstrumentationStackFrame(instrumentation_frame);
+ SetReturnPc(instrumentation_exit_pc_);
+ return true; // Continue.
+ }
+ Thread* const self_;
+ const uintptr_t instrumentation_exit_pc_;
+ };
+ uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
+ InstallStackVisitor visitor(self, instrumentation_exit_pc);
+ visitor.WalkStack(true);
+ Trace* trace = reinterpret_cast<Trace*>(arg);
+ if (trace != NULL) {
+ std::deque<InstrumentationStackFrame>::const_reverse_iterator it =
+ self->GetInstrumentationStack()->rbegin();
+ std::deque<InstrumentationStackFrame>::const_reverse_iterator end =
+ self->GetInstrumentationStack()->rend();
+ for (; it != end; ++it) {
+ trace->LogMethodTraceEvent(self, (*it).method_, Trace::kMethodTraceEnter);
+ }
+ }
+}
+
+static void InstrumentationRestoreStack(Thread* self, void*)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ struct RestoreStackVisitor : public StackVisitor {
+ RestoreStackVisitor(Thread* self, uintptr_t instrumentation_exit_pc)
+ : StackVisitor(self->GetManagedStack(), self->GetInstrumentationStack(), NULL),
+ self_(self), instrumentation_exit_pc_(instrumentation_exit_pc) {}
+
+ virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (self_->IsInstrumentationStackEmpty()) {
return false; // Stop.
}
+ AbstractMethod* m = GetMethod();
+ if (m == NULL) {
+ return true; // Ignore upcalls.
+ }
uintptr_t pc = GetReturnPc();
- if (IsInstrumentationExitPc(pc)) {
+ if (pc == instrumentation_exit_pc_) {
InstrumentationStackFrame instrumentation_frame = self_->PopInstrumentationStackFrame();
SetReturnPc(instrumentation_frame.return_pc_);
- CHECK(GetMethod() == instrumentation_frame.method_);
+ CHECK(m == instrumentation_frame.method_);
+ CHECK_EQ(GetFrameId(), instrumentation_frame.frame_id_);
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsMethodTracingActive()) {
+ Trace* trace = runtime->GetInstrumentation()->GetTrace();
+ trace->LogMethodTraceEvent(self_, m, Trace::kMethodTraceExit);
+ }
}
return true; // Continue.
}
-
- Thread* self_;
+ Thread* const self_;
+ const uintptr_t instrumentation_exit_pc_;
};
- RestoreStackVisitor visitor(self);
- visitor.WalkStack();
+ uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
+ RestoreStackVisitor visitor(self, instrumentation_exit_pc);
+ visitor.WalkStack(true);
}
Instrumentation::~Instrumentation() {
@@ -101,7 +156,11 @@
}
void Instrumentation::InstallStubs() {
+ Thread* self = Thread::Current();
+ Locks::thread_list_lock_->AssertNotHeld(self);
Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ Runtime::Current()->GetThreadList()->ForEach(InstrumentationInstallStack, GetTrace());
}
void Instrumentation::UninstallStubs() {