| 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 #ifndef RUNTIME_VM_DEBUGGER_H_ | 5 #ifndef RUNTIME_VM_DEBUGGER_H_ |
| 6 #define RUNTIME_VM_DEBUGGER_H_ | 6 #define RUNTIME_VM_DEBUGGER_H_ |
| 7 | 7 |
| 8 #include "include/dart_tools_api.h" | 8 #include "include/dart_tools_api.h" |
| 9 | 9 |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/port.h" | 11 #include "vm/port.h" |
| 12 #include "vm/service_event.h" | 12 #include "vm/service_event.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 class CodeBreakpoint; | 16 class CodeBreakpoint; |
| 17 class Isolate; | 17 class Isolate; |
| 18 class JSONArray; | 18 class JSONArray; |
| 19 class JSONStream; | 19 class JSONStream; |
| 20 class ObjectPointerVisitor; | 20 class ObjectPointerVisitor; |
| 21 class RemoteObjectCache; | 21 class RemoteObjectCache; |
| 22 class BreakpointLocation; | 22 class BreakpointLocation; |
| 23 class StackFrame; | 23 class StackFrame; |
| 24 | 24 |
| 25 // A user-defined breakpoint, which either fires once, for a particular closure, | 25 // A user-defined breakpoint, which either fires once, for a particular closure, |
| 26 // or always. The API's notion of a breakpoint corresponds to this object. | 26 // or always. The API's notion of a breakpoint corresponds to this object. |
| 27 class Breakpoint { | 27 class Breakpoint { |
| 28 public: | 28 public: |
| 29 Breakpoint(intptr_t id, BreakpointLocation* bpt_location) | 29 Breakpoint(intptr_t id, BreakpointLocation* bpt_location) |
| 30 : id_(id), | 30 : id_(id), |
| 31 kind_(Breakpoint::kNone), | 31 kind_(Breakpoint::kNone), |
| 32 next_(NULL), | 32 next_(NULL), |
| 33 closure_(Instance::null()), | 33 closure_(Instance::null()), |
| 34 bpt_location_(bpt_location), | 34 bpt_location_(bpt_location), |
| 35 is_synthetic_async_(false) {} | 35 is_synthetic_async_(false) {} |
| 36 | 36 |
| 37 intptr_t id() const { return id_; } | 37 intptr_t id() const { return id_; } |
| 38 Breakpoint* next() const { return next_; } | 38 Breakpoint* next() const { return next_; } |
| 39 void set_next(Breakpoint* n) { next_ = n; } | 39 void set_next(Breakpoint* n) { next_ = n; } |
| 40 | 40 |
| 41 BreakpointLocation* bpt_location() const { return bpt_location_; } | 41 BreakpointLocation* bpt_location() const { return bpt_location_; } |
| 42 void set_bpt_location(BreakpointLocation* new_bpt_location); | 42 void set_bpt_location(BreakpointLocation* new_bpt_location); |
| 43 | 43 |
| 44 bool IsRepeated() const { return kind_ == kRepeated; } | 44 bool IsRepeated() const { return kind_ == kRepeated; } |
| 45 bool IsSingleShot() const { return kind_ == kSingleShot; } | 45 bool IsSingleShot() const { return kind_ == kSingleShot; } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 59 void SetIsPerClosure(const Instance& closure) { | 59 void SetIsPerClosure(const Instance& closure) { |
| 60 ASSERT(kind_ == kNone); | 60 ASSERT(kind_ == kNone); |
| 61 kind_ = kPerClosure; | 61 kind_ = kPerClosure; |
| 62 closure_ = closure.raw(); | 62 closure_ = closure.raw(); |
| 63 } | 63 } |
| 64 | 64 |
| 65 // Mark that this breakpoint is a result of a step OverAwait request. | 65 // Mark that this breakpoint is a result of a step OverAwait request. |
| 66 void set_is_synthetic_async(bool is_synthetic_async) { | 66 void set_is_synthetic_async(bool is_synthetic_async) { |
| 67 is_synthetic_async_ = is_synthetic_async; | 67 is_synthetic_async_ = is_synthetic_async; |
| 68 } | 68 } |
| 69 bool is_synthetic_async() const { | 69 bool is_synthetic_async() const { return is_synthetic_async_; } |
| 70 return is_synthetic_async_; | |
| 71 } | |
| 72 | 70 |
| 73 void PrintJSON(JSONStream* stream); | 71 void PrintJSON(JSONStream* stream); |
| 74 | 72 |
| 75 private: | 73 private: |
| 76 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 74 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 77 | 75 |
| 78 enum ConditionKind { | 76 enum ConditionKind { |
| 79 kNone, | 77 kNone, |
| 80 kRepeated, | 78 kRepeated, |
| 81 kSingleShot, | 79 kSingleShot, |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 238 |
| 241 friend class Debugger; | 239 friend class Debugger; |
| 242 DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint); | 240 DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint); |
| 243 }; | 241 }; |
| 244 | 242 |
| 245 | 243 |
| 246 // ActivationFrame represents one dart function activation frame | 244 // ActivationFrame represents one dart function activation frame |
| 247 // on the call stack. | 245 // on the call stack. |
| 248 class ActivationFrame : public ZoneAllocated { | 246 class ActivationFrame : public ZoneAllocated { |
| 249 public: | 247 public: |
| 250 ActivationFrame(uword pc, uword fp, uword sp, const Code& code, | 248 ActivationFrame(uword pc, |
| 251 const Array& deopt_frame, intptr_t deopt_frame_offset); | 249 uword fp, |
| 250 uword sp, |
| 251 const Code& code, |
| 252 const Array& deopt_frame, |
| 253 intptr_t deopt_frame_offset); |
| 252 | 254 |
| 253 uword pc() const { return pc_; } | 255 uword pc() const { return pc_; } |
| 254 uword fp() const { return fp_; } | 256 uword fp() const { return fp_; } |
| 255 uword sp() const { return sp_; } | 257 uword sp() const { return sp_; } |
| 256 const Function& function() const { | 258 const Function& function() const { |
| 257 ASSERT(!function_.IsNull()); | 259 ASSERT(!function_.IsNull()); |
| 258 return function_; | 260 return function_; |
| 259 } | 261 } |
| 260 const Code& code() const { | 262 const Code& code() const { |
| 261 ASSERT(!code_.IsNull()); | 263 ASSERT(!code_.IsNull()); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 347 |
| 346 friend class Debugger; | 348 friend class Debugger; |
| 347 friend class DebuggerStackTrace; | 349 friend class DebuggerStackTrace; |
| 348 DISALLOW_COPY_AND_ASSIGN(ActivationFrame); | 350 DISALLOW_COPY_AND_ASSIGN(ActivationFrame); |
| 349 }; | 351 }; |
| 350 | 352 |
| 351 | 353 |
| 352 // Array of function activations on the call stack. | 354 // Array of function activations on the call stack. |
| 353 class DebuggerStackTrace : public ZoneAllocated { | 355 class DebuggerStackTrace : public ZoneAllocated { |
| 354 public: | 356 public: |
| 355 explicit DebuggerStackTrace(int capacity) | 357 explicit DebuggerStackTrace(int capacity) : trace_(capacity) {} |
| 356 : trace_(capacity) { } | |
| 357 | 358 |
| 358 intptr_t Length() const { return trace_.length(); } | 359 intptr_t Length() const { return trace_.length(); } |
| 359 | 360 |
| 360 ActivationFrame* FrameAt(int i) const { | 361 ActivationFrame* FrameAt(int i) const { return trace_[i]; } |
| 361 return trace_[i]; | |
| 362 } | |
| 363 | 362 |
| 364 ActivationFrame* GetHandlerFrame(const Instance& exc_obj) const; | 363 ActivationFrame* GetHandlerFrame(const Instance& exc_obj) const; |
| 365 | 364 |
| 366 private: | 365 private: |
| 367 void AddActivation(ActivationFrame* frame); | 366 void AddActivation(ActivationFrame* frame); |
| 368 ZoneGrowableArray<ActivationFrame*> trace_; | 367 ZoneGrowableArray<ActivationFrame*> trace_; |
| 369 | 368 |
| 370 friend class Debugger; | 369 friend class Debugger; |
| 371 DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace); | 370 DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace); |
| 372 }; | 371 }; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 Dart_Port GetIsolateId() { return isolate_id_; } | 476 Dart_Port GetIsolateId() { return isolate_id_; } |
| 478 | 477 |
| 479 static void SetEventHandler(EventHandler* handler); | 478 static void SetEventHandler(EventHandler* handler); |
| 480 | 479 |
| 481 // Utility functions. | 480 // Utility functions. |
| 482 static const char* QualifiedFunctionName(const Function& func); | 481 static const char* QualifiedFunctionName(const Function& func); |
| 483 | 482 |
| 484 RawObject* GetInstanceField(const Class& cls, | 483 RawObject* GetInstanceField(const Class& cls, |
| 485 const String& field_name, | 484 const String& field_name, |
| 486 const Instance& object); | 485 const Instance& object); |
| 487 RawObject* GetStaticField(const Class& cls, | 486 RawObject* GetStaticField(const Class& cls, const String& field_name); |
| 488 const String& field_name); | |
| 489 | 487 |
| 490 // Pause execution for a breakpoint. Called from generated code. | 488 // Pause execution for a breakpoint. Called from generated code. |
| 491 RawError* PauseBreakpoint(); | 489 RawError* PauseBreakpoint(); |
| 492 | 490 |
| 493 // Pause execution due to stepping. Called from generated code. | 491 // Pause execution due to stepping. Called from generated code. |
| 494 RawError* PauseStepping(); | 492 RawError* PauseStepping(); |
| 495 | 493 |
| 496 // Pause execution due to isolate interrupt. | 494 // Pause execution due to isolate interrupt. |
| 497 RawError* PauseInterrupted(); | 495 RawError* PauseInterrupted(); |
| 498 | 496 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 509 RawCode* GetPatchedStubAddress(uword breakpoint_address); | 507 RawCode* GetPatchedStubAddress(uword breakpoint_address); |
| 510 | 508 |
| 511 void PrintBreakpointsToJSONArray(JSONArray* jsarr) const; | 509 void PrintBreakpointsToJSONArray(JSONArray* jsarr) const; |
| 512 void PrintSettingsToJSONObject(JSONObject* jsobj) const; | 510 void PrintSettingsToJSONObject(JSONObject* jsobj) const; |
| 513 | 511 |
| 514 static bool IsDebuggable(const Function& func); | 512 static bool IsDebuggable(const Function& func); |
| 515 | 513 |
| 516 intptr_t limitBreakpointId() { return next_id_; } | 514 intptr_t limitBreakpointId() { return next_id_; } |
| 517 | 515 |
| 518 private: | 516 private: |
| 519 enum ResumeAction { | 517 enum ResumeAction { kContinue, kStepOver, kStepOut, kSingleStep }; |
| 520 kContinue, | |
| 521 kStepOver, | |
| 522 kStepOut, | |
| 523 kSingleStep | |
| 524 }; | |
| 525 | 518 |
| 526 RawError* PauseRequest(ServiceEvent::EventKind kind); | 519 RawError* PauseRequest(ServiceEvent::EventKind kind); |
| 527 | 520 |
| 528 bool NeedsIsolateEvents(); | 521 bool NeedsIsolateEvents(); |
| 529 bool NeedsDebugEvents(); | 522 bool NeedsDebugEvents(); |
| 530 void InvokeEventHandler(ServiceEvent* event); | 523 void InvokeEventHandler(ServiceEvent* event); |
| 531 | 524 |
| 532 void SendBreakpointEvent(ServiceEvent::EventKind kind, Breakpoint* bpt); | 525 void SendBreakpointEvent(ServiceEvent::EventKind kind, Breakpoint* bpt); |
| 533 | 526 |
| 534 bool IsAtAsyncJump(ActivationFrame* top_frame); | 527 bool IsAtAsyncJump(ActivationFrame* top_frame); |
| 535 void FindCompiledFunctions(const Script& script, | 528 void FindCompiledFunctions(const Script& script, |
| 536 TokenPosition start_pos, | 529 TokenPosition start_pos, |
| 537 TokenPosition end_pos, | 530 TokenPosition end_pos, |
| 538 GrowableObjectArray* function_list); | 531 GrowableObjectArray* function_list); |
| 539 RawFunction* FindBestFit(const Script& script, TokenPosition token_pos); | 532 RawFunction* FindBestFit(const Script& script, TokenPosition token_pos); |
| 540 RawFunction* FindInnermostClosure(const Function& function, | 533 RawFunction* FindInnermostClosure(const Function& function, |
| 541 TokenPosition token_pos); | 534 TokenPosition token_pos); |
| 542 TokenPosition ResolveBreakpointPos(const Function& func, | 535 TokenPosition ResolveBreakpointPos(const Function& func, |
| 543 TokenPosition requested_token_pos, | 536 TokenPosition requested_token_pos, |
| 544 TokenPosition last_token_pos, | 537 TokenPosition last_token_pos, |
| 545 intptr_t requested_column); | 538 intptr_t requested_column); |
| 546 void DeoptimizeWorld(); | 539 void DeoptimizeWorld(); |
| 547 BreakpointLocation* SetBreakpoint(const Script& script, | 540 BreakpointLocation* SetBreakpoint(const Script& script, |
| 548 TokenPosition token_pos, | 541 TokenPosition token_pos, |
| 549 TokenPosition last_token_pos, | 542 TokenPosition last_token_pos, |
| 550 intptr_t requested_line, | 543 intptr_t requested_line, |
| 551 intptr_t requested_column); | 544 intptr_t requested_column); |
| 552 void RemoveInternalBreakpoints(); | 545 void RemoveInternalBreakpoints(); |
| 553 void UnlinkCodeBreakpoints(BreakpointLocation* bpt_location); | 546 void UnlinkCodeBreakpoints(BreakpointLocation* bpt_location); |
| 554 BreakpointLocation* GetLatentBreakpoint(const String& url, | 547 BreakpointLocation* GetLatentBreakpoint(const String& url, |
| 555 intptr_t line, | 548 intptr_t line, |
| 556 intptr_t column); | 549 intptr_t column); |
| 557 void RegisterBreakpointLocation(BreakpointLocation* bpt); | 550 void RegisterBreakpointLocation(BreakpointLocation* bpt); |
| 558 void RegisterCodeBreakpoint(CodeBreakpoint* bpt); | 551 void RegisterCodeBreakpoint(CodeBreakpoint* bpt); |
| 559 BreakpointLocation* GetBreakpointLocation(const Script& script, | 552 BreakpointLocation* GetBreakpointLocation(const Script& script, |
| 560 TokenPosition token_pos, | 553 TokenPosition token_pos, |
| 561 intptr_t requested_column); | 554 intptr_t requested_column); |
| 562 void MakeCodeBreakpointAt(const Function& func, | 555 void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt); |
| 563 BreakpointLocation* bpt); | |
| 564 // Returns NULL if no breakpoint exists for the given address. | 556 // Returns NULL if no breakpoint exists for the given address. |
| 565 CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address); | 557 CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address); |
| 566 | 558 |
| 567 void SyncBreakpointLocation(BreakpointLocation* loc); | 559 void SyncBreakpointLocation(BreakpointLocation* loc); |
| 568 | 560 |
| 569 ActivationFrame* TopDartFrame() const; | 561 ActivationFrame* TopDartFrame() const; |
| 570 static ActivationFrame* CollectDartFrame(Isolate* isolate, | 562 static ActivationFrame* CollectDartFrame(Isolate* isolate, |
| 571 uword pc, | 563 uword pc, |
| 572 StackFrame* frame, | 564 StackFrame* frame, |
| 573 const Code& code, | 565 const Code& code, |
| 574 const Array& deopt_frame, | 566 const Array& deopt_frame, |
| 575 intptr_t deopt_frame_offset); | 567 intptr_t deopt_frame_offset); |
| 576 static RawArray* DeoptimizeToArray(Thread* thread, | 568 static RawArray* DeoptimizeToArray(Thread* thread, |
| 577 StackFrame* frame, | 569 StackFrame* frame, |
| 578 const Code& code); | 570 const Code& code); |
| 579 static DebuggerStackTrace* CollectStackTrace(); | 571 static DebuggerStackTrace* CollectStackTrace(); |
| 580 void SignalPausedEvent(ActivationFrame* top_frame, | 572 void SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt); |
| 581 Breakpoint* bpt); | |
| 582 | 573 |
| 583 intptr_t nextId() { return next_id_++; } | 574 intptr_t nextId() { return next_id_++; } |
| 584 | 575 |
| 585 bool ShouldPauseOnException(DebuggerStackTrace* stack_trace, | 576 bool ShouldPauseOnException(DebuggerStackTrace* stack_trace, |
| 586 const Instance& exc); | 577 const Instance& exc); |
| 587 | 578 |
| 588 void CollectLibraryFields(const GrowableObjectArray& field_list, | 579 void CollectLibraryFields(const GrowableObjectArray& field_list, |
| 589 const Library& lib, | 580 const Library& lib, |
| 590 const String& prefix, | 581 const String& prefix, |
| 591 bool include_private_fields); | 582 bool include_private_fields); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 | 640 |
| 650 friend class Isolate; | 641 friend class Isolate; |
| 651 friend class BreakpointLocation; | 642 friend class BreakpointLocation; |
| 652 DISALLOW_COPY_AND_ASSIGN(Debugger); | 643 DISALLOW_COPY_AND_ASSIGN(Debugger); |
| 653 }; | 644 }; |
| 654 | 645 |
| 655 | 646 |
| 656 } // namespace dart | 647 } // namespace dart |
| 657 | 648 |
| 658 #endif // RUNTIME_VM_DEBUGGER_H_ | 649 #endif // RUNTIME_VM_DEBUGGER_H_ |
| OLD | NEW |