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

Unified Diff: runtime/vm/debugger.cc

Issue 10579020: Support captured variables in debugger (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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/flow_graph_compiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/debugger.cc
===================================================================
--- runtime/vm/debugger.cc (revision 8858)
+++ runtime/vm/debugger.cc (working copy)
@@ -106,13 +106,19 @@
}
-ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp)
+ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp,
+ const Context& ctx)
: pc_(pc), fp_(fp), sp_(sp),
+ ctx_(Context::ZoneHandle(ctx.raw())),
function_(Function::ZoneHandle()),
token_index_(-1),
+ pc_desc_index_(-1),
line_number_(-1),
+ context_level_(-1),
+ vars_initialized_(false),
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
- desc_indices_(8) {
+ desc_indices_(8),
+ pc_desc_(PcDescriptors::ZoneHandle()) {
}
@@ -167,16 +173,26 @@
}
-intptr_t ActivationFrame::TokenIndex() {
- if (token_index_ < 0) {
+void ActivationFrame::GetPcDescriptors() {
+ if (pc_desc_.IsNull()) {
const Function& func = DartFunction();
ASSERT(!func.HasOptimizedCode());
Code& code = Code::Handle(func.unoptimized_code());
ASSERT(!code.IsNull());
- PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
- for (int i = 0; i < desc.Length(); i++) {
- if (desc.PC(i) == pc_) {
- token_index_ = desc.TokenIndex(i);
+ pc_desc_ = code.pc_descriptors();
+ ASSERT(!pc_desc_.IsNull());
+ }
+}
+
+
+// Compute token_index_ and pc_desc_index_.
+intptr_t ActivationFrame::TokenIndex() {
+ if (token_index_ < 0) {
+ GetPcDescriptors();
+ for (int i = 0; i < pc_desc_.Length(); i++) {
+ if (pc_desc_.PC(i) == pc_) {
+ pc_desc_index_ = i;
+ token_index_ = pc_desc_.TokenIndex(i);
break;
}
}
@@ -186,6 +202,15 @@
}
+intptr_t ActivationFrame::PcDescIndex() {
+ if (pc_desc_index_ < 0) {
+ TokenIndex();
+ ASSERT(pc_desc_index_ >= 0);
+ }
+ return pc_desc_index_;
+}
+
+
intptr_t ActivationFrame::LineNumber() {
// Compute line number lazily since it causes scanning of the script.
if (line_number_ < 0) {
@@ -197,58 +222,133 @@
}
-void ActivationFrame::GetDescIndices() {
- if (var_descriptors_.IsNull()) {
- ASSERT(!DartFunction().HasOptimizedCode());
- const Code& code = Code::Handle(DartFunction().unoptimized_code());
- var_descriptors_ = code.var_descriptors();
- // TODO(Hausner): Consider replacing this GrowableArray.
- GrowableArray<String*> var_names(8);
+void ActivationFrame::GetVarDescriptors() {
+ if (!var_descriptors_.IsNull()) {
+ return;
+ }
+ ASSERT(!DartFunction().HasOptimizedCode());
+ const Code& code = Code::Handle(DartFunction().unoptimized_code());
+ var_descriptors_ = code.var_descriptors();
+ ASSERT(!var_descriptors_.IsNull());
+}
+
+
+// Calculate the context level at the current token index of the frame.
+intptr_t ActivationFrame::ContextLevel() {
+ if (context_level_ < 0) {
+ context_level_ = 0;
+ intptr_t pc_desc_idx = PcDescIndex();
+ ASSERT(!pc_desc_.IsNull());
+ if (pc_desc_.DescriptorKind(pc_desc_idx) == PcDescriptors::kReturn) {
+ // Special case: the context chain has already been deallocated.
+ // The context level is 0.
+ return context_level_;
+ }
+ intptr_t innermost_begin_pos = 0;
intptr_t activation_token_pos = TokenIndex();
+ GetVarDescriptors();
intptr_t var_desc_len = var_descriptors_.Length();
for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
- ASSERT(var_names.length() == desc_indices_.length());
- intptr_t scope_id, begin_pos, end_pos;
- var_descriptors_.GetScopeInfo(cur_idx, &scope_id, &begin_pos, &end_pos);
- if ((begin_pos <= activation_token_pos) &&
- (activation_token_pos <= end_pos)) {
- // The current variable is textually in scope. Now check whether
- // there is another local variable with the same name that shadows
- // or is shadowed by this variable.
- String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
- intptr_t indices_len = desc_indices_.length();
- bool name_match_found = false;
- for (int i = 0; i < indices_len; i++) {
- if (var_name.Equals(*var_names[i])) {
- // Found two local variables with the same name. Now determine
- // which one is shadowed.
- name_match_found = true;
- intptr_t i_begin_pos, ignore;
- var_descriptors_.GetScopeInfo(
- desc_indices_[i], &ignore, &i_begin_pos, &ignore);
- if (i_begin_pos < begin_pos) {
- // The variable we found earlier is in an outer scope
- // and is shadowed by the current variable. Replace the
- // descriptor index of the previously found variable
- // with the descriptor index of the current variable.
- desc_indices_[i] = cur_idx;
- } else {
- // The variable we found earlier is in an inner scope
- // and shadows the current variable. Skip the current
- // variable. (Nothing to do.)
- }
- break; // Stop looking for name matches.
+ RawLocalVarDescriptors::VarInfo var_info;
+ var_descriptors_.GetInfo(cur_idx, &var_info);
+ if ((var_info.kind == RawLocalVarDescriptors::kContextLevel) &&
+ (var_info.begin_pos <= activation_token_pos) &&
+ (activation_token_pos < var_info.end_pos)) {
+ // This var_descriptors_ entry is a context scope which is in scope
+ // of the current token position. Now check whether it is shadowing
+ // the previous context scope.
+ if (innermost_begin_pos < var_info.begin_pos) {
+ innermost_begin_pos = var_info.begin_pos;
+ context_level_ = var_info.index;
+ }
+ }
+ }
+ ASSERT(context_level_ >= 0);
+ }
+ return context_level_;
+}
+
+
+RawContext* ActivationFrame::CallerContext() {
+ GetVarDescriptors();
+ intptr_t var_desc_len = var_descriptors_.Length();
+ for (int i = 0; i < var_desc_len; i++) {
+ RawLocalVarDescriptors::VarInfo var_info;
+ var_descriptors_.GetInfo(i, &var_info);
+ if (var_info.kind == RawLocalVarDescriptors::kContextChain) {
+ return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index));
+ }
+ }
+ // Caller uses same context chain.
+ return ctx_.raw();
+}
+
+
+void ActivationFrame::GetDescIndices() {
+ if (vars_initialized_) {
+ return;
+ }
+ GetVarDescriptors();
+ // TODO(hausner): Consider replacing this GrowableArray.
+ GrowableArray<String*> var_names(8);
+ intptr_t activation_token_pos = TokenIndex();
+ intptr_t var_desc_len = var_descriptors_.Length();
+ for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
+ ASSERT(var_names.length() == desc_indices_.length());
+ RawLocalVarDescriptors::VarInfo var_info;
+ var_descriptors_.GetInfo(cur_idx, &var_info);
+ if ((var_info.kind != RawLocalVarDescriptors::kStackVar) &&
+ (var_info.kind != RawLocalVarDescriptors::kContextVar)) {
+ continue;
+ }
+ if ((var_info.begin_pos <= activation_token_pos) &&
+ (activation_token_pos <= var_info.end_pos)) {
+ if ((var_info.kind == RawLocalVarDescriptors::kContextVar) &&
+ (ContextLevel() < var_info.scope_id)) {
+ // The variable is textually in scope but the context level
+ // at the activation frame's PC is lower than the context
+ // level of the variable. The context containing the variable
+ // has already been removed from the chain. This can happen when we
+ // break at a return statement, since the contexts get discarded
+ // before the debugger gets called.
+ continue;
+ }
+ // The current variable is textually in scope. Now check whether
+ // there is another local variable with the same name that shadows
+ // or is shadowed by this variable.
+ String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
+ intptr_t indices_len = desc_indices_.length();
+ bool name_match_found = false;
+ for (int i = 0; i < indices_len; i++) {
+ if (var_name.Equals(*var_names[i])) {
+ // Found two local variables with the same name. Now determine
+ // which one is shadowed.
+ name_match_found = true;
+ RawLocalVarDescriptors::VarInfo i_var_info;
+ var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
+ if (i_var_info.begin_pos < var_info.begin_pos) {
+ // The variable we found earlier is in an outer scope
+ // and is shadowed by the current variable. Replace the
+ // descriptor index of the previously found variable
+ // with the descriptor index of the current variable.
+ desc_indices_[i] = cur_idx;
+ } else {
+ // The variable we found earlier is in an inner scope
+ // and shadows the current variable. Skip the current
+ // variable. (Nothing to do.)
}
+ break; // Stop looking for name matches.
}
- if (!name_match_found) {
- // No duplicate name found. Add the current descriptor index to the
- // list of visible variables.
- desc_indices_.Add(cur_idx);
- var_names.Add(&var_name);
- }
}
+ if (!name_match_found) {
+ // No duplicate name found. Add the current descriptor index to the
+ // list of visible variables.
+ desc_indices_.Add(cur_idx);
+ var_names.Add(&var_name);
+ }
}
}
+ vars_initialized_ = true;
}
@@ -265,13 +365,41 @@
Instance* value) {
GetDescIndices();
ASSERT(i < desc_indices_.length());
+ intptr_t desc_index = desc_indices_[i];
ASSERT(name != NULL);
- intptr_t desc_index = desc_indices_[i];
*name ^= var_descriptors_.GetName(desc_index);
- intptr_t scope_id;
- var_descriptors_.GetScopeInfo(desc_index, &scope_id, token_pos, end_pos);
+ RawLocalVarDescriptors::VarInfo var_info;
+ var_descriptors_.GetInfo(desc_index, &var_info);
+ ASSERT(token_pos != NULL);
+ *token_pos = var_info.begin_pos;
+ ASSERT(end_pos != NULL);
+ *end_pos = var_info.end_pos;
ASSERT(value != NULL);
- *value = GetLocalVarValue(var_descriptors_.GetSlotIndex(desc_index));
+ if (var_info.kind == RawLocalVarDescriptors::kStackVar) {
+ *value = GetLocalVarValue(var_info.index);
+ } else {
+ ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
+ ASSERT(!ctx_.IsNull());
+ // The context level at the PC/token index of this activation frame.
+ intptr_t frame_ctx_level = ContextLevel();
+ // The context level of the variable.
+ intptr_t var_ctx_level = var_info.scope_id;
+ intptr_t level_diff = frame_ctx_level - var_ctx_level;
+ intptr_t ctx_slot = var_info.index;
+ if (level_diff == 0) {
+ *value = ctx_.At(ctx_slot);
+ } else {
+ ASSERT(level_diff > 0);
+ Context& ctx = Context::Handle(ctx_.raw());
+ while (level_diff > 0) {
+ ASSERT(!ctx.IsNull());
+ level_diff--;
+ ctx = ctx.parent();
+ }
+ ASSERT(!ctx.IsNull());
+ *value = ctx.At(ctx_slot);
+ }
+ }
}
@@ -282,9 +410,9 @@
Instance& value = Instance::Handle();
const Array& list = Array::Handle(Array::New(2 * num_variables));
for (int i = 0; i < num_variables; i++) {
- var_name = var_descriptors_.GetName(i);
+ intptr_t ignore;
+ VariableAt(i, &var_name, &ignore, &ignore, &value);
list.SetAt(2 * i, var_name);
- value = GetLocalVarValue(var_descriptors_.GetSlotIndex(i));
list.SetAt((2 * i) + 1, value);
}
return list.raw();
@@ -609,13 +737,15 @@
DebuggerStackTrace* Debugger::CollectStackTrace() {
DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
+ Context& ctx = Context::Handle(Isolate::Current()->top_context());
DartFrameIterator iterator;
StackFrame* frame = iterator.NextFrame();
while (frame != NULL) {
ASSERT(frame->IsValid());
ASSERT(frame->IsDartFrame());
ActivationFrame* activation =
- new ActivationFrame(frame->pc(), frame->fp(), frame->sp());
+ new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), ctx);
+ ctx = activation->CallerContext();
stack_trace->AddActivation(activation);
frame = iterator.NextFrame();
}
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698