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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_DEBUGGER_H_
6#define RUNTIME_VM_DEBUGGER_H_
7
8#include "include/dart_tools_api.h"
9
10#include "vm/constants_kbc.h"
11#include "vm/kernel_isolate.h"
12#include "vm/object.h"
13#include "vm/port.h"
14#include "vm/scopes.h"
15#include "vm/service_event.h"
16#include "vm/simulator.h"
17
18DECLARE_FLAG(bool, verbose_debug);
19
20// 'Trace Debugger' TD_Print.
21#if defined(_MSC_VER)
22#define TD_Print(format, ...) \
23 if (FLAG_verbose_debug) Log::Current()->Print(format, __VA_ARGS__)
24#else
25#define TD_Print(format, ...) \
26 if (FLAG_verbose_debug) Log::Current()->Print(format, ##__VA_ARGS__)
27#endif
28
29namespace dart {
30
31class CodeBreakpoint;
32class Isolate;
33class JSONArray;
34class JSONStream;
35class ObjectPointerVisitor;
36class BreakpointLocation;
37class StackFrame;
38
39// A user-defined breakpoint, which either fires once, for a particular closure,
40// or always. The API's notion of a breakpoint corresponds to this object.
41class Breakpoint {
42 public:
43 Breakpoint(intptr_t id, BreakpointLocation* bpt_location)
44 : id_(id),
45 kind_(Breakpoint::kNone),
46 next_(NULL),
47 closure_(Instance::null()),
48 bpt_location_(bpt_location),
49 is_synthetic_async_(false) {}
50
51 intptr_t id() const { return id_; }
52 Breakpoint* next() const { return next_; }
53 void set_next(Breakpoint* n) { next_ = n; }
54
55 BreakpointLocation* bpt_location() const { return bpt_location_; }
56 void set_bpt_location(BreakpointLocation* new_bpt_location);
57
58 bool IsRepeated() const { return kind_ == kRepeated; }
59 bool IsSingleShot() const { return kind_ == kSingleShot; }
60 bool IsPerClosure() const { return kind_ == kPerClosure; }
61 InstancePtr closure() const { return closure_; }
62
63 void SetIsRepeated() {
64 ASSERT(kind_ == kNone);
65 kind_ = kRepeated;
66 }
67
68 void SetIsSingleShot() {
69 ASSERT(kind_ == kNone);
70 kind_ = kSingleShot;
71 }
72
73 void SetIsPerClosure(const Instance& closure) {
74 ASSERT(kind_ == kNone);
75 kind_ = kPerClosure;
76 closure_ = closure.raw();
77 }
78
79 // Mark that this breakpoint is a result of a step OverAwait request.
80 void set_is_synthetic_async(bool is_synthetic_async) {
81 is_synthetic_async_ = is_synthetic_async;
82 }
83 bool is_synthetic_async() const { return is_synthetic_async_; }
84
85 void PrintJSON(JSONStream* stream);
86
87 private:
88 void VisitObjectPointers(ObjectPointerVisitor* visitor);
89
90 enum ConditionKind {
91 kNone,
92 kRepeated,
93 kSingleShot,
94 kPerClosure,
95 };
96
97 intptr_t id_;
98 ConditionKind kind_;
99 Breakpoint* next_;
100 InstancePtr closure_;
101 BreakpointLocation* bpt_location_;
102 bool is_synthetic_async_;
103
104 friend class BreakpointLocation;
105 DISALLOW_COPY_AND_ASSIGN(Breakpoint);
106};
107
108// BreakpointLocation represents a collection of breakpoint conditions at the
109// same token position in Dart source. There may be more than one CodeBreakpoint
110// object per BreakpointLocation.
111// An unresolved breakpoint is one where the underlying code has not
112// been compiled yet. Since the code has not been compiled, we don't know
113// the definitive source location yet. The requested source location may
114// change when the underlying code gets compiled.
115// A latent breakpoint represents a breakpoint location in Dart source
116// that is not loaded in the VM when the breakpoint is requested.
117// When a script with matching url is loaded, a latent breakpoint
118// becomes an unresolved breakpoint.
119class BreakpointLocation {
120 public:
121 // Create a new unresolved breakpoint.
122 BreakpointLocation(const Script& script,
123 TokenPosition token_pos,
124 TokenPosition end_token_pos,
125 intptr_t requested_line_number,
126 intptr_t requested_column_number);
127 // Create a new latent breakpoint.
128 BreakpointLocation(const String& url,
129 intptr_t requested_line_number,
130 intptr_t requested_column_number);
131
132 ~BreakpointLocation();
133
134 FunctionPtr function() const { return function_; }
135 TokenPosition token_pos() const { return token_pos_; }
136 TokenPosition end_token_pos() const { return end_token_pos_; }
137
138 ScriptPtr script() const { return script_; }
139 StringPtr url() const { return url_; }
140
141 intptr_t requested_line_number() const { return requested_line_number_; }
142 intptr_t requested_column_number() const { return requested_column_number_; }
143
144 void GetCodeLocation(Script* script, TokenPosition* token_pos) const;
145
146 Breakpoint* AddRepeated(Debugger* dbg);
147 Breakpoint* AddSingleShot(Debugger* dbg);
148 Breakpoint* AddPerClosure(Debugger* dbg,
149 const Instance& closure,
150 bool for_over_await);
151
152 bool AnyEnabled() const;
153 bool IsResolved() const {
154 return bytecode_token_pos_.IsReal() || code_token_pos_.IsReal();
155 }
156 bool IsResolved(bool in_bytecode) const {
157 return in_bytecode ? bytecode_token_pos_.IsReal()
158 : code_token_pos_.IsReal();
159 }
160 bool IsLatent() const { return !token_pos_.IsReal(); }
161
162 private:
163 void VisitObjectPointers(ObjectPointerVisitor* visitor);
164
165 void SetResolved(bool in_bytecode,
166 const Function& func,
167 TokenPosition token_pos);
168
169 BreakpointLocation* next() const { return this->next_; }
170 void set_next(BreakpointLocation* value) { next_ = value; }
171
172 void AddBreakpoint(Breakpoint* bpt, Debugger* dbg);
173
174 Breakpoint* breakpoints() const { return this->conditions_; }
175 void set_breakpoints(Breakpoint* head) { this->conditions_ = head; }
176
177 ScriptPtr script_;
178 StringPtr url_;
179 TokenPosition token_pos_;
180 TokenPosition end_token_pos_;
181 BreakpointLocation* next_;
182 Breakpoint* conditions_;
183 intptr_t requested_line_number_;
184 intptr_t requested_column_number_;
185
186 // Valid for resolved breakpoints:
187 FunctionPtr function_;
188 TokenPosition bytecode_token_pos_;
189 TokenPosition code_token_pos_;
190
191 friend class Debugger;
192 DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
193};
194
195// CodeBreakpoint represents a location in compiled or interpreted code.
196// There may be more than one CodeBreakpoint for one BreakpointLocation,
197// e.g. when a function gets compiled as a regular function and as a closure.
198class CodeBreakpoint {
199 public:
200 CodeBreakpoint(const Code& code,
201 TokenPosition token_pos,
202 uword pc,
203 PcDescriptorsLayout::Kind kind);
204 CodeBreakpoint(const Bytecode& bytecode, TokenPosition token_pos, uword pc);
205 ~CodeBreakpoint();
206
207 FunctionPtr function() const;
208 uword pc() const { return pc_; }
209 TokenPosition token_pos() const { return token_pos_; }
210
211 ScriptPtr SourceCode();
212 StringPtr SourceUrl();
213 intptr_t LineNumber();
214
215 void Enable();
216 void Disable();
217 bool IsEnabled() const { return is_enabled_; }
218 bool IsInterpreted() const { return bytecode_ != Bytecode::null(); }
219
220 CodePtr OrigStubAddress() const;
221
222 private:
223 void VisitObjectPointers(ObjectPointerVisitor* visitor);
224
225 BreakpointLocation* bpt_location() const { return bpt_location_; }
226 void set_bpt_location(BreakpointLocation* value) { bpt_location_ = value; }
227
228 void set_next(CodeBreakpoint* value) { next_ = value; }
229 CodeBreakpoint* next() const { return this->next_; }
230
231 void PatchCode();
232 void RestoreCode();
233 void SetBytecodeBreakpoint();
234 void UnsetBytecodeBreakpoint();
235
236 CodePtr code_;
237 BytecodePtr bytecode_;
238 TokenPosition token_pos_;
239 uword pc_;
240 intptr_t line_number_;
241 bool is_enabled_;
242
243 BreakpointLocation* bpt_location_;
244 CodeBreakpoint* next_;
245
246 PcDescriptorsLayout::Kind breakpoint_kind_;
247 CodePtr saved_value_;
248
249 friend class Debugger;
250 DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint);
251};
252
253// ActivationFrame represents one dart function activation frame
254// on the call stack.
255class ActivationFrame : public ZoneAllocated {
256 public:
257 enum Kind {
258 kRegular,
259 kAsyncSuspensionMarker,
260 kAsyncCausal,
261 kAsyncActivation,
262 };
263
264 ActivationFrame(uword pc,
265 uword fp,
266 uword sp,
267 const Code& code,
268 const Array& deopt_frame,
269 intptr_t deopt_frame_offset,
270 Kind kind = kRegular);
271
272 ActivationFrame(uword pc, const Code& code);
273
274#if !defined(DART_PRECOMPILED_RUNTIME)
275 ActivationFrame(uword pc,
276 uword fp,
277 uword sp,
278 const Bytecode& bytecode,
279 Kind kind = kRegular);
280
281 ActivationFrame(uword pc, const Bytecode& bytecode);
282#endif // !defined(DART_PRECOMPILED_RUNTIME)
283
284 explicit ActivationFrame(Kind kind);
285
286 explicit ActivationFrame(const Closure& async_activation);
287
288 uword pc() const { return pc_; }
289 uword fp() const { return fp_; }
290 uword sp() const { return sp_; }
291 const Function& function() const {
292 return function_;
293 }
294 const Code& code() const {
295 ASSERT(!code_.IsNull());
296 return code_;
297 }
298 const Bytecode& bytecode() const {
299 ASSERT(!bytecode_.IsNull());
300 return bytecode_;
301 }
302 bool IsInterpreted() const { return !bytecode_.IsNull(); }
303
304 enum Relation {
305 kCallee,
306 kSelf,
307 kCaller,
308 };
309
310 Relation CompareTo(uword other_fp, bool other_is_interpreted) const;
311
312 StringPtr QualifiedFunctionName();
313 StringPtr SourceUrl();
314 ScriptPtr SourceScript();
315 LibraryPtr Library();
316 TokenPosition TokenPos();
317 intptr_t LineNumber();
318 intptr_t ColumnNumber();
319
320 // Returns true if this frame is for a function that is visible
321 // to the user and can be debugged.
322 bool IsDebuggable() const;
323
324 // Returns true if it is possible to rewind the debugger to this frame.
325 bool IsRewindable() const;
326
327 // The context level of a frame is the context level at the
328 // PC/token index of the frame. It determines the depth of the context
329 // chain that belongs to the function of this activation frame.
330 intptr_t ContextLevel();
331
332 const char* ToCString();
333
334 intptr_t NumLocalVariables();
335
336 void VariableAt(intptr_t i,
337 String* name,
338 TokenPosition* declaration_token_pos,
339 TokenPosition* visible_start_token_pos,
340 TokenPosition* visible_end_token_pos,
341 Object* value);
342
343 ArrayPtr GetLocalVariables();
344 ObjectPtr GetParameter(intptr_t index);
345 ObjectPtr GetClosure();
346 ObjectPtr GetReceiver();
347
348 const Context& GetSavedCurrentContext();
349 ObjectPtr GetAsyncOperation();
350
351 TypeArgumentsPtr BuildParameters(
352 const GrowableObjectArray& param_names,
353 const GrowableObjectArray& param_values,
354 const GrowableObjectArray& type_params_names);
355
356 ObjectPtr EvaluateCompiledExpression(const ExternalTypedData& kernel_data,
357 const Array& arguments,
358 const Array& type_definitions,
359 const TypeArguments& type_arguments);
360
361 void PrintToJSONObject(JSONObject* jsobj);
362
363 ObjectPtr GetAsyncAwaiter();
364 ObjectPtr GetCausalStack();
365
366 bool HandlesException(const Instance& exc_obj);
367
368 private:
369 void PrintToJSONObjectRegular(JSONObject* jsobj);
370 void PrintToJSONObjectAsyncCausal(JSONObject* jsobj);
371 void PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj);
372 void PrintContextMismatchError(intptr_t ctx_slot,
373 intptr_t frame_ctx_level,
374 intptr_t var_ctx_level);
375 void PrintDescriptorsError(const char* message);
376
377 intptr_t TryIndex();
378 intptr_t DeoptId();
379 void GetPcDescriptors();
380 void GetVarDescriptors();
381 void GetDescIndices();
382
383 ObjectPtr GetAsyncContextVariable(const String& name);
384 ObjectPtr GetAsyncStreamControllerStreamAwaiter(const Object& stream);
385 ObjectPtr GetAsyncStreamControllerStream();
386 ObjectPtr GetAsyncCompleterAwaiter(const Object& completer);
387 ObjectPtr GetAsyncCompleter();
388 intptr_t GetAwaitJumpVariable();
389 void ExtractTokenPositionFromAsyncClosure();
390
391 bool IsAsyncMachinery() const;
392
393 static const char* KindToCString(Kind kind) {
394 switch (kind) {
395 case kRegular:
396 return "Regular";
397 case kAsyncCausal:
398 return "AsyncCausal";
399 case kAsyncSuspensionMarker:
400 return "AsyncSuspensionMarker";
401 case kAsyncActivation:
402 return "AsyncActivation";
403 default:
404 UNREACHABLE();
405 return "";
406 }
407 }
408
409 ObjectPtr GetStackVar(VariableIndex var_index);
410 ObjectPtr GetRelativeContextVar(intptr_t ctxt_level,
411 intptr_t slot_index,
412 intptr_t frame_ctx_level);
413 ObjectPtr GetContextVar(intptr_t ctxt_level, intptr_t slot_index);
414
415 uword pc_;
416 uword fp_;
417 uword sp_;
418
419 // The anchor of the context chain for this function.
420 Context& ctx_;
421 Code& code_;
422 Bytecode& bytecode_;
423 Function& function_;
424 bool live_frame_; // Is this frame a live frame?
425 bool token_pos_initialized_;
426 TokenPosition token_pos_;
427 intptr_t try_index_;
428 intptr_t deopt_id_;
429
430 intptr_t line_number_;
431 intptr_t column_number_;
432 intptr_t context_level_;
433
434 // Some frames are deoptimized into a side array in order to inspect them.
435 const Array& deopt_frame_;
436 const intptr_t deopt_frame_offset_;
437
438 Kind kind_;
439
440 bool vars_initialized_;
441 LocalVarDescriptors& var_descriptors_;
442 ZoneGrowableArray<intptr_t> desc_indices_;
443 PcDescriptors& pc_desc_;
444
445 friend class Debugger;
446 friend class DebuggerStackTrace;
447 DISALLOW_COPY_AND_ASSIGN(ActivationFrame);
448};
449
450// Array of function activations on the call stack.
451class DebuggerStackTrace : public ZoneAllocated {
452 public:
453 explicit DebuggerStackTrace(int capacity) : trace_(capacity) {}
454
455 intptr_t Length() const { return trace_.length(); }
456
457 ActivationFrame* FrameAt(int i) const { return trace_[i]; }
458
459 ActivationFrame* GetHandlerFrame(const Instance& exc_obj) const;
460
461 private:
462 void AddActivation(ActivationFrame* frame);
463 void AddMarker(ActivationFrame::Kind marker);
464 void AddAsyncCausalFrame(uword pc, const Code& code);
465 void AddAsyncCausalFrame(uword pc, const Bytecode& bytecode);
466
467 ZoneGrowableArray<ActivationFrame*> trace_;
468
469 friend class Debugger;
470 DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace);
471};
472
473// On which exceptions to pause.
474typedef enum {
475 kNoPauseOnExceptions = 1,
476 kPauseOnUnhandledExceptions,
477 kPauseOnAllExceptions,
478 kInvalidExceptionPauseInfo
479} Dart_ExceptionPauseInfo;
480
481class Debugger {
482 public:
483 enum ResumeAction {
484 kContinue,
485 kStepInto,
486 kStepOver,
487 kStepOut,
488 kStepRewind,
489 kStepOverAsyncSuspension,
490 };
491
492 explicit Debugger(Isolate* isolate);
493 ~Debugger();
494
495 void NotifyIsolateCreated();
496 void Shutdown();
497
498 void OnIsolateRunnable();
499
500 void NotifyCompilation(const Function& func) {
501 HandleCodeChange(/* bytecode_loaded = */ false, func);
502 }
503 void NotifyBytecodeLoaded(const Function& func) {
504 HandleCodeChange(/* bytecode_loaded = */ true, func);
505 }
506 void NotifyDoneLoading();
507
508 // Set breakpoint at closest location to function entry.
509 Breakpoint* SetBreakpointAtEntry(const Function& target_function,
510 bool single_shot);
511 Breakpoint* SetBreakpointAtActivation(const Instance& closure,
512 bool for_over_await);
513 Breakpoint* BreakpointAtActivation(const Instance& closure);
514
515 // TODO(turnidge): script_url may no longer be specific enough.
516 Breakpoint* SetBreakpointAtLine(const String& script_url,
517 intptr_t line_number);
518 Breakpoint* SetBreakpointAtLineCol(const String& script_url,
519 intptr_t line_number,
520 intptr_t column_number);
521
522 BreakpointLocation* BreakpointLocationAtLineCol(const String& script_url,
523 intptr_t line_number,
524 intptr_t column_number);
525
526 void RemoveBreakpoint(intptr_t bp_id);
527 Breakpoint* GetBreakpointById(intptr_t id);
528
529 void MaybeAsyncStepInto(const Closure& async_op);
530 void AsyncStepInto(const Closure& async_op);
531
532 void Continue();
533
534 bool SetResumeAction(ResumeAction action,
535 intptr_t frame_index = 1,
536 const char** error = NULL);
537
538 bool IsStepping() const { return resume_action_ != kContinue; }
539
540 bool IsSingleStepping() const { return resume_action_ == kStepInto; }
541
542 bool IsPaused() const { return pause_event_ != NULL; }
543
544 bool ignore_breakpoints() const { return ignore_breakpoints_; }
545 void set_ignore_breakpoints(bool ignore_breakpoints) {
546 ignore_breakpoints_ = ignore_breakpoints;
547 }
548
549 bool HasEnabledBytecodeBreakpoints() const;
550 // Called from the interpreter. Note that pc already points to next bytecode.
551 bool HasBytecodeBreakpointAt(const KBCInstr* next_pc) const;
552
553 // Put the isolate into single stepping mode when Dart code next runs.
554 //
555 // This is used by the vm service to allow the user to step while
556 // paused at isolate start.
557 void EnterSingleStepMode();
558
559 // Indicates why the debugger is currently paused. If the debugger
560 // is not paused, this returns NULL. Note that the debugger can be
561 // paused for breakpoints, isolate interruption, and (sometimes)
562 // exceptions.
563 const ServiceEvent* PauseEvent() const { return pause_event_; }
564
565 void SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info);
566 Dart_ExceptionPauseInfo GetExceptionPauseInfo() const;
567
568 void VisitObjectPointers(ObjectPointerVisitor* visitor);
569
570 // Returns true if there is at least one breakpoint set in func or code.
571 // Checks for both user-defined and internal temporary breakpoints.
572 // This may be called from different threads, therefore do not use the,
573 // debugger's zone.
574 bool HasBreakpoint(const Function& func, Zone* zone);
575 bool HasBreakpoint(const Code& code);
576 // A Bytecode version of HasBreakpoint is not needed.
577
578 // Returns true if the call at address pc is patched to point to
579 // a debugger stub.
580 bool HasActiveBreakpoint(uword pc);
581
582 // Returns a stack trace with frames corresponding to invisible functions
583 // omitted. CurrentStackTrace always returns a new trace on the current stack.
584 // The trace returned by StackTrace may have been cached; it is suitable for
585 // use when stepping, but otherwise may be out of sync with the current stack.
586 DebuggerStackTrace* StackTrace();
587 DebuggerStackTrace* CurrentStackTrace();
588
589 DebuggerStackTrace* AsyncCausalStackTrace();
590 DebuggerStackTrace* CurrentAsyncCausalStackTrace();
591
592 DebuggerStackTrace* AwaiterStackTrace();
593 DebuggerStackTrace* CurrentAwaiterStackTrace();
594
595 // Returns a debugger stack trace corresponding to a dart.core.StackTrace.
596 // Frames corresponding to invisible functions are omitted. It is not valid
597 // to query local variables in the returned stack.
598 DebuggerStackTrace* StackTraceFrom(const class StackTrace& dart_stacktrace);
599
600 // Utility functions.
601 static const char* QualifiedFunctionName(const Function& func);
602
603 // Pause execution for a breakpoint. Called from generated code.
604 ErrorPtr PauseBreakpoint();
605
606 // Pause execution due to stepping. Called from generated code.
607 ErrorPtr PauseStepping();
608
609 // Pause execution due to isolate interrupt.
610 ErrorPtr PauseInterrupted();
611
612 // Pause after a reload request.
613 ErrorPtr PausePostRequest();
614
615 // Pause execution due to an uncaught exception.
616 void PauseException(const Instance& exc);
617
618 // Pause execution due to a call to the debugger() function from
619 // Dart.
620 void PauseDeveloper(const String& msg);
621
622 CodePtr GetPatchedStubAddress(uword breakpoint_address);
623
624 void PrintBreakpointsToJSONArray(JSONArray* jsarr) const;
625 void PrintSettingsToJSONObject(JSONObject* jsobj) const;
626
627 static bool IsDebuggable(const Function& func);
628 static bool IsDebugging(Thread* thread, const Function& func);
629
630 intptr_t limitBreakpointId() { return next_id_; }
631
632 // Callback to the debugger to continue frame rewind, post-deoptimization.
633 void RewindPostDeopt();
634
635 static DebuggerStackTrace* CollectAwaiterReturnStackTrace();
636
637 private:
638 ErrorPtr PauseRequest(ServiceEvent::EventKind kind);
639
640 // Finds the breakpoint we hit at |location|.
641 Breakpoint* FindHitBreakpoint(BreakpointLocation* location,
642 ActivationFrame* top_frame);
643
644 // Will return false if we are not at an await.
645 bool SetupStepOverAsyncSuspension(const char** error);
646
647 bool NeedsIsolateEvents();
648 bool NeedsDebugEvents();
649 void InvokeEventHandler(ServiceEvent* event);
650
651 void SendBreakpointEvent(ServiceEvent::EventKind kind, Breakpoint* bpt);
652
653 bool IsAtAsyncJump(ActivationFrame* top_frame);
654 void FindCompiledFunctions(const Script& script,
655 TokenPosition start_pos,
656 TokenPosition end_pos,
657 GrowableObjectArray* bytecode_function_list,
658 GrowableObjectArray* code_function_list);
659 bool FindBestFit(const Script& script,
660 TokenPosition token_pos,
661 TokenPosition last_token_pos,
662 Function* best_fit);
663 FunctionPtr FindInnermostClosure(const Function& function,
664 TokenPosition token_pos);
665 TokenPosition ResolveBreakpointPos(bool in_bytecode,
666 const Function& func,
667 TokenPosition requested_token_pos,
668 TokenPosition last_token_pos,
669 intptr_t requested_column,
670 TokenPosition exact_token_pos);
671 void DeoptimizeWorld();
672 void NotifySingleStepping(bool value) const;
673 BreakpointLocation* SetCodeBreakpoints(bool in_bytecode,
674 BreakpointLocation* loc,
675 const Script& script,
676 TokenPosition token_pos,
677 TokenPosition last_token_pos,
678 intptr_t requested_line,
679 intptr_t requested_column,
680 TokenPosition exact_token_pos,
681 const GrowableObjectArray& functions);
682 BreakpointLocation* SetBreakpoint(const Script& script,
683 TokenPosition token_pos,
684 TokenPosition last_token_pos,
685 intptr_t requested_line,
686 intptr_t requested_column,
687 const Function& function);
688 bool RemoveBreakpointFromTheList(intptr_t bp_id, BreakpointLocation** list);
689 Breakpoint* GetBreakpointByIdInTheList(intptr_t id, BreakpointLocation* list);
690 void RemoveUnlinkedCodeBreakpoints();
691 void UnlinkCodeBreakpoints(BreakpointLocation* bpt_location);
692 BreakpointLocation* GetLatentBreakpoint(const String& url,
693 intptr_t line,
694 intptr_t column);
695 void RegisterBreakpointLocation(BreakpointLocation* bpt);
696 void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
697 BreakpointLocation* GetBreakpointLocation(
698 const Script& script,
699 TokenPosition token_pos,
700 intptr_t requested_line,
701 intptr_t requested_column,
702 TokenPosition bytecode_token_pos = TokenPosition::kNoSource,
703 TokenPosition code_token_pos = TokenPosition::kNoSource);
704 void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
705 // Returns NULL if no breakpoint exists for the given address.
706 CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
707
708 void SyncBreakpointLocation(BreakpointLocation* loc);
709 void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
710 JSONArray* jsarr) const;
711
712 void HandleCodeChange(bool bytecode_loaded, const Function& func);
713
714 ActivationFrame* TopDartFrame() const;
715 static ActivationFrame* CollectDartFrame(
716 Isolate* isolate,
717 uword pc,
718 StackFrame* frame,
719 const Code& code,
720 const Array& deopt_frame,
721 intptr_t deopt_frame_offset,
722 ActivationFrame::Kind kind = ActivationFrame::kRegular);
723#if !defined(DART_PRECOMPILED_RUNTIME)
724 static ActivationFrame* CollectDartFrame(
725 Isolate* isolate,
726 uword pc,
727 StackFrame* frame,
728 const Bytecode& bytecode,
729 ActivationFrame::Kind kind = ActivationFrame::kRegular);
730 static ArrayPtr DeoptimizeToArray(Thread* thread,
731 StackFrame* frame,
732 const Code& code);
733 TokenPosition FindExactTokenPosition(const Script& script,
734 TokenPosition start_of_line,
735 intptr_t column_number);
736#endif
737 // Appends at least one stack frame. Multiple frames will be appended
738 // if |code| at the frame's pc contains inlined functions.
739 static void AppendCodeFrames(Thread* thread,
740 Isolate* isolate,
741 Zone* zone,
742 DebuggerStackTrace* stack_trace,
743 StackFrame* frame,
744 Code* code,
745 Code* inlined_code,
746 Array* deopt_frame);
747 static DebuggerStackTrace* CollectStackTrace();
748 static DebuggerStackTrace* CollectAsyncCausalStackTrace();
749 static DebuggerStackTrace* CollectAsyncLazyStackTrace();
750 void SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt);
751
752 intptr_t nextId() { return next_id_++; }
753
754 bool ShouldPauseOnException(DebuggerStackTrace* stack_trace,
755 const Instance& exc);
756
757 // Handles any events which pause vm execution. Breakpoints,
758 // interrupts, etc.
759 void Pause(ServiceEvent* event);
760
761 void HandleSteppingRequest(DebuggerStackTrace* stack_trace,
762 bool skip_next_step = false);
763
764 void CacheStackTraces(DebuggerStackTrace* stack_trace,
765 DebuggerStackTrace* async_causal_stack_trace,
766 DebuggerStackTrace* awaiter_stack_trace);
767 void ClearCachedStackTraces();
768
769 // Can we rewind to the indicated frame?
770 bool CanRewindFrame(intptr_t frame_index, const char** error) const;
771
772 void RewindToFrame(intptr_t frame_index);
773 void RewindToUnoptimizedFrame(StackFrame* frame, const Code& code);
774 void RewindToOptimizedFrame(StackFrame* frame,
775 const Code& code,
776 intptr_t post_deopt_frame_index);
777 void RewindToInterpretedFrame(StackFrame* frame, const Bytecode& bytecode);
778
779 void ResetSteppingFramePointers();
780 bool SteppedForSyntheticAsyncBreakpoint() const;
781 void CleanupSyntheticAsyncBreakpoint();
782 void RememberTopFrameAwaiter();
783 void SetAsyncSteppingFramePointer(DebuggerStackTrace* stack_trace);
784 void SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace);
785
786 Isolate* isolate_;
787
788 // ID number generator.
789 intptr_t next_id_;
790
791 BreakpointLocation* latent_locations_;
792 BreakpointLocation* breakpoint_locations_;
793 CodeBreakpoint* code_breakpoints_;
794
795 // Tells debugger what to do when resuming execution after a breakpoint.
796 ResumeAction resume_action_;
797 intptr_t resume_frame_index_;
798 intptr_t post_deopt_frame_index_;
799
800 // Do not call back to breakpoint handler if this flag is set.
801 // Effectively this means ignoring breakpoints. Set when Dart code may
802 // be run as a side effect of getting values of fields.
803 bool ignore_breakpoints_;
804
805 // Indicates why the debugger is currently paused. If the debugger
806 // is not paused, this is NULL. Note that the debugger can be
807 // paused for breakpoints, isolate interruption, and (sometimes)
808 // exceptions.
809 ServiceEvent* pause_event_;
810
811 // Current stack trace. Valid only while IsPaused().
812 DebuggerStackTrace* stack_trace_;
813 DebuggerStackTrace* async_causal_stack_trace_;
814 DebuggerStackTrace* awaiter_stack_trace_;
815
816 // When stepping through code, only pause the program if the top
817 // frame corresponds to this fp value, or if the top frame is
818 // lower on the stack.
819 uword stepping_fp_;
820 bool interpreted_stepping_;
821
822 // When stepping through code, do not stop more than once in the same
823 // token position range.
824 uword last_stepping_fp_;
825 TokenPosition last_stepping_pos_;
826
827 // Used to track the current async/async* function.
828 uword async_stepping_fp_;
829 bool interpreted_async_stepping_;
830 ObjectPtr top_frame_awaiter_;
831
832 // If we step while at a breakpoint, we would hit the same pc twice.
833 // We use this field to let us skip the next single-step after a
834 // breakpoint.
835 bool skip_next_step_;
836
837 bool needs_breakpoint_cleanup_;
838
839 // We keep this breakpoint alive until after the debugger does the step over
840 // async continuation machinery so that we can report that we've stopped
841 // at the breakpoint.
842 Breakpoint* synthetic_async_breakpoint_;
843
844 Dart_ExceptionPauseInfo exc_pause_info_;
845
846 friend class Isolate;
847 friend class BreakpointLocation;
848 DISALLOW_COPY_AND_ASSIGN(Debugger);
849};
850
851class DisableBreakpointsScope : public ValueObject {
852 public:
853 DisableBreakpointsScope(Debugger* debugger, bool disable)
854 : debugger_(debugger) {
855 ASSERT(debugger_ != NULL);
856 initial_state_ = debugger_->ignore_breakpoints();
857 debugger_->set_ignore_breakpoints(disable);
858 }
859
860 ~DisableBreakpointsScope() {
861 debugger_->set_ignore_breakpoints(initial_state_);
862 }
863
864 private:
865 Debugger* debugger_;
866 bool initial_state_;
867
868 DISALLOW_COPY_AND_ASSIGN(DisableBreakpointsScope);
869};
870
871} // namespace dart
872
873#endif // RUNTIME_VM_DEBUGGER_H_
874