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/deopt_instructions.h" |
14 #include "vm/flags.h" | 14 #include "vm/flags.h" |
15 #include "vm/globals.h" | 15 #include "vm/globals.h" |
16 #include "vm/longjump.h" | 16 #include "vm/longjump.h" |
17 #include "vm/json_stream.h" | 17 #include "vm/json_stream.h" |
18 #include "vm/object.h" | 18 #include "vm/object.h" |
19 #include "vm/object_store.h" | 19 #include "vm/object_store.h" |
20 #include "vm/os.h" | 20 #include "vm/os.h" |
21 #include "vm/port.h" | 21 #include "vm/port.h" |
| 22 #include "vm/service.h" |
22 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
23 #include "vm/stub_code.h" | 24 #include "vm/stub_code.h" |
24 #include "vm/symbols.h" | 25 #include "vm/symbols.h" |
25 #include "vm/visitor.h" | 26 #include "vm/visitor.h" |
26 | 27 |
27 | 28 |
28 namespace dart { | 29 namespace dart { |
29 | 30 |
30 DEFINE_FLAG(bool, enable_debugger, true, "Enables debugger step checks"); | 31 DEFINE_FLAG(bool, enable_debugger, true, "Enables debugger step checks"); |
31 DEFINE_FLAG(bool, show_invisible_frames, false, | 32 DEFINE_FLAG(bool, show_invisible_frames, false, |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 context_level_(-1), | 186 context_level_(-1), |
186 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 187 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
187 deopt_frame_offset_(deopt_frame_offset), | 188 deopt_frame_offset_(deopt_frame_offset), |
188 vars_initialized_(false), | 189 vars_initialized_(false), |
189 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 190 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
190 desc_indices_(8), | 191 desc_indices_(8), |
191 pc_desc_(PcDescriptors::ZoneHandle()) { | 192 pc_desc_(PcDescriptors::ZoneHandle()) { |
192 } | 193 } |
193 | 194 |
194 | 195 |
| 196 bool Debugger::HasEventHandler() { |
| 197 return (event_handler_ != NULL) || Service::NeedsDebuggerEvents(); |
| 198 } |
| 199 |
| 200 |
| 201 void Debugger::InvokeEventHandler(DebuggerEvent* event) { |
| 202 ASSERT(HasEventHandler()); |
| 203 |
| 204 // Give the event to the Service first, as the debugger event handler |
| 205 // may go into a message loop and the Service will not. |
| 206 if (Service::NeedsDebuggerEvents()) { |
| 207 Service::HandleDebuggerEvent(event); |
| 208 } |
| 209 |
| 210 if (event_handler_ != NULL) { |
| 211 (*event_handler_)(event); |
| 212 } |
| 213 } |
| 214 |
| 215 |
195 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { | 216 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { |
196 if (event_handler_ != NULL) { | 217 if (HasEventHandler()) { |
197 DebuggerEvent event(type); | 218 DebuggerEvent event(isolate_, type); |
198 event.set_isolate_id(isolate_id_); | |
199 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); | 219 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); |
200 if (type == DebuggerEvent::kIsolateInterrupted) { | 220 if (type == DebuggerEvent::kIsolateInterrupted) { |
201 DebuggerStackTrace* trace = CollectStackTrace(); | 221 DebuggerStackTrace* trace = CollectStackTrace(); |
202 ASSERT(trace->Length() > 0); | 222 ASSERT(trace->Length() > 0); |
203 ASSERT(stack_trace_ == NULL); | 223 ASSERT(stack_trace_ == NULL); |
204 stack_trace_ = trace; | 224 stack_trace_ = trace; |
205 resume_action_ = kContinue; | 225 resume_action_ = kContinue; |
206 Pause(&event); | 226 Pause(&event); |
207 HandleSteppingRequest(trace); | 227 HandleSteppingRequest(trace); |
208 stack_trace_ = NULL; | 228 stack_trace_ = NULL; |
209 } else { | 229 } else { |
210 (*event_handler_)(&event); | 230 InvokeEventHandler(&event); |
211 } | 231 } |
212 } | 232 } |
213 } | 233 } |
214 | 234 |
215 | 235 |
216 void Debugger::SignalIsolateInterrupted() { | 236 void Debugger::SignalIsolateInterrupted() { |
217 if (event_handler_ != NULL) { | 237 if (HasEventHandler()) { |
218 Debugger* debugger = Isolate::Current()->debugger(); | 238 Debugger* debugger = Isolate::Current()->debugger(); |
219 ASSERT(debugger != NULL); | 239 ASSERT(debugger != NULL); |
220 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); | 240 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); |
221 } | 241 } |
222 } | 242 } |
223 | 243 |
224 | 244 |
225 const char* Debugger::QualifiedFunctionName(const Function& func) { | 245 const char* Debugger::QualifiedFunctionName(const Function& func) { |
226 const String& func_name = String::Handle(func.name()); | 246 const String& func_name = String::Handle(func.name()); |
227 Class& func_class = Class::Handle(func.Owner()); | 247 Class& func_class = Class::Handle(func.Owner()); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 return "IsolateInterrupted"; | 523 return "IsolateInterrupted"; |
504 default: | 524 default: |
505 UNREACHABLE(); | 525 UNREACHABLE(); |
506 return "Unknown"; | 526 return "Unknown"; |
507 } | 527 } |
508 } | 528 } |
509 | 529 |
510 | 530 |
511 void DebuggerEvent::PrintJSON(JSONStream* js) const { | 531 void DebuggerEvent::PrintJSON(JSONStream* js) const { |
512 JSONObject jsobj(js); | 532 JSONObject jsobj(js); |
513 jsobj.AddProperty("type", "DebuggerEvent"); | 533 jsobj.AddProperty("type", "ServiceEvent"); |
514 // TODO(turnidge): Drop the 'id' for things like DebuggerEvent. | 534 // TODO(turnidge): Drop the 'id' for things like DebuggerEvent. |
515 jsobj.AddProperty("id", ""); | 535 jsobj.AddProperty("id", ""); |
516 // TODO(turnidge): Add 'isolate'. | |
517 jsobj.AddProperty("eventType", EventTypeToCString(type())); | 536 jsobj.AddProperty("eventType", EventTypeToCString(type())); |
| 537 jsobj.AddProperty("isolate", isolate()); |
518 if (type() == kBreakpointResolved || type() == kBreakpointReached) { | 538 if (type() == kBreakpointResolved || type() == kBreakpointReached) { |
519 jsobj.AddProperty("breakpoint", breakpoint()); | 539 jsobj.AddProperty("breakpoint", breakpoint()); |
520 } | 540 } |
521 if (type() == kExceptionThrown) { | 541 if (type() == kExceptionThrown) { |
522 jsobj.AddProperty("exception", *(exception())); | 542 jsobj.AddProperty("exception", *(exception())); |
523 } | 543 } |
524 } | 544 } |
525 | 545 |
526 | 546 |
527 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | 547 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 } | 1225 } |
1206 bpt = new CodeBreakpoint(code, i); | 1226 bpt = new CodeBreakpoint(code, i); |
1207 RegisterCodeBreakpoint(bpt); | 1227 RegisterCodeBreakpoint(bpt); |
1208 bpt->Enable(); | 1228 bpt->Enable(); |
1209 } | 1229 } |
1210 } | 1230 } |
1211 } | 1231 } |
1212 | 1232 |
1213 | 1233 |
1214 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1234 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
1215 if (event_handler_ != NULL) { | 1235 if (HasEventHandler()) { |
1216 DebuggerEvent event(DebuggerEvent::kBreakpointResolved); | 1236 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); |
1217 event.set_breakpoint(bpt); | 1237 event.set_breakpoint(bpt); |
1218 (*event_handler_)(&event); | 1238 InvokeEventHandler(&event); |
1219 } | 1239 } |
1220 } | 1240 } |
1221 | 1241 |
1222 | 1242 |
1223 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1243 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
1224 uword pc, | 1244 uword pc, |
1225 StackFrame* frame, | 1245 StackFrame* frame, |
1226 const Code& code, | 1246 const Code& code, |
1227 const Array& deopt_frame, | 1247 const Array& deopt_frame, |
1228 intptr_t deopt_frame_offset, | 1248 intptr_t deopt_frame_offset, |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1493 } | 1513 } |
1494 | 1514 |
1495 | 1515 |
1496 void Debugger::SignalExceptionThrown(const Instance& exc) { | 1516 void Debugger::SignalExceptionThrown(const Instance& exc) { |
1497 // We ignore this exception event when the VM is executing code invoked | 1517 // We ignore this exception event when the VM is executing code invoked |
1498 // by the debugger to evaluate variables values, when we see a nested | 1518 // by the debugger to evaluate variables values, when we see a nested |
1499 // breakpoint or exception event, or if the debugger is not | 1519 // breakpoint or exception event, or if the debugger is not |
1500 // interested in exception events. | 1520 // interested in exception events. |
1501 if (ignore_breakpoints_ || | 1521 if (ignore_breakpoints_ || |
1502 IsPaused() || | 1522 IsPaused() || |
1503 (event_handler_ == NULL) || | 1523 (!HasEventHandler()) || |
1504 (exc_pause_info_ == kNoPauseOnExceptions)) { | 1524 (exc_pause_info_ == kNoPauseOnExceptions)) { |
1505 return; | 1525 return; |
1506 } | 1526 } |
1507 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1527 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
1508 if (!ShouldPauseOnException(stack_trace, exc)) { | 1528 if (!ShouldPauseOnException(stack_trace, exc)) { |
1509 return; | 1529 return; |
1510 } | 1530 } |
1511 DebuggerEvent event(DebuggerEvent::kExceptionThrown); | 1531 DebuggerEvent event(isolate_, DebuggerEvent::kExceptionThrown); |
1512 event.set_exception(&exc); | 1532 event.set_exception(&exc); |
1513 ASSERT(stack_trace_ == NULL); | 1533 ASSERT(stack_trace_ == NULL); |
1514 stack_trace_ = stack_trace; | 1534 stack_trace_ = stack_trace; |
1515 Pause(&event); | 1535 Pause(&event); |
1516 stack_trace_ = NULL; | 1536 stack_trace_ = NULL; |
1517 } | 1537 } |
1518 | 1538 |
1519 | 1539 |
1520 // Given a function and a token range, return the best fit | 1540 // Given a function and a token range, return the best fit |
1521 // token position to set a breakpoint. The best fit is the safe point | 1541 // token position to set a breakpoint. The best fit is the safe point |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2131 prefix_name = String::Concat(prefix_name, Symbols::Dot()); | 2151 prefix_name = String::Concat(prefix_name, Symbols::Dot()); |
2132 for (intptr_t i = 0; i < prefix.num_imports(); i++) { | 2152 for (intptr_t i = 0; i < prefix.num_imports(); i++) { |
2133 imported = prefix.GetLibrary(i); | 2153 imported = prefix.GetLibrary(i); |
2134 CollectLibraryFields(field_list, imported, prefix_name, false); | 2154 CollectLibraryFields(field_list, imported, prefix_name, false); |
2135 } | 2155 } |
2136 } | 2156 } |
2137 return Array::MakeArray(field_list); | 2157 return Array::MakeArray(field_list); |
2138 } | 2158 } |
2139 | 2159 |
2140 | 2160 |
| 2161 // static |
2141 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 2162 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
2142 ASSERT(visitor != NULL); | 2163 ASSERT(visitor != NULL); |
2143 SourceBreakpoint* bpt = src_breakpoints_; | 2164 SourceBreakpoint* bpt = src_breakpoints_; |
2144 while (bpt != NULL) { | 2165 while (bpt != NULL) { |
2145 bpt->VisitObjectPointers(visitor); | 2166 bpt->VisitObjectPointers(visitor); |
2146 bpt = bpt->next(); | 2167 bpt = bpt->next(); |
2147 } | 2168 } |
2148 CodeBreakpoint* cbpt = code_breakpoints_; | 2169 CodeBreakpoint* cbpt = code_breakpoints_; |
2149 while (cbpt != NULL) { | 2170 while (cbpt != NULL) { |
2150 cbpt->VisitObjectPointers(visitor); | 2171 cbpt->VisitObjectPointers(visitor); |
2151 cbpt = cbpt->next(); | 2172 cbpt = cbpt->next(); |
2152 } | 2173 } |
2153 } | 2174 } |
2154 | 2175 |
2155 | 2176 |
| 2177 // static |
2156 void Debugger::SetEventHandler(EventHandler* handler) { | 2178 void Debugger::SetEventHandler(EventHandler* handler) { |
2157 event_handler_ = handler; | 2179 event_handler_ = handler; |
2158 } | 2180 } |
2159 | 2181 |
2160 | 2182 |
2161 void Debugger::Pause(DebuggerEvent* event) { | 2183 void Debugger::Pause(DebuggerEvent* event) { |
2162 ASSERT(!IsPaused()); // No recursive pausing. | 2184 ASSERT(!IsPaused()); // No recursive pausing. |
2163 ASSERT(obj_cache_ == NULL); | 2185 ASSERT(obj_cache_ == NULL); |
2164 | 2186 |
2165 pause_event_ = event; | 2187 pause_event_ = event; |
2166 obj_cache_ = new RemoteObjectCache(64); | 2188 obj_cache_ = new RemoteObjectCache(64); |
2167 | 2189 |
2168 (*event_handler_)(event); | 2190 InvokeEventHandler(event); |
2169 | 2191 |
2170 pause_event_ = NULL; | 2192 pause_event_ = NULL; |
2171 obj_cache_ = NULL; // Zone allocated | 2193 obj_cache_ = NULL; // Zone allocated |
2172 } | 2194 } |
2173 | 2195 |
2174 | 2196 |
2175 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { | 2197 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { |
2176 stepping_fp_ = 0; | 2198 stepping_fp_ = 0; |
2177 if (resume_action_ == kSingleStep) { | 2199 if (resume_action_ == kSingleStep) { |
2178 isolate_->set_single_step(true); | 2200 isolate_->set_single_step(true); |
(...skipping 26 matching lines...) Expand all Loading... |
2205 } | 2227 } |
2206 | 2228 |
2207 | 2229 |
2208 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, | 2230 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, |
2209 SourceBreakpoint* bpt) { | 2231 SourceBreakpoint* bpt) { |
2210 resume_action_ = kContinue; | 2232 resume_action_ = kContinue; |
2211 stepping_fp_ = 0; | 2233 stepping_fp_ = 0; |
2212 isolate_->set_single_step(false); | 2234 isolate_->set_single_step(false); |
2213 ASSERT(!IsPaused()); | 2235 ASSERT(!IsPaused()); |
2214 ASSERT(obj_cache_ == NULL); | 2236 ASSERT(obj_cache_ == NULL); |
2215 DebuggerEvent event(DebuggerEvent::kBreakpointReached); | 2237 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); |
2216 event.set_top_frame(top_frame); | 2238 event.set_top_frame(top_frame); |
2217 event.set_breakpoint(bpt); | 2239 event.set_breakpoint(bpt); |
2218 Pause(&event); | 2240 Pause(&event); |
2219 } | 2241 } |
2220 | 2242 |
2221 | 2243 |
2222 void Debugger::DebuggerStepCallback() { | 2244 void Debugger::DebuggerStepCallback() { |
2223 ASSERT(isolate_->single_step()); | 2245 ASSERT(isolate_->single_step()); |
2224 // We can't get here unless the debugger event handler enabled | 2246 // We can't get here unless the debugger event handler enabled |
2225 // single stepping. | 2247 // single stepping. |
2226 ASSERT(event_handler_ != NULL); | 2248 ASSERT(HasEventHandler()); |
2227 // Don't pause recursively. | 2249 // Don't pause recursively. |
2228 if (IsPaused()) return; | 2250 if (IsPaused()) return; |
2229 | 2251 |
2230 // Check whether we are in a Dart function that the user is | 2252 // Check whether we are in a Dart function that the user is |
2231 // interested in. If we saved the frame pointer of a stack frame | 2253 // interested in. If we saved the frame pointer of a stack frame |
2232 // the user is interested in, we ignore the single step if we are | 2254 // the user is interested in, we ignore the single step if we are |
2233 // in a callee of that frame. Note that we assume that the stack | 2255 // in a callee of that frame. Note that we assume that the stack |
2234 // grows towards lower addresses. | 2256 // grows towards lower addresses. |
2235 ActivationFrame* frame = TopDartFrame(); | 2257 ActivationFrame* frame = TopDartFrame(); |
2236 ASSERT(frame != NULL); | 2258 ASSERT(frame != NULL); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2276 SignalPausedEvent(frame, NULL); | 2298 SignalPausedEvent(frame, NULL); |
2277 HandleSteppingRequest(stack_trace_); | 2299 HandleSteppingRequest(stack_trace_); |
2278 stack_trace_ = NULL; | 2300 stack_trace_ = NULL; |
2279 } | 2301 } |
2280 | 2302 |
2281 | 2303 |
2282 void Debugger::SignalBpReached() { | 2304 void Debugger::SignalBpReached() { |
2283 // We ignore this breakpoint when the VM is executing code invoked | 2305 // We ignore this breakpoint when the VM is executing code invoked |
2284 // by the debugger to evaluate variables values, or when we see a nested | 2306 // by the debugger to evaluate variables values, or when we see a nested |
2285 // breakpoint or exception event. | 2307 // breakpoint or exception event. |
2286 if (ignore_breakpoints_ || IsPaused() || (event_handler_ == NULL)) { | 2308 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { |
2287 return; | 2309 return; |
2288 } | 2310 } |
2289 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2311 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
2290 ASSERT(stack_trace->Length() > 0); | 2312 ASSERT(stack_trace->Length() > 0); |
2291 ActivationFrame* top_frame = stack_trace->FrameAt(0); | 2313 ActivationFrame* top_frame = stack_trace->FrameAt(0); |
2292 ASSERT(top_frame != NULL); | 2314 ASSERT(top_frame != NULL); |
2293 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); | 2315 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); |
2294 ASSERT(bpt != NULL); | 2316 ASSERT(bpt != NULL); |
2295 | 2317 |
2296 if (FLAG_verbose_debug) { | 2318 if (FLAG_verbose_debug) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2562 } | 2584 } |
2563 | 2585 |
2564 | 2586 |
2565 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2587 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2566 ASSERT(bpt->next() == NULL); | 2588 ASSERT(bpt->next() == NULL); |
2567 bpt->set_next(code_breakpoints_); | 2589 bpt->set_next(code_breakpoints_); |
2568 code_breakpoints_ = bpt; | 2590 code_breakpoints_ = bpt; |
2569 } | 2591 } |
2570 | 2592 |
2571 } // namespace dart | 2593 } // namespace dart |
OLD | NEW |