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" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 token_pos_ = token_pos; | 92 token_pos_ = token_pos; |
93 end_token_pos_ = token_pos; | 93 end_token_pos_ = token_pos; |
94 line_number_ = -1; // Recalcualte lazily. | 94 line_number_ = -1; // Recalcualte lazily. |
95 is_resolved_ = true; | 95 is_resolved_ = true; |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 // TODO(hausner): Get rid of library parameter. A source breakpoint location | 99 // TODO(hausner): Get rid of library parameter. A source breakpoint location |
100 // does not imply a library, since the same source code can be included | 100 // does not imply a library, since the same source code can be included |
101 // in more than one library, e.g. the text location of mixin functions. | 101 // in more than one library, e.g. the text location of mixin functions. |
102 void SourceBreakpoint::GetCodeLocation( | 102 void SourceBreakpoint::GetCodeLocation(Library* lib, |
103 Library* lib, | 103 Script* script, |
104 Script* script, | 104 intptr_t* pos) { |
105 intptr_t* pos) { | |
106 *script = this->script(); | 105 *script = this->script(); |
107 *pos = token_pos_; | 106 *pos = token_pos_; |
108 if (IsResolved()) { | 107 if (IsResolved()) { |
109 const Function& func = Function::Handle(function_); | 108 const Function& func = Function::Handle(function_); |
110 ASSERT(!func.IsNull()); | 109 ASSERT(!func.IsNull()); |
111 const Class& cls = Class::Handle(func.origin()); | 110 const Class& cls = Class::Handle(func.origin()); |
112 *lib = cls.library(); | 111 *lib = cls.library(); |
113 } else { | 112 } else { |
114 *lib = Library::null(); | 113 *lib = Library::null(); |
115 } | 114 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 context_level_(-1), | 184 context_level_(-1), |
186 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 185 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
187 deopt_frame_offset_(deopt_frame_offset), | 186 deopt_frame_offset_(deopt_frame_offset), |
188 vars_initialized_(false), | 187 vars_initialized_(false), |
189 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 188 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
190 desc_indices_(8), | 189 desc_indices_(8), |
191 pc_desc_(PcDescriptors::ZoneHandle()) { | 190 pc_desc_(PcDescriptors::ZoneHandle()) { |
192 } | 191 } |
193 | 192 |
194 | 193 |
195 void Debugger::SignalIsolateEvent(EventType type) { | 194 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { |
196 if (event_handler_ != NULL) { | 195 if (event_handler_ != NULL) { |
197 DebuggerEvent event(type); | 196 DebuggerEvent event(type); |
198 event.isolate_id = isolate_id_; | 197 event.set_isolate_id(isolate_id_); |
199 ASSERT(event.isolate_id != ILLEGAL_ISOLATE_ID); | 198 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); |
200 if (type == kIsolateInterrupted) { | 199 if (type == DebuggerEvent::kIsolateInterrupted) { |
201 DebuggerStackTrace* trace = CollectStackTrace(); | 200 DebuggerStackTrace* trace = CollectStackTrace(); |
202 ASSERT(trace->Length() > 0); | 201 ASSERT(trace->Length() > 0); |
203 ASSERT(stack_trace_ == NULL); | 202 ASSERT(stack_trace_ == NULL); |
204 stack_trace_ = trace; | 203 stack_trace_ = trace; |
205 resume_action_ = kContinue; | 204 resume_action_ = kContinue; |
206 Pause(&event); | 205 Pause(&event); |
207 HandleSteppingRequest(trace); | 206 HandleSteppingRequest(trace); |
208 stack_trace_ = NULL; | 207 stack_trace_ = NULL; |
209 } else { | 208 } else { |
210 (*event_handler_)(&event); | 209 (*event_handler_)(&event); |
211 } | 210 } |
212 } | 211 } |
213 } | 212 } |
214 | 213 |
215 | 214 |
216 void Debugger::SignalIsolateInterrupted() { | 215 void Debugger::SignalIsolateInterrupted() { |
217 if (event_handler_ != NULL) { | 216 if (event_handler_ != NULL) { |
218 Debugger* debugger = Isolate::Current()->debugger(); | 217 Debugger* debugger = Isolate::Current()->debugger(); |
219 ASSERT(debugger != NULL); | 218 ASSERT(debugger != NULL); |
220 debugger->SignalIsolateEvent(kIsolateInterrupted); | 219 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); |
221 } | 220 } |
222 } | 221 } |
223 | 222 |
224 | 223 |
225 const char* Debugger::QualifiedFunctionName(const Function& func) { | 224 const char* Debugger::QualifiedFunctionName(const Function& func) { |
226 const String& func_name = String::Handle(func.name()); | 225 const String& func_name = String::Handle(func.name()); |
227 Class& func_class = Class::Handle(func.Owner()); | 226 Class& func_class = Class::Handle(func.Owner()); |
228 String& class_name = String::Handle(func_class.Name()); | 227 String& class_name = String::Handle(func_class.Name()); |
229 | 228 |
230 const char* kFormat = "%s%s%s"; | 229 const char* kFormat = "%s%s%s"; |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 var_info.index); | 479 var_info.index); |
481 } | 480 } |
482 return GetLocalContextVar(var_info.index); | 481 return GetLocalContextVar(var_info.index); |
483 } | 482 } |
484 } | 483 } |
485 UNREACHABLE(); | 484 UNREACHABLE(); |
486 return Context::null(); | 485 return Context::null(); |
487 } | 486 } |
488 | 487 |
489 | 488 |
| 489 const char* DebuggerEvent::EventTypeToCString(EventType type) { |
| 490 switch (type) { |
| 491 case kBreakpointReached: |
| 492 return "BreakpointReached"; |
| 493 case kBreakpointResolved: |
| 494 return "BreakpointResolved"; |
| 495 case kExceptionThrown: |
| 496 return "ExceptionThrown"; |
| 497 case kIsolateCreated: |
| 498 return "IsolateCreated"; |
| 499 case kIsolateShutdown: |
| 500 return "IsolateShutdown"; |
| 501 case kIsolateInterrupted: |
| 502 return "IsolateInterrupted"; |
| 503 default: |
| 504 UNREACHABLE(); |
| 505 return "Unknown"; |
| 506 } |
| 507 } |
| 508 |
| 509 |
| 510 void DebuggerEvent::PrintJSON(JSONStream* js) const { |
| 511 JSONObject jsobj(js); |
| 512 jsobj.AddProperty("type", "DebuggerEvent"); |
| 513 // TODO(turnidge): Drop the 'id' for things like DebuggerEvent. |
| 514 jsobj.AddProperty("id", ""); |
| 515 // TODO(turnidge): Add 'isolate'. |
| 516 jsobj.AddProperty("eventType", EventTypeToCString(type())); |
| 517 if (type() == kBreakpointResolved || type() == kBreakpointReached) { |
| 518 jsobj.AddProperty("breakpoint", breakpoint()); |
| 519 } |
| 520 if (type() == kExceptionThrown) { |
| 521 jsobj.AddProperty("exception", *(exception())); |
| 522 } |
| 523 } |
| 524 |
| 525 |
490 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | 526 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( |
491 const Instance& exc_obj) const { | 527 const Instance& exc_obj) const { |
492 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | 528 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); |
493 Array& handled_types = Array::Handle(); | 529 Array& handled_types = Array::Handle(); |
494 AbstractType& type = Type::Handle(); | 530 AbstractType& type = Type::Handle(); |
495 const TypeArguments& no_instantiator = TypeArguments::Handle(); | 531 const TypeArguments& no_instantiator = TypeArguments::Handle(); |
496 for (intptr_t frame_index = 0; | 532 for (intptr_t frame_index = 0; |
497 frame_index < Length(); | 533 frame_index < Length(); |
498 frame_index++) { | 534 frame_index++) { |
499 ActivationFrame* frame = FrameAt(frame_index); | 535 ActivationFrame* frame = FrameAt(frame_index); |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 src_breakpoints_ = src_breakpoints_->next(); | 1059 src_breakpoints_ = src_breakpoints_->next(); |
1024 delete bpt; | 1060 delete bpt; |
1025 } | 1061 } |
1026 while (code_breakpoints_ != NULL) { | 1062 while (code_breakpoints_ != NULL) { |
1027 CodeBreakpoint* bpt = code_breakpoints_; | 1063 CodeBreakpoint* bpt = code_breakpoints_; |
1028 code_breakpoints_ = code_breakpoints_->next(); | 1064 code_breakpoints_ = code_breakpoints_->next(); |
1029 bpt->Disable(); | 1065 bpt->Disable(); |
1030 delete bpt; | 1066 delete bpt; |
1031 } | 1067 } |
1032 // Signal isolate shutdown event. | 1068 // Signal isolate shutdown event. |
1033 SignalIsolateEvent(Debugger::kIsolateShutdown); | 1069 SignalIsolateEvent(DebuggerEvent::kIsolateShutdown); |
1034 } | 1070 } |
1035 | 1071 |
1036 | 1072 |
1037 static RawFunction* ResolveLibraryFunction( | 1073 static RawFunction* ResolveLibraryFunction( |
1038 const Library& library, | 1074 const Library& library, |
1039 const String& fname) { | 1075 const String& fname) { |
1040 ASSERT(!library.IsNull()); | 1076 ASSERT(!library.IsNull()); |
1041 const Object& object = Object::Handle(library.ResolveName(fname)); | 1077 const Object& object = Object::Handle(library.ResolveName(fname)); |
1042 if (!object.IsNull() && object.IsFunction()) { | 1078 if (!object.IsNull() && object.IsFunction()) { |
1043 return Function::Cast(object).raw(); | 1079 return Function::Cast(object).raw(); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 bpt = new CodeBreakpoint(code, i); | 1205 bpt = new CodeBreakpoint(code, i); |
1170 RegisterCodeBreakpoint(bpt); | 1206 RegisterCodeBreakpoint(bpt); |
1171 bpt->Enable(); | 1207 bpt->Enable(); |
1172 } | 1208 } |
1173 } | 1209 } |
1174 } | 1210 } |
1175 | 1211 |
1176 | 1212 |
1177 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1213 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
1178 if (event_handler_ != NULL) { | 1214 if (event_handler_ != NULL) { |
1179 DebuggerEvent event(kBreakpointResolved); | 1215 DebuggerEvent event(DebuggerEvent::kBreakpointResolved); |
1180 event.breakpoint = bpt; | 1216 event.set_breakpoint(bpt); |
1181 (*event_handler_)(&event); | 1217 (*event_handler_)(&event); |
1182 } | 1218 } |
1183 } | 1219 } |
1184 | 1220 |
1185 | 1221 |
1186 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1222 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
1187 uword pc, | 1223 uword pc, |
1188 StackFrame* frame, | 1224 StackFrame* frame, |
1189 const Code& code_param, | 1225 const Code& code_param, |
1190 const Array& deopt_frame, | 1226 const Array& deopt_frame, |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 if (ignore_breakpoints_ || | 1509 if (ignore_breakpoints_ || |
1474 IsPaused() || | 1510 IsPaused() || |
1475 (event_handler_ == NULL) || | 1511 (event_handler_ == NULL) || |
1476 (exc_pause_info_ == kNoPauseOnExceptions)) { | 1512 (exc_pause_info_ == kNoPauseOnExceptions)) { |
1477 return; | 1513 return; |
1478 } | 1514 } |
1479 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1515 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
1480 if (!ShouldPauseOnException(stack_trace, exc)) { | 1516 if (!ShouldPauseOnException(stack_trace, exc)) { |
1481 return; | 1517 return; |
1482 } | 1518 } |
1483 DebuggerEvent event(kExceptionThrown); | 1519 DebuggerEvent event(DebuggerEvent::kExceptionThrown); |
1484 event.exception = &exc; | 1520 event.set_exception(&exc); |
1485 ASSERT(stack_trace_ == NULL); | 1521 ASSERT(stack_trace_ == NULL); |
1486 stack_trace_ = stack_trace; | 1522 stack_trace_ = stack_trace; |
1487 Pause(&event); | 1523 Pause(&event); |
1488 stack_trace_ = NULL; | 1524 stack_trace_ = NULL; |
1489 } | 1525 } |
1490 | 1526 |
1491 | 1527 |
1492 // Given a function and a token range, return the best fit | 1528 // Given a function and a token range, return the best fit |
1493 // token position to set a breakpoint. The best fit is the safe point | 1529 // token position to set a breakpoint. The best fit is the safe point |
1494 // with the lowest compiled code address within the token range. | 1530 // with the lowest compiled code address within the token range. |
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2159 ActivationFrame* frame = stack_trace->FrameAt(i); | 2195 ActivationFrame* frame = stack_trace->FrameAt(i); |
2160 if (frame->IsDebuggable()) { | 2196 if (frame->IsDebuggable()) { |
2161 stepping_fp_ = frame->fp(); | 2197 stepping_fp_ = frame->fp(); |
2162 break; | 2198 break; |
2163 } | 2199 } |
2164 } | 2200 } |
2165 } | 2201 } |
2166 } | 2202 } |
2167 | 2203 |
2168 | 2204 |
| 2205 // static |
2169 bool Debugger::IsDebuggable(const Function& func) { | 2206 bool Debugger::IsDebuggable(const Function& func) { |
2170 if (!IsDebuggableFunctionKind(func)) { | 2207 if (!IsDebuggableFunctionKind(func)) { |
2171 return false; | 2208 return false; |
2172 } | 2209 } |
2173 const Class& cls = Class::Handle(func.Owner()); | 2210 const Class& cls = Class::Handle(func.Owner()); |
2174 const Library& lib = Library::Handle(cls.library()); | 2211 const Library& lib = Library::Handle(cls.library()); |
2175 return lib.IsDebuggable(); | 2212 return lib.IsDebuggable(); |
2176 } | 2213 } |
2177 | 2214 |
2178 | 2215 |
2179 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, | 2216 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, |
2180 SourceBreakpoint* bpt) { | 2217 SourceBreakpoint* bpt) { |
2181 resume_action_ = kContinue; | 2218 resume_action_ = kContinue; |
2182 stepping_fp_ = 0; | 2219 stepping_fp_ = 0; |
2183 isolate_->set_single_step(false); | 2220 isolate_->set_single_step(false); |
2184 ASSERT(!IsPaused()); | 2221 ASSERT(!IsPaused()); |
2185 ASSERT(obj_cache_ == NULL); | 2222 ASSERT(obj_cache_ == NULL); |
2186 DebuggerEvent event(kBreakpointReached); | 2223 DebuggerEvent event(DebuggerEvent::kBreakpointReached); |
2187 event.top_frame = top_frame; | 2224 event.set_top_frame(top_frame); |
2188 event.breakpoint = bpt; | 2225 event.set_breakpoint(bpt); |
2189 Pause(&event); | 2226 Pause(&event); |
2190 } | 2227 } |
2191 | 2228 |
2192 | 2229 |
2193 void Debugger::DebuggerStepCallback() { | 2230 void Debugger::DebuggerStepCallback() { |
2194 ASSERT(isolate_->single_step()); | 2231 ASSERT(isolate_->single_step()); |
2195 // We can't get here unless the debugger event handler enabled | 2232 // We can't get here unless the debugger event handler enabled |
2196 // single stepping. | 2233 // single stepping. |
2197 ASSERT(event_handler_ != NULL); | 2234 ASSERT(event_handler_ != NULL); |
2198 // Don't pause recursively. | 2235 // Don't pause recursively. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 return; | 2327 return; |
2291 } | 2328 } |
2292 isolate_ = isolate; | 2329 isolate_ = isolate; |
2293 // Use the isolate's control port as the isolate_id for debugging. | 2330 // Use the isolate's control port as the isolate_id for debugging. |
2294 // This port will be used as a unique ID to represet the isolate in the | 2331 // This port will be used as a unique ID to represet the isolate in the |
2295 // debugger wire protocol messages. | 2332 // debugger wire protocol messages. |
2296 isolate_id_ = isolate->main_port(); | 2333 isolate_id_ = isolate->main_port(); |
2297 initialized_ = true; | 2334 initialized_ = true; |
2298 | 2335 |
2299 // Signal isolate creation event. | 2336 // Signal isolate creation event. |
2300 SignalIsolateEvent(Debugger::kIsolateCreated); | 2337 SignalIsolateEvent(DebuggerEvent::kIsolateCreated); |
2301 } | 2338 } |
2302 | 2339 |
2303 | 2340 |
2304 // Return innermost closure contained in 'function' that contains | 2341 // Return innermost closure contained in 'function' that contains |
2305 // the given token position. | 2342 // the given token position. |
2306 RawFunction* Debugger::FindInnermostClosure(const Function& function, | 2343 RawFunction* Debugger::FindInnermostClosure(const Function& function, |
2307 intptr_t token_pos) { | 2344 intptr_t token_pos) { |
2308 const Class& owner = Class::Handle(isolate_, function.Owner()); | 2345 const Class& owner = Class::Handle(isolate_, function.Owner()); |
2309 if (owner.closures() == GrowableObjectArray::null()) { | 2346 if (owner.closures() == GrowableObjectArray::null()) { |
2310 return Function::null(); | 2347 return Function::null(); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2533 } | 2570 } |
2534 | 2571 |
2535 | 2572 |
2536 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2573 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2537 ASSERT(bpt->next() == NULL); | 2574 ASSERT(bpt->next() == NULL); |
2538 bpt->set_next(code_breakpoints_); | 2575 bpt->set_next(code_breakpoints_); |
2539 code_breakpoints_ = bpt; | 2576 code_breakpoints_ = bpt; |
2540 } | 2577 } |
2541 | 2578 |
2542 } // namespace dart | 2579 } // namespace dart |
OLD | NEW |