OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |