Index: runtime/vm/debugger.h |
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h |
index fa9c3a61466776e9cf319922d508f8806b11296c..7bd5d2878a3088daece976aee7f7ece8ce24e046 100644 |
--- a/runtime/vm/debugger.h |
+++ b/runtime/vm/debugger.h |
@@ -11,6 +11,18 @@ |
#include "vm/port.h" |
#include "vm/service_event.h" |
+DECLARE_FLAG(bool, verbose_debug); |
+ |
+// 'Trace Debugger' TD_Print. |
+#if defined(_MSC_VER) |
+#define TD_Print(format, ...) \ |
+ if (FLAG_verbose_debug) Log::Current()->Print(format, __VA_ARGS__) |
+#else |
+#define TD_Print(format, ...) \ |
+ if (FLAG_verbose_debug) Log::Current()->Print(format, ##__VA_ARGS__) |
+#endif |
+ |
+ |
namespace dart { |
class CodeBreakpoint; |
@@ -245,12 +257,23 @@ class CodeBreakpoint { |
// on the call stack. |
class ActivationFrame : public ZoneAllocated { |
public: |
+ enum Kind { |
+ kRegular, |
+ kAsyncSuspensionMarker, |
+ kAsyncCausal, |
+ }; |
+ |
ActivationFrame(uword pc, |
uword fp, |
uword sp, |
const Code& code, |
const Array& deopt_frame, |
- intptr_t deopt_frame_offset); |
+ intptr_t deopt_frame_offset, |
+ Kind kind = kRegular); |
+ |
+ ActivationFrame(uword pc, const Code& code); |
+ |
+ explicit ActivationFrame(Kind kind); |
uword pc() const { return pc_; } |
uword fp() const { return fp_; } |
@@ -311,6 +334,10 @@ class ActivationFrame : public ZoneAllocated { |
void PrintToJSONObject(JSONObject* jsobj, bool full = false); |
private: |
+ void PrintToJSONObjectRegular(JSONObject* jsobj, bool full); |
+ void PrintToJSONObjectAsyncCausal(JSONObject* jsobj, bool full); |
+ void PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj, bool full); |
+ |
void PrintContextMismatchError(intptr_t ctx_slot, |
intptr_t frame_ctx_level, |
intptr_t var_ctx_level); |
@@ -320,6 +347,20 @@ class ActivationFrame : public ZoneAllocated { |
void GetVarDescriptors(); |
void GetDescIndices(); |
+ static const char* KindToCString(Kind kind) { |
+ switch (kind) { |
+ case kRegular: |
+ return "kRegular"; |
+ case kAsyncCausal: |
+ return "kAsyncCausal"; |
+ case kAsyncSuspensionMarker: |
+ return "kAsyncSuspensionMarker"; |
+ default: |
+ UNREACHABLE(); |
+ return ""; |
+ } |
+ } |
+ |
RawObject* GetStackVar(intptr_t slot_index); |
RawObject* GetContextVar(intptr_t ctxt_level, intptr_t slot_index); |
@@ -329,8 +370,9 @@ class ActivationFrame : public ZoneAllocated { |
// The anchor of the context chain for this function. |
Context& ctx_; |
- const Code& code_; |
- const Function& function_; |
+ Code& code_; |
+ Function& function_; |
+ bool live_frame_; // Is this frame a live frame? |
bool token_pos_initialized_; |
TokenPosition token_pos_; |
intptr_t try_index_; |
@@ -343,6 +385,8 @@ class ActivationFrame : public ZoneAllocated { |
const Array& deopt_frame_; |
const intptr_t deopt_frame_offset_; |
+ Kind kind_; |
+ |
bool vars_initialized_; |
LocalVarDescriptors& var_descriptors_; |
ZoneGrowableArray<intptr_t> desc_indices_; |
@@ -367,6 +411,9 @@ class DebuggerStackTrace : public ZoneAllocated { |
private: |
void AddActivation(ActivationFrame* frame); |
+ void AddMarker(ActivationFrame::Kind marker); |
+ void AddAsyncCausalFrame(uword pc, const Code& code); |
+ |
ZoneGrowableArray<ActivationFrame*> trace_; |
friend class Debugger; |
@@ -470,6 +517,9 @@ class Debugger { |
DebuggerStackTrace* StackTrace(); |
DebuggerStackTrace* CurrentStackTrace(); |
+ DebuggerStackTrace* AsyncCausalStackTrace(); |
+ DebuggerStackTrace* CurrentAsyncCausalStackTrace(); |
+ |
// Returns a debugger stack trace corresponding to a dart.core.StackTrace. |
// Frames corresponding to invisible functions are omitted. It is not valid |
// to query local variables in the returned stack. |
@@ -530,6 +580,10 @@ class Debugger { |
private: |
RawError* PauseRequest(ServiceEvent::EventKind kind); |
+ // Finds the breakpoint we hit at |location|. |
+ Breakpoint* FindHitBreakpoint(BreakpointLocation* location, |
+ ActivationFrame* top_frame); |
+ |
// Will return false if we are not at an await. |
bool SetupStepOverAsyncSuspension(const char** error); |
@@ -583,7 +637,18 @@ class Debugger { |
static RawArray* DeoptimizeToArray(Thread* thread, |
StackFrame* frame, |
const Code& code); |
+ // Appends at least one stack frame. Multiple frames will be appended |
+ // if |code| at the frame's pc contains inlined functions. |
+ static void AppendCodeFrames(Thread* thread, |
+ Isolate* isolate, |
+ Zone* zone, |
+ DebuggerStackTrace* stack_trace, |
+ StackFrame* frame, |
+ Code* code, |
+ Code* inlined_code, |
+ Array* deopt_frame); |
static DebuggerStackTrace* CollectStackTrace(); |
+ static DebuggerStackTrace* CollectAsyncCausalStackTrace(); |
void SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt); |
intptr_t nextId() { return next_id_++; } |
@@ -603,6 +668,11 @@ class Debugger { |
void HandleSteppingRequest(DebuggerStackTrace* stack_trace, |
bool skip_next_step = false); |
+ void CacheStackTraces(DebuggerStackTrace* stack_trace, |
+ DebuggerStackTrace* async_causal_stack_trace); |
+ void ClearCachedStackTraces(); |
+ |
+ |
// Can we rewind to the indicated frame? |
bool CanRewindFrame(intptr_t frame_index, const char** error) const; |
@@ -644,6 +714,7 @@ class Debugger { |
// Current stack trace. Valid only while IsPaused(). |
DebuggerStackTrace* stack_trace_; |
+ DebuggerStackTrace* async_causal_stack_trace_; |
// When stepping through code, only pause the program if the top |
// frame corresponds to this fp value, or if the top frame is |