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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "vm/code_generator.h" 7 #include "vm/code_generator.h"
8 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 99 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
100 } 100 }
101 101
102 102
103 103
104 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 104 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
105 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 105 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
106 } 106 }
107 107
108 108
109 ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp) 109 ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp,
110 const Context& ctx)
110 : pc_(pc), fp_(fp), sp_(sp), 111 : pc_(pc), fp_(fp), sp_(sp),
112 ctx_(Context::ZoneHandle(ctx.raw())),
111 function_(Function::ZoneHandle()), 113 function_(Function::ZoneHandle()),
112 token_index_(-1), 114 token_index_(-1),
115 pc_desc_index_(-1),
113 line_number_(-1), 116 line_number_(-1),
117 context_level_(-1),
118 vars_initialized_(false),
114 var_descriptors_(LocalVarDescriptors::ZoneHandle()), 119 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
115 desc_indices_(8) { 120 desc_indices_(8),
121 pc_desc_(PcDescriptors::ZoneHandle()) {
116 } 122 }
117 123
118 124
119 const Function& ActivationFrame::DartFunction() { 125 const Function& ActivationFrame::DartFunction() {
120 if (function_.IsNull()) { 126 if (function_.IsNull()) {
121 Isolate* isolate = Isolate::Current(); 127 Isolate* isolate = Isolate::Current();
122 ASSERT(isolate != NULL); 128 ASSERT(isolate != NULL);
123 const Code& code = Code::Handle(Code::LookupCode(pc_)); 129 const Code& code = Code::Handle(Code::LookupCode(pc_));
124 function_ = code.function(); 130 function_ = code.function();
125 } 131 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 } 166 }
161 167
162 168
163 RawScript* ActivationFrame::SourceScript() { 169 RawScript* ActivationFrame::SourceScript() {
164 const Function& func = DartFunction(); 170 const Function& func = DartFunction();
165 const Class& cls = Class::Handle(func.owner()); 171 const Class& cls = Class::Handle(func.owner());
166 return cls.script(); 172 return cls.script();
167 } 173 }
168 174
169 175
170 intptr_t ActivationFrame::TokenIndex() { 176 void ActivationFrame::GetPcDescriptors() {
171 if (token_index_ < 0) { 177 if (pc_desc_.IsNull()) {
172 const Function& func = DartFunction(); 178 const Function& func = DartFunction();
173 ASSERT(!func.HasOptimizedCode()); 179 ASSERT(!func.HasOptimizedCode());
174 Code& code = Code::Handle(func.unoptimized_code()); 180 Code& code = Code::Handle(func.unoptimized_code());
175 ASSERT(!code.IsNull()); 181 ASSERT(!code.IsNull());
176 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 182 pc_desc_ = code.pc_descriptors();
177 for (int i = 0; i < desc.Length(); i++) { 183 ASSERT(!pc_desc_.IsNull());
178 if (desc.PC(i) == pc_) { 184 }
179 token_index_ = desc.TokenIndex(i); 185 }
186
187
188 // Compute token_index_ and pc_desc_index_.
189 intptr_t ActivationFrame::TokenIndex() {
190 if (token_index_ < 0) {
191 GetPcDescriptors();
192 for (int i = 0; i < pc_desc_.Length(); i++) {
193 if (pc_desc_.PC(i) == pc_) {
194 pc_desc_index_ = i;
195 token_index_ = pc_desc_.TokenIndex(i);
180 break; 196 break;
181 } 197 }
182 } 198 }
183 ASSERT(token_index_ >= 0); 199 ASSERT(token_index_ >= 0);
184 } 200 }
185 return token_index_; 201 return token_index_;
186 } 202 }
187 203
188 204
205 intptr_t ActivationFrame::PcDescIndex() {
206 if (pc_desc_index_ < 0) {
207 TokenIndex();
208 ASSERT(pc_desc_index_ >= 0);
209 }
210 return pc_desc_index_;
211 }
212
213
189 intptr_t ActivationFrame::LineNumber() { 214 intptr_t ActivationFrame::LineNumber() {
190 // Compute line number lazily since it causes scanning of the script. 215 // Compute line number lazily since it causes scanning of the script.
191 if (line_number_ < 0) { 216 if (line_number_ < 0) {
192 const Script& script = Script::Handle(SourceScript()); 217 const Script& script = Script::Handle(SourceScript());
193 intptr_t ignore_column; 218 intptr_t ignore_column;
194 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column); 219 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column);
195 } 220 }
196 return line_number_; 221 return line_number_;
197 } 222 }
198 223
199 224
225 void ActivationFrame::GetVarDescriptors() {
226 if (!var_descriptors_.IsNull()) {
227 return;
228 }
229 ASSERT(!DartFunction().HasOptimizedCode());
230 const Code& code = Code::Handle(DartFunction().unoptimized_code());
231 var_descriptors_ = code.var_descriptors();
232 ASSERT(!var_descriptors_.IsNull());
233 }
234
235
236 // Calculate the context level at the current token index of the frame.
237 intptr_t ActivationFrame::ContextLevel() {
238 if (context_level_ < 0) {
239 context_level_ = 0;
240 intptr_t pc_desc_idx = PcDescIndex();
241 ASSERT(!pc_desc_.IsNull());
242 if (pc_desc_.DescriptorKind(pc_desc_idx) == PcDescriptors::kReturn) {
243 // Special case: the context chain has already been deallocated.
244 // The context level is 0.
245 return context_level_;
246 }
247 intptr_t innermost_begin_pos = 0;
248 intptr_t activation_token_pos = TokenIndex();
249 GetVarDescriptors();
250 intptr_t var_desc_len = var_descriptors_.Length();
251 for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
252 RawLocalVarDescriptors::VarInfo var_info;
253 var_descriptors_.GetInfo(cur_idx, &var_info);
254 if ((var_info.kind == RawLocalVarDescriptors::kContextLevel) &&
255 (var_info.begin_pos <= activation_token_pos) &&
256 (activation_token_pos < var_info.end_pos)) {
257 // This var_descriptors_ entry is a context scope which is in scope
258 // of the current token position. Now check whether it is shadowing
259 // the previous context scope.
260 if (innermost_begin_pos < var_info.begin_pos) {
261 innermost_begin_pos = var_info.begin_pos;
262 context_level_ = var_info.index;
263 }
264 }
265 }
266 ASSERT(context_level_ >= 0);
267 }
268 return context_level_;
269 }
270
271
272 RawContext* ActivationFrame::CallerContext() {
273 GetVarDescriptors();
274 intptr_t var_desc_len = var_descriptors_.Length();
275 for (int i = 0; i < var_desc_len; i++) {
276 RawLocalVarDescriptors::VarInfo var_info;
277 var_descriptors_.GetInfo(i, &var_info);
278 if (var_info.kind == RawLocalVarDescriptors::kContextChain) {
279 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index));
280 }
281 }
282 // Caller uses same context chain.
283 return ctx_.raw();
284 }
285
286
200 void ActivationFrame::GetDescIndices() { 287 void ActivationFrame::GetDescIndices() {
201 if (var_descriptors_.IsNull()) { 288 if (vars_initialized_) {
202 ASSERT(!DartFunction().HasOptimizedCode()); 289 return;
203 const Code& code = Code::Handle(DartFunction().unoptimized_code()); 290 }
204 var_descriptors_ = code.var_descriptors(); 291 GetVarDescriptors();
205 // TODO(Hausner): Consider replacing this GrowableArray. 292 // TODO(hausner): Consider replacing this GrowableArray.
206 GrowableArray<String*> var_names(8); 293 GrowableArray<String*> var_names(8);
207 intptr_t activation_token_pos = TokenIndex(); 294 intptr_t activation_token_pos = TokenIndex();
208 intptr_t var_desc_len = var_descriptors_.Length(); 295 intptr_t var_desc_len = var_descriptors_.Length();
209 for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { 296 for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
210 ASSERT(var_names.length() == desc_indices_.length()); 297 ASSERT(var_names.length() == desc_indices_.length());
211 intptr_t scope_id, begin_pos, end_pos; 298 RawLocalVarDescriptors::VarInfo var_info;
212 var_descriptors_.GetScopeInfo(cur_idx, &scope_id, &begin_pos, &end_pos); 299 var_descriptors_.GetInfo(cur_idx, &var_info);
213 if ((begin_pos <= activation_token_pos) && 300 if ((var_info.kind != RawLocalVarDescriptors::kStackVar) &&
214 (activation_token_pos <= end_pos)) { 301 (var_info.kind != RawLocalVarDescriptors::kContextVar)) {
215 // The current variable is textually in scope. Now check whether 302 continue;
216 // there is another local variable with the same name that shadows 303 }
217 // or is shadowed by this variable. 304 if ((var_info.begin_pos <= activation_token_pos) &&
218 String& var_name = String::Handle(var_descriptors_.GetName(cur_idx)); 305 (activation_token_pos <= var_info.end_pos)) {
219 intptr_t indices_len = desc_indices_.length(); 306 if ((var_info.kind == RawLocalVarDescriptors::kContextVar) &&
220 bool name_match_found = false; 307 (ContextLevel() < var_info.scope_id)) {
221 for (int i = 0; i < indices_len; i++) { 308 // The variable is textually in scope but the context level
222 if (var_name.Equals(*var_names[i])) { 309 // at the activation frame's PC is lower than the context
223 // Found two local variables with the same name. Now determine 310 // level of the variable. The context containing the variable
224 // which one is shadowed. 311 // has already been removed from the chain. This can happen when we
225 name_match_found = true; 312 // break at a return statement, since the contexts get discarded
226 intptr_t i_begin_pos, ignore; 313 // before the debugger gets called.
227 var_descriptors_.GetScopeInfo( 314 continue;
228 desc_indices_[i], &ignore, &i_begin_pos, &ignore); 315 }
229 if (i_begin_pos < begin_pos) { 316 // The current variable is textually in scope. Now check whether
230 // The variable we found earlier is in an outer scope 317 // there is another local variable with the same name that shadows
231 // and is shadowed by the current variable. Replace the 318 // or is shadowed by this variable.
232 // descriptor index of the previously found variable 319 String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
233 // with the descriptor index of the current variable. 320 intptr_t indices_len = desc_indices_.length();
234 desc_indices_[i] = cur_idx; 321 bool name_match_found = false;
235 } else { 322 for (int i = 0; i < indices_len; i++) {
236 // The variable we found earlier is in an inner scope 323 if (var_name.Equals(*var_names[i])) {
237 // and shadows the current variable. Skip the current 324 // Found two local variables with the same name. Now determine
238 // variable. (Nothing to do.) 325 // which one is shadowed.
239 } 326 name_match_found = true;
240 break; // Stop looking for name matches. 327 RawLocalVarDescriptors::VarInfo i_var_info;
328 var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
329 if (i_var_info.begin_pos < var_info.begin_pos) {
330 // The variable we found earlier is in an outer scope
331 // and is shadowed by the current variable. Replace the
332 // descriptor index of the previously found variable
333 // with the descriptor index of the current variable.
334 desc_indices_[i] = cur_idx;
335 } else {
336 // The variable we found earlier is in an inner scope
337 // and shadows the current variable. Skip the current
338 // variable. (Nothing to do.)
241 } 339 }
340 break; // Stop looking for name matches.
242 } 341 }
243 if (!name_match_found) { 342 }
244 // No duplicate name found. Add the current descriptor index to the 343 if (!name_match_found) {
245 // list of visible variables. 344 // No duplicate name found. Add the current descriptor index to the
246 desc_indices_.Add(cur_idx); 345 // list of visible variables.
247 var_names.Add(&var_name); 346 desc_indices_.Add(cur_idx);
248 } 347 var_names.Add(&var_name);
249 } 348 }
250 } 349 }
251 } 350 }
351 vars_initialized_ = true;
252 } 352 }
253 353
254 354
255 intptr_t ActivationFrame::NumLocalVariables() { 355 intptr_t ActivationFrame::NumLocalVariables() {
256 GetDescIndices(); 356 GetDescIndices();
257 return desc_indices_.length(); 357 return desc_indices_.length();
258 } 358 }
259 359
260 360
261 void ActivationFrame::VariableAt(intptr_t i, 361 void ActivationFrame::VariableAt(intptr_t i,
262 String* name, 362 String* name,
263 intptr_t* token_pos, 363 intptr_t* token_pos,
264 intptr_t* end_pos, 364 intptr_t* end_pos,
265 Instance* value) { 365 Instance* value) {
266 GetDescIndices(); 366 GetDescIndices();
267 ASSERT(i < desc_indices_.length()); 367 ASSERT(i < desc_indices_.length());
368 intptr_t desc_index = desc_indices_[i];
268 ASSERT(name != NULL); 369 ASSERT(name != NULL);
269 intptr_t desc_index = desc_indices_[i];
270 *name ^= var_descriptors_.GetName(desc_index); 370 *name ^= var_descriptors_.GetName(desc_index);
271 intptr_t scope_id; 371 RawLocalVarDescriptors::VarInfo var_info;
272 var_descriptors_.GetScopeInfo(desc_index, &scope_id, token_pos, end_pos); 372 var_descriptors_.GetInfo(desc_index, &var_info);
373 ASSERT(token_pos != NULL);
374 *token_pos = var_info.begin_pos;
375 ASSERT(end_pos != NULL);
376 *end_pos = var_info.end_pos;
273 ASSERT(value != NULL); 377 ASSERT(value != NULL);
274 *value = GetLocalVarValue(var_descriptors_.GetSlotIndex(desc_index)); 378 if (var_info.kind == RawLocalVarDescriptors::kStackVar) {
379 *value = GetLocalVarValue(var_info.index);
380 } else {
381 ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
382 ASSERT(!ctx_.IsNull());
383 // The context level at the PC/token index of this activation frame.
384 intptr_t frame_ctx_level = ContextLevel();
385 // The context level of the variable.
386 intptr_t var_ctx_level = var_info.scope_id;
387 intptr_t level_diff = frame_ctx_level - var_ctx_level;
388 intptr_t ctx_slot = var_info.index;
389 if (level_diff == 0) {
390 *value = ctx_.At(ctx_slot);
391 } else {
392 ASSERT(level_diff > 0);
393 Context& ctx = Context::Handle(ctx_.raw());
394 while (level_diff > 0) {
395 ASSERT(!ctx.IsNull());
396 level_diff--;
397 ctx = ctx.parent();
398 }
399 ASSERT(!ctx.IsNull());
400 *value = ctx.At(ctx_slot);
401 }
402 }
275 } 403 }
276 404
277 405
278 RawArray* ActivationFrame::GetLocalVariables() { 406 RawArray* ActivationFrame::GetLocalVariables() {
279 GetDescIndices(); 407 GetDescIndices();
280 intptr_t num_variables = desc_indices_.length(); 408 intptr_t num_variables = desc_indices_.length();
281 String& var_name = String::Handle(); 409 String& var_name = String::Handle();
282 Instance& value = Instance::Handle(); 410 Instance& value = Instance::Handle();
283 const Array& list = Array::Handle(Array::New(2 * num_variables)); 411 const Array& list = Array::Handle(Array::New(2 * num_variables));
284 for (int i = 0; i < num_variables; i++) { 412 for (int i = 0; i < num_variables; i++) {
285 var_name = var_descriptors_.GetName(i); 413 intptr_t ignore;
414 VariableAt(i, &var_name, &ignore, &ignore, &value);
286 list.SetAt(2 * i, var_name); 415 list.SetAt(2 * i, var_name);
287 value = GetLocalVarValue(var_descriptors_.GetSlotIndex(i));
288 list.SetAt((2 * i) + 1, value); 416 list.SetAt((2 * i) + 1, value);
289 } 417 }
290 return list.raw(); 418 return list.raw();
291 } 419 }
292 420
293 421
294 const char* ActivationFrame::ToCString() { 422 const char* ActivationFrame::ToCString() {
295 const char* kFormat = "Function: '%s' url: '%s' line: %d"; 423 const char* kFormat = "Function: '%s' url: '%s' line: %d";
296 424
297 const Function& func = DartFunction(); 425 const Function& func = DartFunction();
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 DebuggerEvent event; 730 DebuggerEvent event;
603 event.type = kBreakpointResolved; 731 event.type = kBreakpointResolved;
604 event.breakpoint = bpt; 732 event.breakpoint = bpt;
605 (*event_handler_)(&event); 733 (*event_handler_)(&event);
606 } 734 }
607 } 735 }
608 736
609 737
610 DebuggerStackTrace* Debugger::CollectStackTrace() { 738 DebuggerStackTrace* Debugger::CollectStackTrace() {
611 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); 739 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
740 Context& ctx = Context::Handle(Isolate::Current()->top_context());
612 DartFrameIterator iterator; 741 DartFrameIterator iterator;
613 StackFrame* frame = iterator.NextFrame(); 742 StackFrame* frame = iterator.NextFrame();
614 while (frame != NULL) { 743 while (frame != NULL) {
615 ASSERT(frame->IsValid()); 744 ASSERT(frame->IsValid());
616 ASSERT(frame->IsDartFrame()); 745 ASSERT(frame->IsDartFrame());
617 ActivationFrame* activation = 746 ActivationFrame* activation =
618 new ActivationFrame(frame->pc(), frame->fp(), frame->sp()); 747 new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), ctx);
748 ctx = activation->CallerContext();
619 stack_trace->AddActivation(activation); 749 stack_trace->AddActivation(activation);
620 frame = iterator.NextFrame(); 750 frame = iterator.NextFrame();
621 } 751 }
622 return stack_trace; 752 return stack_trace;
623 } 753 }
624 754
625 755
626 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { 756 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) {
627 exc_pause_info_ = pause_info; 757 exc_pause_info_ = pause_info;
628 } 758 }
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 } 1464 }
1335 1465
1336 1466
1337 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1467 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1338 ASSERT(bpt->next() == NULL); 1468 ASSERT(bpt->next() == NULL);
1339 bpt->set_next(code_breakpoints_); 1469 bpt->set_next(code_breakpoints_);
1340 code_breakpoints_ = bpt; 1470 code_breakpoints_ = bpt;
1341 } 1471 }
1342 1472
1343 } // namespace dart 1473 } // namespace dart
OLDNEW
« 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