1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_DEBUG_DEBUG_H_
6#define V8_DEBUG_DEBUG_H_
7
8#include "src/allocation.h"
9#include "src/arguments.h"
10#include "src/assembler.h"
11#include "src/base/atomicops.h"
12#include "src/base/hashmap.h"
13#include "src/base/platform/platform.h"
14#include "src/debug/debug-interface.h"
15#include "src/execution.h"
16#include "src/factory.h"
17#include "src/flags.h"
18#include "src/frames.h"
19#include "src/globals.h"
20#include "src/runtime/runtime.h"
21#include "src/source-position-table.h"
22#include "src/string-stream.h"
23#include "src/v8threads.h"
24
25#include "include/v8-debug.h"
26
27namespace v8 {
28namespace internal {
29
30
31// Forward declarations.
32class DebugScope;
33
34
35// Step actions. NOTE: These values are in macros.py as well.
36enum StepAction : int8_t {
37  StepNone = -1,  // Stepping not prepared.
38  StepOut = 0,    // Step out of the current function.
39  StepNext = 1,   // Step to the next statement in the current function.
40  StepIn = 2,     // Step into new functions invoked or the next statement
41                  // in the current function.
42  StepFrame = 3,  // Step into a new frame or return to previous frame.
43
44  LastStepAction = StepFrame
45};
46
47// Type of exception break. NOTE: These values are in macros.py as well.
48enum ExceptionBreakType {
49  BreakException = 0,
50  BreakUncaughtException = 1
51};
52
53
54// Type of exception break.
55enum BreakLocatorType { ALL_BREAK_LOCATIONS, CALLS_AND_RETURNS };
56
57
58// The different types of breakpoint position alignments.
59// Must match Debug.BreakPositionAlignment in debug.js
60enum BreakPositionAlignment {
61  STATEMENT_ALIGNED = 0,
62  BREAK_POSITION_ALIGNED = 1
63};
64
65enum DebugBreakType {
66  NOT_DEBUG_BREAK,
67  DEBUGGER_STATEMENT,
68  DEBUG_BREAK_SLOT,
69  DEBUG_BREAK_SLOT_AT_CALL,
70  DEBUG_BREAK_SLOT_AT_RETURN,
71  DEBUG_BREAK_SLOT_AT_TAIL_CALL,
72};
73
74class BreakLocation {
75 public:
76  static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
77                                 JavaScriptFrame* frame);
78
79  static void AllAtCurrentStatement(Handle<DebugInfo> debug_info,
80                                    JavaScriptFrame* frame,
81                                    List<BreakLocation>* result_out);
82
83  inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
84  inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
85  inline bool IsTailCall() const {
86    return type_ == DEBUG_BREAK_SLOT_AT_TAIL_CALL;
87  }
88  inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
89  inline bool IsDebuggerStatement() const {
90    return type_ == DEBUGGER_STATEMENT;
91  }
92
93  bool HasBreakPoint(Handle<DebugInfo> debug_info) const;
94
95  inline int position() const { return position_; }
96
97 private:
98  BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
99                int code_offset, int position)
100      : abstract_code_(abstract_code),
101        code_offset_(code_offset),
102        type_(type),
103        position_(position) {
104    DCHECK_NE(NOT_DEBUG_BREAK, type_);
105  }
106
107  static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
108                                      Handle<AbstractCode> abstract_code,
109                                      int offset);
110
111  void SetDebugBreak();
112  void ClearDebugBreak();
113
114  Handle<AbstractCode> abstract_code_;
115  int code_offset_;
116  DebugBreakType type_;
117  int position_;
118
119  friend class CodeBreakIterator;
120  friend class BytecodeArrayBreakIterator;
121};
122
123class BreakIterator {
124 public:
125  static std::unique_ptr<BreakIterator> GetIterator(
126      Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code,
127      BreakLocatorType type = ALL_BREAK_LOCATIONS);
128
129  virtual ~BreakIterator() {}
130
131  virtual BreakLocation GetBreakLocation() = 0;
132  virtual bool Done() const = 0;
133  virtual void Next() = 0;
134
135  void SkipTo(int count) {
136    while (count-- > 0) Next();
137  }
138
139  virtual int code_offset() = 0;
140  int break_index() const { return break_index_; }
141  inline int position() const { return position_; }
142  inline int statement_position() const { return statement_position_; }
143
144  virtual bool IsDebugBreak() = 0;
145  virtual void ClearDebugBreak() = 0;
146  virtual void SetDebugBreak() = 0;
147
148 protected:
149  explicit BreakIterator(Handle<DebugInfo> debug_info,
150                         BreakLocatorType break_locator_type);
151
152  int BreakIndexFromPosition(int position, BreakPositionAlignment alignment);
153
154  Isolate* isolate() { return debug_info_->GetIsolate(); }
155
156  Handle<DebugInfo> debug_info_;
157  int break_index_;
158  int position_;
159  int statement_position_;
160  BreakLocatorType break_locator_type_;
161
162 private:
163  DisallowHeapAllocation no_gc_;
164  DISALLOW_COPY_AND_ASSIGN(BreakIterator);
165};
166
167class CodeBreakIterator : public BreakIterator {
168 public:
169  CodeBreakIterator(Handle<DebugInfo> debug_info, BreakLocatorType type);
170  ~CodeBreakIterator() override {}
171
172  BreakLocation GetBreakLocation() override;
173  bool Done() const override { return reloc_iterator_.done(); }
174  void Next() override;
175
176  bool IsDebugBreak() override;
177  void ClearDebugBreak() override;
178  void SetDebugBreak() override;
179
180  void SkipToPosition(int position, BreakPositionAlignment alignment);
181
182  int code_offset() override {
183    return static_cast<int>(rinfo()->pc() -
184                            debug_info_->DebugCode()->instruction_start());
185  }
186
187 private:
188  int GetModeMask(BreakLocatorType type);
189  DebugBreakType GetDebugBreakType();
190
191  RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
192  RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
193
194  RelocIterator reloc_iterator_;
195  SourcePositionTableIterator source_position_iterator_;
196  DISALLOW_COPY_AND_ASSIGN(CodeBreakIterator);
197};
198
199class BytecodeArrayBreakIterator : public BreakIterator {
200 public:
201  BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info,
202                             BreakLocatorType type);
203  ~BytecodeArrayBreakIterator() override {}
204
205  BreakLocation GetBreakLocation() override;
206  bool Done() const override { return source_position_iterator_.done(); }
207  void Next() override;
208
209  bool IsDebugBreak() override;
210  void ClearDebugBreak() override;
211  void SetDebugBreak() override;
212
213  void SkipToPosition(int position, BreakPositionAlignment alignment);
214
215  int code_offset() override { return source_position_iterator_.code_offset(); }
216
217 private:
218  DebugBreakType GetDebugBreakType();
219
220  SourcePositionTableIterator source_position_iterator_;
221  DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBreakIterator);
222};
223
224// Linked list holding debug info objects. The debug info objects are kept as
225// weak handles to avoid a debug info object to keep a function alive.
226class DebugInfoListNode {
227 public:
228  explicit DebugInfoListNode(DebugInfo* debug_info);
229  ~DebugInfoListNode();
230
231  DebugInfoListNode* next() { return next_; }
232  void set_next(DebugInfoListNode* next) { next_ = next; }
233  Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); }
234
235 private:
236  // Global (weak) handle to the debug info object.
237  DebugInfo** debug_info_;
238
239  // Next pointer for linked list.
240  DebugInfoListNode* next_;
241};
242
243
244// Message delivered to the message handler callback. This is either a debugger
245// event or the response to a command.
246class MessageImpl: public v8::Debug::Message {
247 public:
248  // Create a message object for a debug event.
249  static MessageImpl NewEvent(DebugEvent event,
250                              bool running,
251                              Handle<JSObject> exec_state,
252                              Handle<JSObject> event_data);
253
254  // Create a message object for the response to a debug command.
255  static MessageImpl NewResponse(DebugEvent event,
256                                 bool running,
257                                 Handle<JSObject> exec_state,
258                                 Handle<JSObject> event_data,
259                                 Handle<String> response_json,
260                                 v8::Debug::ClientData* client_data);
261
262  // Implementation of interface v8::Debug::Message.
263  virtual bool IsEvent() const;
264  virtual bool IsResponse() const;
265  virtual DebugEvent GetEvent() const;
266  virtual bool WillStartRunning() const;
267  virtual v8::Local<v8::Object> GetExecutionState() const;
268  virtual v8::Local<v8::Object> GetEventData() const;
269  virtual v8::Local<v8::String> GetJSON() const;
270  virtual v8::Local<v8::Context> GetEventContext() const;
271  virtual v8::Debug::ClientData* GetClientData() const;
272  virtual v8::Isolate* GetIsolate() const;
273
274 private:
275  MessageImpl(bool is_event,
276              DebugEvent event,
277              bool running,
278              Handle<JSObject> exec_state,
279              Handle<JSObject> event_data,
280              Handle<String> response_json,
281              v8::Debug::ClientData* client_data);
282
283  bool is_event_;  // Does this message represent a debug event?
284  DebugEvent event_;  // Debug event causing the break.
285  bool running_;  // Will the VM start running after this event?
286  Handle<JSObject> exec_state_;  // Current execution state.
287  Handle<JSObject> event_data_;  // Data associated with the event.
288  Handle<String> response_json_;  // Response JSON if message holds a response.
289  v8::Debug::ClientData* client_data_;  // Client data passed with the request.
290};
291
292
293// Details of the debug event delivered to the debug event listener.
294class EventDetailsImpl : public v8::DebugInterface::EventDetails {
295 public:
296  EventDetailsImpl(DebugEvent event,
297                   Handle<JSObject> exec_state,
298                   Handle<JSObject> event_data,
299                   Handle<Object> callback_data,
300                   v8::Debug::ClientData* client_data);
301  virtual DebugEvent GetEvent() const;
302  virtual v8::Local<v8::Object> GetExecutionState() const;
303  virtual v8::Local<v8::Object> GetEventData() const;
304  virtual v8::Local<v8::Context> GetEventContext() const;
305  virtual v8::Local<v8::Value> GetCallbackData() const;
306  virtual v8::Debug::ClientData* GetClientData() const;
307  virtual v8::Isolate* GetIsolate() const;
308
309 private:
310  DebugEvent event_;  // Debug event causing the break.
311  Handle<JSObject> exec_state_;         // Current execution state.
312  Handle<JSObject> event_data_;         // Data associated with the event.
313  Handle<Object> callback_data_;        // User data passed with the callback
314                                        // when it was registered.
315  v8::Debug::ClientData* client_data_;  // Data passed to DebugBreakForCommand.
316};
317
318
319// Message send by user to v8 debugger or debugger output message.
320// In addition to command text it may contain a pointer to some user data
321// which are expected to be passed along with the command reponse to message
322// handler.
323class CommandMessage {
324 public:
325  static CommandMessage New(const Vector<uint16_t>& command,
326                            v8::Debug::ClientData* data);
327  CommandMessage();
328
329  // Deletes user data and disposes of the text.
330  void Dispose();
331  Vector<uint16_t> text() const { return text_; }
332  v8::Debug::ClientData* client_data() const { return client_data_; }
333 private:
334  CommandMessage(const Vector<uint16_t>& text,
335                 v8::Debug::ClientData* data);
336
337  Vector<uint16_t> text_;
338  v8::Debug::ClientData* client_data_;
339};
340
341
342// A Queue of CommandMessage objects.  A thread-safe version is
343// LockingCommandMessageQueue, based on this class.
344class CommandMessageQueue BASE_EMBEDDED {
345 public:
346  explicit CommandMessageQueue(int size);
347  ~CommandMessageQueue();
348  bool IsEmpty() const { return start_ == end_; }
349  CommandMessage Get();
350  void Put(const CommandMessage& message);
351  void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
352 private:
353  // Doubles the size of the message queue, and copies the messages.
354  void Expand();
355
356  CommandMessage* messages_;
357  int start_;
358  int end_;
359  int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
360};
361
362
363// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
364// messages.  The message data is not managed by LockingCommandMessageQueue.
365// Pointers to the data are passed in and out. Implemented by adding a
366// Mutex to CommandMessageQueue.  Includes logging of all puts and gets.
367class LockingCommandMessageQueue BASE_EMBEDDED {
368 public:
369  LockingCommandMessageQueue(Logger* logger, int size);
370  bool IsEmpty() const;
371  CommandMessage Get();
372  void Put(const CommandMessage& message);
373  void Clear();
374 private:
375  Logger* logger_;
376  CommandMessageQueue queue_;
377  mutable base::Mutex mutex_;
378  DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
379};
380
381
382class DebugFeatureTracker {
383 public:
384  enum Feature {
385    kActive = 1,
386    kBreakPoint = 2,
387    kStepping = 3,
388    kHeapSnapshot = 4,
389    kAllocationTracking = 5,
390    kProfiler = 6,
391    kLiveEdit = 7,
392  };
393
394  explicit DebugFeatureTracker(Isolate* isolate)
395      : isolate_(isolate), bitfield_(0) {}
396  void Track(Feature feature);
397
398 private:
399  Isolate* isolate_;
400  uint32_t bitfield_;
401};
402
403
404// This class contains the debugger support. The main purpose is to handle
405// setting break points in the code.
406//
407// This class controls the debug info for all functions which currently have
408// active breakpoints in them. This debug info is held in the heap root object
409// debug_info which is a FixedArray. Each entry in this list is of class
410// DebugInfo.
411class Debug {
412 public:
413  // Debug event triggers.
414  void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
415
416  void OnThrow(Handle<Object> exception);
417  void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
418  void OnCompileError(Handle<Script> script);
419  void OnBeforeCompile(Handle<Script> script);
420  void OnAfterCompile(Handle<Script> script);
421  void OnAsyncTaskEvent(Handle<String> type, Handle<Object> id,
422                        Handle<String> name);
423
424  // API facing.
425  void SetEventListener(Handle<Object> callback, Handle<Object> data);
426  void SetMessageHandler(v8::Debug::MessageHandler handler);
427  void EnqueueCommandMessage(Vector<const uint16_t> command,
428                             v8::Debug::ClientData* client_data = NULL);
429  MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun,
430                                           Handle<Object> data);
431  Handle<Context> GetDebugContext();
432  void HandleDebugBreak();
433  void ProcessDebugMessages(bool debug_command_only);
434
435  // Internal logic
436  bool Load();
437  void Break(JavaScriptFrame* frame);
438  void SetAfterBreakTarget(JavaScriptFrame* frame);
439
440  // Scripts handling.
441  Handle<FixedArray> GetLoadedScripts();
442
443  // Break point handling.
444  bool SetBreakPoint(Handle<JSFunction> function,
445                     Handle<Object> break_point_object,
446                     int* source_position);
447  bool SetBreakPointForScript(Handle<Script> script,
448                              Handle<Object> break_point_object,
449                              int* source_position,
450                              BreakPositionAlignment alignment);
451  void ClearBreakPoint(Handle<Object> break_point_object);
452  void ChangeBreakOnException(ExceptionBreakType type, bool enable);
453  bool IsBreakOnException(ExceptionBreakType type);
454
455  // Stepping handling.
456  void PrepareStep(StepAction step_action);
457  void PrepareStepIn(Handle<JSFunction> function);
458  void PrepareStepInSuspendedGenerator();
459  void PrepareStepOnThrow();
460  void ClearStepping();
461  void ClearStepOut();
462
463  bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
464  bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
465                              int end_position, std::set<int>* positions);
466
467  void RecordAsyncFunction(Handle<JSGeneratorObject> generator_object);
468
469  // Returns whether the operation succeeded. Compilation can only be triggered
470  // if a valid closure is passed as the second argument, otherwise the shared
471  // function needs to be compiled already.
472  bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
473                       Handle<JSFunction> function);
474  void CreateDebugInfo(Handle<SharedFunctionInfo> shared);
475  static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
476
477  template <typename C>
478  bool CompileToRevealInnerFunctions(C* compilable);
479
480  // This function is used in FunctionNameUsing* tests.
481  Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
482                                                int position);
483
484  static Handle<Object> GetSourceBreakLocations(
485      Handle<SharedFunctionInfo> shared,
486      BreakPositionAlignment position_aligment);
487
488  // Check whether a global object is the debug global object.
489  bool IsDebugGlobal(JSGlobalObject* global);
490
491  // Check whether this frame is just about to return.
492  bool IsBreakAtReturn(JavaScriptFrame* frame);
493
494  // Support for LiveEdit
495  void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
496                             LiveEditFrameDropMode mode);
497
498  // Threading support.
499  char* ArchiveDebug(char* to);
500  char* RestoreDebug(char* from);
501  static int ArchiveSpacePerThread();
502  void FreeThreadResources() { }
503  void Iterate(ObjectVisitor* v);
504
505  bool CheckExecutionState(int id) {
506    return CheckExecutionState() && break_id() == id;
507  }
508
509  bool CheckExecutionState() {
510    return is_active() && !debug_context().is_null() && break_id() != 0;
511  }
512
513  // Flags and states.
514  DebugScope* debugger_entry() {
515    return reinterpret_cast<DebugScope*>(
516        base::NoBarrier_Load(&thread_local_.current_debug_scope_));
517  }
518  inline Handle<Context> debug_context() { return debug_context_; }
519
520  void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
521  bool live_edit_enabled() const {
522    return FLAG_enable_liveedit && live_edit_enabled_;
523  }
524
525  inline bool is_active() const { return is_active_; }
526  inline bool is_loaded() const { return !debug_context_.is_null(); }
527  inline bool in_debug_scope() const {
528    return !!base::NoBarrier_Load(&thread_local_.current_debug_scope_);
529  }
530  void set_break_points_active(bool v) { break_points_active_ = v; }
531  bool break_points_active() const { return break_points_active_; }
532
533  StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
534  int break_id() { return thread_local_.break_id_; }
535
536  Handle<Object> return_value() { return thread_local_.return_value_; }
537  void set_return_value(Handle<Object> value) {
538    thread_local_.return_value_ = value;
539  }
540
541  // Support for embedding into generated code.
542  Address is_active_address() {
543    return reinterpret_cast<Address>(&is_active_);
544  }
545
546  Address after_break_target_address() {
547    return reinterpret_cast<Address>(&after_break_target_);
548  }
549
550  Address last_step_action_address() {
551    return reinterpret_cast<Address>(&thread_local_.last_step_action_);
552  }
553
554  Address suspended_generator_address() {
555    return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
556  }
557
558  StepAction last_step_action() { return thread_local_.last_step_action_; }
559
560  DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }
561
562 private:
563  explicit Debug(Isolate* isolate);
564
565  void UpdateState();
566  void Unload();
567  void SetNextBreakId() {
568    thread_local_.break_id_ = ++thread_local_.break_count_;
569  }
570
571  // Check whether there are commands in the command queue.
572  inline bool has_commands() const { return !command_queue_.IsEmpty(); }
573  inline bool ignore_events() const { return is_suppressed_ || !is_active_; }
574  inline bool break_disabled() const {
575    return break_disabled_ || in_debug_event_listener_;
576  }
577
578  void clear_suspended_generator() {
579    thread_local_.suspended_generator_ = Smi::kZero;
580  }
581
582  bool has_suspended_generator() const {
583    return thread_local_.suspended_generator_ != Smi::kZero;
584  }
585
586  void OnException(Handle<Object> exception, Handle<Object> promise);
587
588  // Constructors for debug event objects.
589  MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
590  MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent(
591      Handle<Object> break_points_hit);
592  MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent(
593      Handle<Object> exception,
594      bool uncaught,
595      Handle<Object> promise);
596  MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent(
597      Handle<Script> script, v8::DebugEvent type);
598  MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(Handle<String> type,
599                                                         Handle<Object> id,
600                                                         Handle<String> name);
601
602  // Mirror cache handling.
603  void ClearMirrorCache();
604
605  void CallEventCallback(v8::DebugEvent event,
606                         Handle<Object> exec_state,
607                         Handle<Object> event_data,
608                         v8::Debug::ClientData* client_data);
609  void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script);
610  void ProcessDebugEvent(v8::DebugEvent event,
611                         Handle<JSObject> event_data,
612                         bool auto_continue);
613  void NotifyMessageHandler(v8::DebugEvent event,
614                            Handle<JSObject> exec_state,
615                            Handle<JSObject> event_data,
616                            bool auto_continue);
617  void InvokeMessageHandler(MessageImpl message);
618
619  // Find the closest source position for a break point for a given position.
620  int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position,
621                            BreakPositionAlignment alignment);
622  // Instrument code to break at break points.
623  void ApplyBreakPoints(Handle<DebugInfo> debug_info);
624  // Clear code from instrumentation.
625  void ClearBreakPoints(Handle<DebugInfo> debug_info);
626  // Clear all code from instrumentation.
627  void ClearAllBreakPoints();
628  // Instrument a function with one-shots.
629  void FloodWithOneShot(Handle<JSFunction> function,
630                        BreakLocatorType type = ALL_BREAK_LOCATIONS);
631  // Clear all one-shot instrumentations, but restore break points.
632  void ClearOneShot();
633
634  void ActivateStepOut(StackFrame* frame);
635  void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info);
636  Handle<Object> CheckBreakPoints(Handle<DebugInfo> debug_info,
637                                  BreakLocation* location,
638                                  bool* has_break_points = nullptr);
639  bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
640  bool CheckBreakPoint(Handle<Object> break_point_object);
641  MaybeHandle<Object> CallFunction(const char* name, int argc,
642                                   Handle<Object> args[]);
643
644  inline void AssertDebugContext() {
645    DCHECK(isolate_->context() == *debug_context());
646    DCHECK(in_debug_scope());
647  }
648
649  void ThreadInit();
650
651  void PrintBreakLocation();
652
653  // Global handles.
654  Handle<Context> debug_context_;
655  Handle<Object> event_listener_;
656  Handle<Object> event_listener_data_;
657
658  v8::Debug::MessageHandler message_handler_;
659
660  static const int kQueueInitialSize = 4;
661  base::Semaphore command_received_;  // Signaled for each command received.
662  LockingCommandMessageQueue command_queue_;
663
664  bool is_active_;
665  bool is_suppressed_;
666  bool live_edit_enabled_;
667  bool break_disabled_;
668  bool break_points_active_;
669  bool in_debug_event_listener_;
670  bool break_on_exception_;
671  bool break_on_uncaught_exception_;
672
673  DebugInfoListNode* debug_info_list_;  // List of active debug info objects.
674
675  // Storage location for jump when exiting debug break calls.
676  // Note that this address is not GC safe.  It should be computed immediately
677  // before returning to the DebugBreakCallHelper.
678  Address after_break_target_;
679
680  // Used to collect histogram data on debugger feature usage.
681  DebugFeatureTracker feature_tracker_;
682
683  // Per-thread data.
684  class ThreadLocal {
685   public:
686    // Top debugger entry.
687    base::AtomicWord current_debug_scope_;
688
689    // Counter for generating next break id.
690    int break_count_;
691
692    // Current break id.
693    int break_id_;
694
695    // Frame id for the frame of the current break.
696    StackFrame::Id break_frame_id_;
697
698    // Step action for last step performed.
699    StepAction last_step_action_;
700
701    // Source statement position from last step next action.
702    int last_statement_position_;
703
704    // Frame pointer from last step next or step frame action.
705    Address last_fp_;
706
707    // Frame pointer of the target frame we want to arrive at.
708    Address target_fp_;
709
710    // Stores the way how LiveEdit has patched the stack. It is used when
711    // debugger returns control back to user script.
712    LiveEditFrameDropMode frame_drop_mode_;
713
714    // Value of accumulator in interpreter frames. In non-interpreter frames
715    // this value will be the hole.
716    Handle<Object> return_value_;
717
718    Object* suspended_generator_;
719  };
720
721  // Storage location for registers when handling debug break calls
722  ThreadLocal thread_local_;
723
724  Isolate* isolate_;
725
726  friend class Isolate;
727  friend class DebugScope;
728  friend class DisableBreak;
729  friend class LiveEdit;
730  friend class SuppressDebug;
731
732  friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
733  friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
734
735  DISALLOW_COPY_AND_ASSIGN(Debug);
736};
737
738
739// This scope is used to load and enter the debug context and create a new
740// break state.  Leaving the scope will restore the previous state.
741// On failure to load, FailedToEnter returns true.
742class DebugScope BASE_EMBEDDED {
743 public:
744  explicit DebugScope(Debug* debug);
745  ~DebugScope();
746
747  // Check whether loading was successful.
748  inline bool failed() { return failed_; }
749
750  // Get the active context from before entering the debugger.
751  inline Handle<Context> GetContext() { return save_.context(); }
752
753 private:
754  Isolate* isolate() { return debug_->isolate_; }
755
756  Debug* debug_;
757  DebugScope* prev_;               // Previous scope if entered recursively.
758  StackFrame::Id break_frame_id_;  // Previous break frame id.
759  int break_id_;                   // Previous break id.
760  Handle<Object> return_value_;    // Previous result.
761  bool failed_;                    // Did the debug context fail to load?
762  SaveContext save_;               // Saves previous context.
763  PostponeInterruptsScope no_termination_exceptons_;
764};
765
766
767// Stack allocated class for disabling break.
768class DisableBreak BASE_EMBEDDED {
769 public:
770  explicit DisableBreak(Debug* debug, bool disable_break)
771      : debug_(debug),
772        previous_break_disabled_(debug->break_disabled_),
773        previous_in_debug_event_listener_(debug->in_debug_event_listener_) {
774    debug_->break_disabled_ = disable_break;
775    debug_->in_debug_event_listener_ = disable_break;
776  }
777  ~DisableBreak() {
778    debug_->break_disabled_ = previous_break_disabled_;
779    debug_->in_debug_event_listener_ = previous_in_debug_event_listener_;
780  }
781
782 private:
783  Debug* debug_;
784  bool previous_break_disabled_;
785  bool previous_in_debug_event_listener_;
786  DISALLOW_COPY_AND_ASSIGN(DisableBreak);
787};
788
789
790class SuppressDebug BASE_EMBEDDED {
791 public:
792  explicit SuppressDebug(Debug* debug)
793      : debug_(debug), old_state_(debug->is_suppressed_) {
794    debug_->is_suppressed_ = true;
795  }
796  ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
797
798 private:
799  Debug* debug_;
800  bool old_state_;
801  DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
802};
803
804
805// Code generator routines.
806class DebugCodegen : public AllStatic {
807 public:
808  enum DebugBreakCallHelperMode {
809    SAVE_RESULT_REGISTER,
810    IGNORE_RESULT_REGISTER
811  };
812
813  static void GenerateDebugBreakStub(MacroAssembler* masm,
814                                     DebugBreakCallHelperMode mode);
815
816  // FrameDropper is a code replacement for a JavaScript frame with possibly
817  // several frames above.
818  // There is no calling conventions here, because it never actually gets
819  // called, it only gets returned to.
820  static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
821
822
823  static void GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode);
824
825  static void PatchDebugBreakSlot(Isolate* isolate, Address pc,
826                                  Handle<Code> code);
827  static bool DebugBreakSlotIsPatched(Address pc);
828  static void ClearDebugBreakSlot(Isolate* isolate, Address pc);
829};
830
831
832}  // namespace internal
833}  // namespace v8
834
835#endif  // V8_DEBUG_DEBUG_H_
836