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

Unified Diff: runtime/vm/debugger.cc

Issue 240213004: Fixes a problem with the recovery of contexts in the debugger at closure calls. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/debugger.cc
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 3d487b22b7021c0fd480252d57296005f6a8abcc..3fc970adb318402fe62b5bf9ff737dcfb77deab3 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -28,6 +28,8 @@
namespace dart {
DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
+DEFINE_FLAG(bool, trace_debugger_stacktrace, false,
+ "Trace debugger stacktrace collection");
Debugger::EventHandler* Debugger::event_handler_ = NULL;
@@ -446,6 +448,10 @@ RawContext* ActivationFrame::GetSavedEntryContext() {
RawLocalVarDescriptors::VarInfo var_info;
var_descriptors_.GetInfo(i, &var_info);
if (var_info.kind == RawLocalVarDescriptors::kSavedEntryContext) {
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tFound saved entry ctx at index %" Pd "\n",
+ var_info.index);
+ }
return GetLocalContextVar(var_info.index);
}
}
@@ -464,6 +470,10 @@ RawContext* ActivationFrame::GetSavedCurrentContext() {
RawLocalVarDescriptors::VarInfo var_info;
var_descriptors_.GetInfo(i, &var_info);
if (var_info.kind == RawLocalVarDescriptors::kSavedCurrentContext) {
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tFound saved current ctx at index %" Pd "\n",
+ var_info.index);
+ }
return GetLocalContextVar(var_info.index);
}
}
@@ -625,6 +635,52 @@ RawContext* ActivationFrame::GetLocalContextVar(intptr_t slot_index) {
}
+void ActivationFrame::PrintContextMismatchError(
+ const String& var_name,
+ intptr_t ctx_slot,
+ intptr_t frame_ctx_level,
+ intptr_t var_ctx_level) {
+ OS::PrintErr("-------------------------\n"
+ "Encountered context mismatch\n"
+ "\tvar name: %s\n"
+ "\tctx_slot: %" Pd "\n"
+ "\tframe_ctx_level: %" Pd "\n"
+ "\tvar_ctx_level: %" Pd "\n\n",
+ var_name.ToCString(),
+ ctx_slot,
+ frame_ctx_level,
+ var_ctx_level);
+
+ OS::PrintErr("-------------------------\n"
+ "Current frame:\n%s\n",
+ this->ToCString());
+
+ OS::PrintErr("-------------------------\n"
+ "Context contents:\n");
+ ctx_.Dump(8);
+
+ OS::PrintErr("-------------------------\n"
+ "Debugger stack trace...\n\n");
+ DebuggerStackTrace* stack =
+ Isolate::Current()->debugger()->StackTrace();
+ intptr_t num_frames = stack->Length();
+ for (intptr_t i = 0; i < num_frames; i++) {
+ ActivationFrame* frame = stack->FrameAt(i);
+ OS::PrintErr("#%04" Pd " %s", i, frame->ToCString());
+ }
+
+ OS::PrintErr("-------------------------\n"
+ "All frames...\n\n");
+ StackFrameIterator iterator(false);
+ StackFrame* frame = iterator.NextFrame();
+ intptr_t num = 0;
+ while ((frame != NULL)) {
+ frame = iterator.NextFrame();
+ OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
+ }
+}
+
+
void ActivationFrame::VariableAt(intptr_t i,
String* name,
intptr_t* token_pos,
@@ -648,6 +704,8 @@ void ActivationFrame::VariableAt(intptr_t i,
ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
if (ctx_.IsNull()) {
// The context has been removed by the optimizing compiler.
+ //
+ // TODO(turnidge): This may be erroneous. Revisit.
*value = Symbols::OptimizedOut().raw();
return;
}
@@ -660,6 +718,11 @@ void ActivationFrame::VariableAt(intptr_t i,
intptr_t level_diff = frame_ctx_level - var_ctx_level;
intptr_t ctx_slot = var_info.index;
if (level_diff == 0) {
+ if ((ctx_slot < 0) ||
+ (ctx_slot >= ctx_.num_variables())) {
+ PrintContextMismatchError(*name, ctx_slot,
+ frame_ctx_level, var_ctx_level);
+ }
ASSERT((ctx_slot >= 0) && (ctx_slot < ctx_.num_variables()));
*value = ctx_.At(ctx_slot);
} else {
@@ -669,6 +732,12 @@ void ActivationFrame::VariableAt(intptr_t i,
level_diff--;
var_ctx = var_ctx.parent();
}
+ if (var_ctx.IsNull() ||
+ (ctx_slot < 0) ||
+ (ctx_slot >= var_ctx.num_variables())) {
+ PrintContextMismatchError(*name, ctx_slot,
+ frame_ctx_level, var_ctx_level);
+ }
ASSERT(!var_ctx.IsNull());
ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables()));
*value = var_ctx.At(ctx_slot);
@@ -694,18 +763,22 @@ RawArray* ActivationFrame::GetLocalVariables() {
const char* ActivationFrame::ToCString() {
- const char* kFormat = "Function: '%s' url: '%s' line: %d";
-
const String& url = String::Handle(SourceUrl());
intptr_t line = LineNumber();
const char* func_name = Debugger::QualifiedFunctionName(function());
-
- intptr_t len =
- OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line);
- len++; // String terminator.
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line);
- return chars;
+ return Isolate::Current()->current_zone()->
+ PrintToString("[ Frame pc(0x%" Px ") fp(0x%" Px ") sp(0x%" Px ")\n"
+ "\tfunction = %s\n"
+ "\turl = %s\n"
+ "\tline = %" Pd "\n"
+ "\tcontext = %s\n"
+ "\tcontext level = %" Pd " ]\n",
+ pc(), fp(), sp(),
+ func_name,
+ url.ToCString(),
+ line,
+ ctx_.ToCString(),
+ ContextLevel());
}
@@ -1065,21 +1138,42 @@ ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
new ActivationFrame(pc, frame->fp(), frame->sp(), code,
deopt_frame, deopt_frame_offset);
- // Recover the context for this frame.
- if (callee_activation == NULL) {
- // No callee. Use incoming entry context. Could be from
- // isolate's top context or from an entry frame.
- ASSERT(!entry_ctx.IsNull());
- activation->SetContext(entry_ctx);
+ // Is there a closure call at the current PC?
+ //
+ // We can't just check the callee_activation to see if it is a
+ // closure function, because it may not be on the stack yet.
+ bool is_closure_call = false;
+ const PcDescriptors& pc_desc =
+ PcDescriptors::Handle(code.pc_descriptors());
+ ASSERT(code.ContainsInstructionAt(pc));
+ for (int i = 0; i < pc_desc.Length(); i++) {
+ if (pc_desc.PC(i) == pc &&
+ pc_desc.DescriptorKind(i) == PcDescriptors::kClosureCall) {
+ is_closure_call = true;
+ break;
+ }
+ }
- } else if (callee_activation->function().IsClosureFunction()) {
+ // Recover the context for this frame.
+ if (is_closure_call) {
// 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());
ASSERT(!closure_call_ctx.IsNull());
activation->SetContext(closure_call_ctx);
-
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tUsing closure call ctx: %s\n",
+ closure_call_ctx.ToCString());
+ }
+ } else if (callee_activation == NULL) {
+ // No callee available. Use incoming entry context. Could be from
+ // isolate's top context or from an entry frame.
+ ASSERT(!entry_ctx.IsNull());
+ activation->SetContext(entry_ctx);
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tUsing entry ctx: %s\n", entry_ctx.ToCString());
+ }
} 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
@@ -1090,6 +1184,13 @@ ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
const Context& callee_ctx =
Context::Handle(isolate, callee_activation->GetSavedEntryContext());
activation->SetContext(callee_ctx);
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tUsing callee call ctx: %s\n",
+ callee_ctx.ToCString());
+ }
+ }
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
}
return activation;
}
@@ -1132,9 +1233,17 @@ DebuggerStackTrace* Debugger::CollectStackTrace() {
frame != NULL;
frame = iterator.NextFrame()) {
ASSERT(frame->IsValid());
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
+ frame->ToCString());
+ }
if (frame->IsEntryFrame()) {
current_activation = NULL;
entry_ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext();
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tFound saved ctx in entry frame:\n\t%s\n",
+ entry_ctx.ToCString());
+ }
} else if (frame->IsDartFrame()) {
code = frame->LookupDartCode();
@@ -1144,6 +1253,13 @@ DebuggerStackTrace* Debugger::CollectStackTrace() {
!it.Done();
it.Advance()) {
inlined_code = it.code();
+ if (FLAG_trace_debugger_stacktrace) {
+ const Function& function =
+ Function::Handle(inlined_code.function());
+ ASSERT(!function.IsNull());
+ OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
+ function.ToFullyQualifiedCString());
+ }
intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
current_activation = CollectDartFrame(isolate,
it.pc(),
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698