Index: runtime/vm/debugger.h |
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h |
index 7319c8e41fdd2a8acccc57c4c580737758b63c9f..74fd1ea5a5e93c17d38efe0b106fc37a0d6bdfb5 100644 |
--- a/runtime/vm/debugger.h |
+++ b/runtime/vm/debugger.h |
@@ -276,6 +276,9 @@ class ActivationFrame : public ZoneAllocated { |
// to the user and can be debugged. |
bool IsDebuggable() const; |
+ // Returns true if it is possible to rewind the debugger to this frame. |
+ bool IsRewindable() const; |
+ |
// The context level of a frame is the context level at the |
// PC/token index of the frame. It determines the depth of the context |
// chain that belongs to the function of this activation frame. |
@@ -373,6 +376,15 @@ class DebuggerStackTrace : public ZoneAllocated { |
class Debugger { |
public: |
+ enum ResumeAction { |
+ kContinue, |
+ kStepInto, |
+ kStepOver, |
+ kStepOut, |
+ kStepRewind, |
+ kStepOverAsyncSuspension, |
+ }; |
+ |
typedef void EventHandler(ServiceEvent* event); |
Debugger(); |
@@ -412,11 +424,10 @@ class Debugger { |
void RemoveBreakpoint(intptr_t bp_id); |
Breakpoint* GetBreakpointById(intptr_t id); |
- // Will return false if we are not at an await. |
- bool SetupStepOverAsyncSuspension(); |
- void SetStepOver(); |
- void SetSingleStep(); |
- void SetStepOut(); |
+ bool SetResumeAction(ResumeAction action, |
+ intptr_t frame_index = 1, |
+ const char** error = NULL); |
+ |
bool IsStepping() const { return resume_action_ != kContinue; } |
bool IsPaused() const { return pause_event_ != NULL; } |
@@ -513,11 +524,15 @@ class Debugger { |
intptr_t limitBreakpointId() { return next_id_; } |
- private: |
- enum ResumeAction { kContinue, kStepOver, kStepOut, kSingleStep }; |
+ // Callback to the debugger to continue frame rewind, post-deoptimization. |
+ void RewindPostDeopt(); |
+ private: |
RawError* PauseRequest(ServiceEvent::EventKind kind); |
+ // Will return false if we are not at an await. |
+ bool SetupStepOverAsyncSuspension(const char** error); |
+ |
bool NeedsIsolateEvents(); |
bool NeedsDebugEvents(); |
void InvokeEventHandler(ServiceEvent* event); |
@@ -588,6 +603,15 @@ class Debugger { |
void HandleSteppingRequest(DebuggerStackTrace* stack_trace, |
bool skip_next_step = false); |
+ // Can we rewind to the indicated frame? |
+ bool CanRewindFrame(intptr_t frame_index, const char** error) const; |
+ |
+ void RewindToFrame(intptr_t frame_index); |
+ void RewindToUnoptimizedFrame(StackFrame* frame, const Code& code); |
+ void RewindToOptimizedFrame(StackFrame* frame, |
+ const Code& code, |
+ intptr_t post_deopt_frame_index); |
+ |
Isolate* isolate_; |
Dart_Port isolate_id_; // A unique ID for the isolate in the debugger. |
bool initialized_; |
@@ -601,6 +625,8 @@ class Debugger { |
// Tells debugger what to do when resuming execution after a breakpoint. |
ResumeAction resume_action_; |
+ intptr_t resume_frame_index_; |
+ intptr_t post_deopt_frame_index_; |
// Do not call back to breakpoint handler if this flag is set. |
// Effectively this means ignoring breakpoints. Set when Dart code may |