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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
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 "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
11 #include "vm/compiler.h" 11 #include "vm/compiler.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/deopt_instructions.h"
13 #include "vm/flags.h" 14 #include "vm/flags.h"
14 #include "vm/globals.h" 15 #include "vm/globals.h"
15 #include "vm/longjump.h" 16 #include "vm/longjump.h"
16 #include "vm/object.h" 17 #include "vm/object.h"
17 #include "vm/object_store.h" 18 #include "vm/object_store.h"
18 #include "vm/os.h" 19 #include "vm/os.h"
19 #include "vm/port.h" 20 #include "vm/port.h"
20 #include "vm/stack_frame.h" 21 #include "vm/stack_frame.h"
21 #include "vm/stub_code.h" 22 #include "vm/stub_code.h"
22 #include "vm/symbols.h" 23 #include "vm/symbols.h"
23 #include "vm/visitor.h" 24 #include "vm/visitor.h"
24 25
25 26
26 namespace dart { 27 namespace dart {
27 28
28 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); 29 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
30 DEFINE_FLAG(bool, use_new_stacktrace, true,
31 "Use new stacktrace creation");
29 32
30 33
31 Debugger::EventHandler* Debugger::event_handler_ = NULL; 34 Debugger::EventHandler* Debugger::event_handler_ = NULL;
32 35
33 36
34 class RemoteObjectCache : public ZoneAllocated { 37 class RemoteObjectCache : public ZoneAllocated {
35 public: 38 public:
36 explicit RemoteObjectCache(intptr_t initial_size); 39 explicit RemoteObjectCache(intptr_t initial_size);
37 intptr_t AddObject(const Object& obj); 40 intptr_t AddObject(const Object& obj);
38 RawObject* GetObj(intptr_t obj_id) const; 41 RawObject* GetObj(intptr_t obj_id) const;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 129
127 ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp, const Code& code) 130 ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp, const Code& code)
128 : pc_(pc), fp_(fp), sp_(sp), 131 : pc_(pc), fp_(fp), sp_(sp),
129 ctx_(Context::ZoneHandle()), 132 ctx_(Context::ZoneHandle()),
130 code_(Code::ZoneHandle(code.raw())), 133 code_(Code::ZoneHandle(code.raw())),
131 function_(Function::ZoneHandle(code.function())), 134 function_(Function::ZoneHandle(code.function())),
132 token_pos_(-1), 135 token_pos_(-1),
133 pc_desc_index_(-1), 136 pc_desc_index_(-1),
134 line_number_(-1), 137 line_number_(-1),
135 context_level_(-1), 138 context_level_(-1),
139 deopt_frame_(Array::ZoneHandle()),
140 deopt_frame_offset_(0),
136 vars_initialized_(false), 141 vars_initialized_(false),
137 var_descriptors_(LocalVarDescriptors::ZoneHandle()), 142 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
138 desc_indices_(8), 143 desc_indices_(8),
139 pc_desc_(PcDescriptors::ZoneHandle()) { 144 pc_desc_(PcDescriptors::ZoneHandle()) {
140 } 145 }
141 146
142 147
143 void Debugger::SignalIsolateEvent(EventType type) { 148 void Debugger::SignalIsolateEvent(EventType type) {
144 if (event_handler_ != NULL) { 149 if (event_handler_ != NULL) {
145 Debugger* debugger = Isolate::Current()->debugger(); 150 Debugger* debugger = Isolate::Current()->debugger();
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 RawLocalVarDescriptors::VarInfo var_info; 356 RawLocalVarDescriptors::VarInfo var_info;
352 var_descriptors_.GetInfo(i, &var_info); 357 var_descriptors_.GetInfo(i, &var_info);
353 if (var_info.kind == RawLocalVarDescriptors::kSavedEntryContext) { 358 if (var_info.kind == RawLocalVarDescriptors::kSavedEntryContext) {
354 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index)); 359 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index));
355 } 360 }
356 } 361 }
357 return ctx.raw(); 362 return ctx.raw();
358 } 363 }
359 364
360 365
366 RawContext* ActivationFrame::GetSavedEntryContextNew() {
367 if (ctx_.IsNull()) {
368 // We have bailed on providing a context for this frame. Bail for
369 // the caller as well.
370 return Context::null();
371 }
372
373 // Attempt to find a saved context.
374 GetVarDescriptors();
375 intptr_t var_desc_len = var_descriptors_.Length();
376 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.
377 RawLocalVarDescriptors::VarInfo var_info;
378 var_descriptors_.GetInfo(i, &var_info);
379 if (var_info.kind == RawLocalVarDescriptors::kSavedEntryContext) {
380 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index));
381 }
382 }
383
384 // No saved context. Return the current context.
385 return ctx_.raw();
386 }
387
388
361 // Get the saved context if the callee of this activation frame is a 389 // Get the saved context if the callee of this activation frame is a
362 // closure function. 390 // closure function.
363 RawContext* ActivationFrame::GetSavedCurrentContext() { 391 RawContext* ActivationFrame::GetSavedCurrentContext() {
364 GetVarDescriptors(); 392 GetVarDescriptors();
365 intptr_t var_desc_len = var_descriptors_.Length(); 393 intptr_t var_desc_len = var_descriptors_.Length();
366 for (int i = 0; i < var_desc_len; i++) { 394 for (int i = 0; i < var_desc_len; i++) {
367 RawLocalVarDescriptors::VarInfo var_info; 395 RawLocalVarDescriptors::VarInfo var_info;
368 var_descriptors_.GetInfo(i, &var_info); 396 var_descriptors_.GetInfo(i, &var_info);
369 if (var_info.kind == RawLocalVarDescriptors::kSavedCurrentContext) { 397 if (var_info.kind == RawLocalVarDescriptors::kSavedCurrentContext) {
370 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index)); 398 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index));
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 void ActivationFrame::GetDescIndices() { 442 void ActivationFrame::GetDescIndices() {
415 if (vars_initialized_) { 443 if (vars_initialized_) {
416 return; 444 return;
417 } 445 }
418 GetVarDescriptors(); 446 GetVarDescriptors();
419 447
420 // We don't trust variable descriptors in optimized code. 448 // We don't trust variable descriptors in optimized code.
421 // Rather than potentially displaying incorrect values, we 449 // Rather than potentially displaying incorrect values, we
422 // pretend that there are no variables in the frame. 450 // pretend that there are no variables in the frame.
423 // We should be more clever about this in the future. 451 // We should be more clever about this in the future.
424 if (code().is_optimized()) { 452 if (!FLAG_use_new_stacktrace && code().is_optimized()) {
425 vars_initialized_ = true; 453 vars_initialized_ = true;
426 return; 454 return;
427 } 455 }
428 456
429 intptr_t activation_token_pos = TokenPos(); 457 intptr_t activation_token_pos = TokenPos();
430 if (activation_token_pos < 0) { 458 if (activation_token_pos < 0) {
431 // We don't have a token position for this frame, so can't determine 459 // We don't have a token position for this frame, so can't determine
432 // which variables are visible. 460 // which variables are visible.
433 vars_initialized_ = true; 461 vars_initialized_ = true;
434 return; 462 return;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 vars_initialized_ = true; 522 vars_initialized_ = true;
495 } 523 }
496 524
497 525
498 intptr_t ActivationFrame::NumLocalVariables() { 526 intptr_t ActivationFrame::NumLocalVariables() {
499 GetDescIndices(); 527 GetDescIndices();
500 return desc_indices_.length(); 528 return desc_indices_.length();
501 } 529 }
502 530
503 531
532 // TODO(hausner): Handle captured variables.
533 RawInstance* ActivationFrame::GetLocalVarValue(intptr_t slot_index) {
534 if (deopt_frame_.IsNull()) {
535 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
536 return reinterpret_cast<RawInstance*>(
537 *reinterpret_cast<uword*>(var_address));
538 } else {
539 Instance& instance = Instance::Handle();
540 instance ^= deopt_frame_.At(deopt_frame_offset_ + slot_index);
541 return instance.raw();
542 }
543 }
544
545
504 void ActivationFrame::VariableAt(intptr_t i, 546 void ActivationFrame::VariableAt(intptr_t i,
505 String* name, 547 String* name,
506 intptr_t* token_pos, 548 intptr_t* token_pos,
507 intptr_t* end_pos, 549 intptr_t* end_pos,
508 Instance* value) { 550 Instance* value) {
509 GetDescIndices(); 551 GetDescIndices();
510 ASSERT(i < desc_indices_.length()); 552 ASSERT(i < desc_indices_.length());
511 intptr_t desc_index = desc_indices_[i]; 553 intptr_t desc_index = desc_indices_[i];
512 ASSERT(name != NULL); 554 ASSERT(name != NULL);
513 *name ^= var_descriptors_.GetName(desc_index); 555 *name ^= var_descriptors_.GetName(desc_index);
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { 980 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) {
939 if (event_handler_ != NULL) { 981 if (event_handler_ != NULL) {
940 DebuggerEvent event; 982 DebuggerEvent event;
941 event.type = kBreakpointResolved; 983 event.type = kBreakpointResolved;
942 event.breakpoint = bpt; 984 event.breakpoint = bpt;
943 (*event_handler_)(&event); 985 (*event_handler_)(&event);
944 } 986 }
945 } 987 }
946 988
947 989
990 static void PrintStackTraceError(const char* message,
991 ActivationFrame* current_activation,
992 ActivationFrame* callee_activation) {
993 const Function& current = current_activation->function();
994 const Function& callee = callee_activation->function();
995 const Script& script =
996 Script::Handle(Class::Handle(current.Owner()).script());
997 intptr_t line, col;
998 script.GetTokenLocation(current_activation->TokenPos(), &line, &col);
999 OS::PrintErr("Error building stack trace: %s:"
1000 "current function '%s' callee_function '%s' "
1001 " line %" Pd " column %" Pd "\n",
1002 message,
1003 current.ToFullyQualifiedCString(),
1004 callee.ToFullyQualifiedCString(),
1005 line, col);
1006 }
1007
1008
1009 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
1010 uword pc,
1011 StackFrame* frame,
1012 const Code& code,
1013 bool optimized,
1014 ActivationFrame* callee_activation,
1015 const Context& entry_ctx) {
1016 // We never provide both a callee activation and an entry context.
1017 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.
1018 ActivationFrame* activation =
1019 new ActivationFrame(pc, frame->fp(), frame->sp(), code);
1020
1021 // Recover the context for this frame.
1022 if (optimized) {
1023 // Bail out for optimized frames for now.
1024 activation->SetContext(Context::Handle(isolate));
1025
1026 } else if (callee_activation == NULL) {
1027 // No callee. Use incoming entry context. Could be from
1028 // isolate's top context or from an entry frame.
1029 activation->SetContext(entry_ctx);
1030
1031 } else if (callee_activation->function().IsClosureFunction()) {
1032 // If the callee is a closure, we should have stored the context
1033 // in the current frame before making the call.
1034 const Context& closure_call_ctx =
1035 Context::Handle(isolate, activation->GetSavedCurrentContext());
1036 activation->SetContext(closure_call_ctx);
1037
1038 // 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.
1039 if (FLAG_verbose_debug && closure_call_ctx.IsNull()) {
1040 PrintStackTraceError(
1041 "Expected to find saved context for call to closure function",
1042 activation, callee_activation);
1043 }
1044
1045 } else {
1046 // Use the context provided by our callee. This is either the
1047 // callee's context or a context that was saved in the callee's
1048 // frame.
1049 const Context& callee_ctx =
1050 Context::Handle(isolate, callee_activation->GetSavedEntryContextNew());
1051 activation->SetContext(callee_ctx);
1052 }
1053 return activation;
1054 }
1055
srdjan 2013/10/07 21:36:53 2 lines between functions
turnidge 2013/10/08 17:29:12 Done.
1056 RawArray* Debugger::DeoptimizeToArray(Isolate* isolate,
1057 StackFrame* frame,
1058 const Code& code) {
srdjan 2013/10/07 21:36:53 Fix indent
turnidge 2013/10/08 17:29:12 Done.
1059 ASSERT(code.is_optimized());
1060
1061 // Create the DeoptContext for this deoptimization.
1062 DeoptContext* deopt_context =
1063 new DeoptContext(frame, code,
1064 DeoptContext::kDestIsAllocated,
1065 NULL, NULL);
1066 isolate->set_deopt_context(deopt_context);
1067
1068 deopt_context->FillDestFrame();
1069 deopt_context->MaterializeDeferredObjects();
1070 const Array& dest_frame = Array::Handle(deopt_context->DestFrameAsArray());
1071
1072 isolate->set_deopt_context(NULL);
1073 delete deopt_context;
1074
1075 return dest_frame.raw();
1076 }
1077
1078
1079 DebuggerStackTrace* Debugger::CollectStackTraceNew() {
1080 Isolate* isolate = Isolate::Current();
1081 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
1082 StackFrameIterator iterator(false);
1083 ActivationFrame* current_activation = NULL;
1084 Context& entry_ctx = Context::Handle(isolate->top_context());
1085 for (StackFrame* frame = iterator.NextFrame();
1086 frame != NULL;
1087 frame = iterator.NextFrame()) {
1088 ASSERT(frame->IsValid());
1089 if (frame->IsEntryFrame()) {
1090 current_activation = NULL;
1091 entry_ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext();
1092
1093 } else if (frame->IsDartFrame()) {
1094 const Code& code = Code::Handle(isolate, frame->LookupDartCode());
1095 if (code.is_optimized()) {
1096 const Array& deopt_frame =
1097 Array::Handle(DeoptimizeToArray(isolate, frame, code));
1098 for (InlinedFunctionsIterator it(code, frame->pc());
1099 !it.Done();
1100 it.Advance()) {
1101 const Code& inlined_code = Code::Handle(isolate, it.code());
1102 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
1103 current_activation = CollectDartFrame(isolate,
1104 it.pc(),
1105 frame,
1106 inlined_code,
1107 true,
1108 current_activation,
1109 entry_ctx);
1110 current_activation->SetDeoptFrame(deopt_frame, deopt_frame_offset);
1111 stack_trace->AddActivation(current_activation);
1112 entry_ctx = Context::null(); // Only use entry context once.
1113 }
1114 } else {
1115 current_activation = CollectDartFrame(isolate,
1116 frame->pc(),
1117 frame,
1118 code,
1119 false,
1120 current_activation,
1121 entry_ctx);
1122 stack_trace->AddActivation(current_activation);
1123 entry_ctx = Context::null(); // Only use entry context once.
1124 }
1125 }
1126 }
1127 return stack_trace;
1128 }
1129
1130
1131
948 DebuggerStackTrace* Debugger::CollectStackTrace() { 1132 DebuggerStackTrace* Debugger::CollectStackTrace() {
1133 if (FLAG_use_new_stacktrace) {
1134 // Guard new stack trace generation under a flag in case there are
1135 // problems rolling it out.
1136 return CollectStackTraceNew();
1137 }
949 Isolate* isolate = Isolate::Current(); 1138 Isolate* isolate = Isolate::Current();
950 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); 1139 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
951 Context& ctx = Context::Handle(isolate->top_context()); 1140 Context& ctx = Context::Handle(isolate->top_context());
952 Code& code = Code::Handle(isolate); 1141 Code& code = Code::Handle(isolate);
953 StackFrameIterator iterator(false); 1142 StackFrameIterator iterator(false);
954 ActivationFrame* callee_activation = NULL; 1143 ActivationFrame* callee_activation = NULL;
955 bool optimized_frame_found = false; 1144 bool optimized_frame_found = false;
956 for (StackFrame* frame = iterator.NextFrame(); 1145 for (StackFrame* frame = iterator.NextFrame();
957 frame != NULL; 1146 frame != NULL;
958 frame = iterator.NextFrame()) { 1147 frame = iterator.NextFrame()) {
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after
1877 } 2066 }
1878 2067
1879 2068
1880 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 2069 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1881 ASSERT(bpt->next() == NULL); 2070 ASSERT(bpt->next() == NULL);
1882 bpt->set_next(code_breakpoints_); 2071 bpt->set_next(code_breakpoints_);
1883 code_breakpoints_ = bpt; 2072 code_breakpoints_ = bpt;
1884 } 2073 }
1885 2074
1886 } // namespace dart 2075 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698