Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1092)

Unified Diff: runtime/vm/debugger.cc

Issue 26255004: Allow the debugger to inspect local variables from optimized and (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/debugger.cc
===================================================================
--- runtime/vm/debugger.cc (revision 28225)
+++ runtime/vm/debugger.cc (working copy)
@@ -10,6 +10,7 @@
#include "vm/code_patcher.h"
#include "vm/compiler.h"
#include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/longjump.h"
@@ -26,6 +27,8 @@
namespace dart {
DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
+DEFINE_FLAG(bool, use_new_stacktrace, true,
+ "Use new stacktrace creation");
Debugger::EventHandler* Debugger::event_handler_ = NULL;
@@ -133,6 +136,8 @@
pc_desc_index_(-1),
line_number_(-1),
context_level_(-1),
+ deopt_frame_(Array::ZoneHandle()),
+ deopt_frame_offset_(0),
vars_initialized_(false),
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
desc_indices_(8),
@@ -358,6 +363,29 @@
}
+RawContext* ActivationFrame::GetSavedEntryContextNew() {
+ if (ctx_.IsNull()) {
+ // We have bailed on providing a context for this frame. Bail for
+ // the caller as well.
+ return Context::null();
+ }
+
+ // Attempt to find a saved context.
+ GetVarDescriptors();
+ intptr_t var_desc_len = var_descriptors_.Length();
+ for (int i = 0; i < var_desc_len; i++) {
srdjan 2013/10/07 21:36:53 s/int/intptr_t/
turnidge 2013/10/08 17:29:12 Done. There is other cases like this in this file
srdjan 2013/10/08 18:41:25 Either here or a later CL.
+ RawLocalVarDescriptors::VarInfo var_info;
+ var_descriptors_.GetInfo(i, &var_info);
+ if (var_info.kind == RawLocalVarDescriptors::kSavedEntryContext) {
+ return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index));
+ }
+ }
+
+ // No saved context. Return the current context.
+ return ctx_.raw();
+}
+
+
// Get the saved context if the callee of this activation frame is a
// closure function.
RawContext* ActivationFrame::GetSavedCurrentContext() {
@@ -421,7 +449,7 @@
// Rather than potentially displaying incorrect values, we
// pretend that there are no variables in the frame.
// We should be more clever about this in the future.
- if (code().is_optimized()) {
+ if (!FLAG_use_new_stacktrace && code().is_optimized()) {
vars_initialized_ = true;
return;
}
@@ -501,6 +529,20 @@
}
+// TODO(hausner): Handle captured variables.
+RawInstance* ActivationFrame::GetLocalVarValue(intptr_t slot_index) {
+ if (deopt_frame_.IsNull()) {
+ uword var_address = fp() + slot_index * kWordSize;
srdjan 2013/10/07 21:36:53 If you assign the result first to an instance (as
turnidge 2013/10/08 17:29:12 Done.
turnidge 2013/10/08 18:21:11 Turns out this uncovered an oddness -- value isn't
+ return reinterpret_cast<RawInstance*>(
+ *reinterpret_cast<uword*>(var_address));
+ } else {
+ Instance& instance = Instance::Handle();
+ instance ^= deopt_frame_.At(deopt_frame_offset_ + slot_index);
+ return instance.raw();
+ }
+}
+
+
void ActivationFrame::VariableAt(intptr_t i,
String* name,
intptr_t* token_pos,
@@ -945,7 +987,154 @@
}
+static void PrintStackTraceError(const char* message,
+ ActivationFrame* current_activation,
+ ActivationFrame* callee_activation) {
+ const Function& current = current_activation->function();
+ const Function& callee = callee_activation->function();
+ const Script& script =
+ Script::Handle(Class::Handle(current.Owner()).script());
+ intptr_t line, col;
+ script.GetTokenLocation(current_activation->TokenPos(), &line, &col);
+ OS::PrintErr("Error building stack trace: %s:"
+ "current function '%s' callee_function '%s' "
+ " line %" Pd " column %" Pd "\n",
+ message,
+ current.ToFullyQualifiedCString(),
+ callee.ToFullyQualifiedCString(),
+ line, col);
+}
+
+
+ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
+ uword pc,
+ StackFrame* frame,
+ const Code& code,
+ bool optimized,
+ ActivationFrame* callee_activation,
+ const Context& entry_ctx) {
+ // We never provide both a callee activation and an entry context.
+ ASSERT(callee_activation == NULL || entry_ctx.IsNull());
srdjan 2013/10/07 21:36:53 Add parenthesis
turnidge 2013/10/08 17:29:12 Where do you want the parentheses?
turnidge 2013/10/08 18:21:11 Added the parentheses.
+ ActivationFrame* activation =
+ new ActivationFrame(pc, frame->fp(), frame->sp(), code);
+
+ // Recover the context for this frame.
+ if (optimized) {
+ // Bail out for optimized frames for now.
+ activation->SetContext(Context::Handle(isolate));
+
+ } else if (callee_activation == NULL) {
+ // No callee. Use incoming entry context. Could be from
+ // isolate's top context or from an entry frame.
+ activation->SetContext(entry_ctx);
+
+ } else if (callee_activation->function().IsClosureFunction()) {
+ // If the callee is a closure, we should have stored the context
+ // in the current frame before making the call.
+ const Context& closure_call_ctx =
+ Context::Handle(isolate, activation->GetSavedCurrentContext());
+ activation->SetContext(closure_call_ctx);
+
+ // Sometimes there is no saved context. This is a bug.
srdjan 2013/10/07 21:36:53 Please add bug id.
turnidge 2013/10/08 17:29:12 Done.
+ if (FLAG_verbose_debug && closure_call_ctx.IsNull()) {
+ PrintStackTraceError(
+ "Expected to find saved context for call to closure function",
+ activation, callee_activation);
+ }
+
+ } else {
+ // Use the context provided by our callee. This is either the
+ // callee's context or a context that was saved in the callee's
+ // frame.
+ const Context& callee_ctx =
+ Context::Handle(isolate, callee_activation->GetSavedEntryContextNew());
+ activation->SetContext(callee_ctx);
+ }
+ return activation;
+}
+
srdjan 2013/10/07 21:36:53 2 lines between functions
turnidge 2013/10/08 17:29:12 Done.
+RawArray* Debugger::DeoptimizeToArray(Isolate* isolate,
+ StackFrame* frame,
+ const Code& code) {
srdjan 2013/10/07 21:36:53 Fix indent
turnidge 2013/10/08 17:29:12 Done.
+ ASSERT(code.is_optimized());
+
+ // Create the DeoptContext for this deoptimization.
+ DeoptContext* deopt_context =
+ new DeoptContext(frame, code,
+ DeoptContext::kDestIsAllocated,
+ NULL, NULL);
+ isolate->set_deopt_context(deopt_context);
+
+ deopt_context->FillDestFrame();
+ deopt_context->MaterializeDeferredObjects();
+ const Array& dest_frame = Array::Handle(deopt_context->DestFrameAsArray());
+
+ isolate->set_deopt_context(NULL);
+ delete deopt_context;
+
+ return dest_frame.raw();
+}
+
+
+DebuggerStackTrace* Debugger::CollectStackTraceNew() {
+ Isolate* isolate = Isolate::Current();
+ DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
+ StackFrameIterator iterator(false);
+ ActivationFrame* current_activation = NULL;
+ Context& entry_ctx = Context::Handle(isolate->top_context());
+ for (StackFrame* frame = iterator.NextFrame();
+ frame != NULL;
+ frame = iterator.NextFrame()) {
+ ASSERT(frame->IsValid());
+ if (frame->IsEntryFrame()) {
+ current_activation = NULL;
+ entry_ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext();
+
+ } else if (frame->IsDartFrame()) {
+ const Code& code = Code::Handle(isolate, frame->LookupDartCode());
+ if (code.is_optimized()) {
+ const Array& deopt_frame =
+ Array::Handle(DeoptimizeToArray(isolate, frame, code));
+ for (InlinedFunctionsIterator it(code, frame->pc());
+ !it.Done();
+ it.Advance()) {
+ const Code& inlined_code = Code::Handle(isolate, it.code());
+ intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
+ current_activation = CollectDartFrame(isolate,
+ it.pc(),
+ frame,
+ inlined_code,
+ true,
+ current_activation,
+ entry_ctx);
+ current_activation->SetDeoptFrame(deopt_frame, deopt_frame_offset);
+ stack_trace->AddActivation(current_activation);
+ entry_ctx = Context::null(); // Only use entry context once.
+ }
+ } else {
+ current_activation = CollectDartFrame(isolate,
+ frame->pc(),
+ frame,
+ code,
+ false,
+ current_activation,
+ entry_ctx);
+ stack_trace->AddActivation(current_activation);
+ entry_ctx = Context::null(); // Only use entry context once.
+ }
+ }
+ }
+ return stack_trace;
+}
+
+
+
DebuggerStackTrace* Debugger::CollectStackTrace() {
+ if (FLAG_use_new_stacktrace) {
+ // Guard new stack trace generation under a flag in case there are
+ // problems rolling it out.
+ return CollectStackTraceNew();
+ }
Isolate* isolate = Isolate::Current();
DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
Context& ctx = Context::Handle(isolate->top_context());

Powered by Google App Engine
This is Rietveld 408576698