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