| 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 |