• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_DEBUG_H_
29 #define V8_DEBUG_H_
30 
31 #include "allocation.h"
32 #include "arguments.h"
33 #include "assembler.h"
34 #include "debug-agent.h"
35 #include "execution.h"
36 #include "factory.h"
37 #include "flags.h"
38 #include "frames-inl.h"
39 #include "hashmap.h"
40 #include "platform.h"
41 #include "string-stream.h"
42 #include "v8threads.h"
43 
44 #ifdef ENABLE_DEBUGGER_SUPPORT
45 #include "../include/v8-debug.h"
46 
47 namespace v8 {
48 namespace internal {
49 
50 
51 // Forward declarations.
52 class EnterDebugger;
53 
54 
55 // Step actions. NOTE: These values are in macros.py as well.
56 enum StepAction {
57   StepNone = -1,  // Stepping not prepared.
58   StepOut = 0,   // Step out of the current function.
59   StepNext = 1,  // Step to the next statement in the current function.
60   StepIn = 2,    // Step into new functions invoked or the next statement
61                  // in the current function.
62   StepMin = 3,   // Perform a minimum step in the current function.
63   StepInMin = 4  // Step into new functions invoked or perform a minimum step
64                  // in the current function.
65 };
66 
67 
68 // Type of exception break. NOTE: These values are in macros.py as well.
69 enum ExceptionBreakType {
70   BreakException = 0,
71   BreakUncaughtException = 1
72 };
73 
74 
75 // Type of exception break. NOTE: These values are in macros.py as well.
76 enum BreakLocatorType {
77   ALL_BREAK_LOCATIONS = 0,
78   SOURCE_BREAK_LOCATIONS = 1
79 };
80 
81 
82 // Class for iterating through the break points in a function and changing
83 // them.
84 class BreakLocationIterator {
85  public:
86   explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
87                                  BreakLocatorType type);
88   virtual ~BreakLocationIterator();
89 
90   void Next();
91   void Next(int count);
92   void FindBreakLocationFromAddress(Address pc);
93   void FindBreakLocationFromPosition(int position);
94   void Reset();
95   bool Done() const;
96   void SetBreakPoint(Handle<Object> break_point_object);
97   void ClearBreakPoint(Handle<Object> break_point_object);
98   void SetOneShot();
99   void ClearOneShot();
100   void PrepareStepIn();
101   bool IsExit() const;
102   bool HasBreakPoint();
103   bool IsDebugBreak();
104   Object* BreakPointObjects();
105   void ClearAllDebugBreak();
106 
107 
code_position()108   inline int code_position() {
109     return static_cast<int>(pc() - debug_info_->code()->entry());
110   }
break_point()111   inline int break_point() { return break_point_; }
position()112   inline int position() { return position_; }
statement_position()113   inline int statement_position() { return statement_position_; }
pc()114   inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
code()115   inline Code* code() { return debug_info_->code(); }
rinfo()116   inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
rmode()117   inline RelocInfo::Mode rmode() const {
118     return reloc_iterator_->rinfo()->rmode();
119   }
original_rinfo()120   inline RelocInfo* original_rinfo() {
121     return reloc_iterator_original_->rinfo();
122   }
original_rmode()123   inline RelocInfo::Mode original_rmode() const {
124     return reloc_iterator_original_->rinfo()->rmode();
125   }
126 
127   bool IsDebuggerStatement();
128 
129  protected:
130   bool RinfoDone() const;
131   void RinfoNext();
132 
133   BreakLocatorType type_;
134   int break_point_;
135   int position_;
136   int statement_position_;
137   Handle<DebugInfo> debug_info_;
138   RelocIterator* reloc_iterator_;
139   RelocIterator* reloc_iterator_original_;
140 
141  private:
142   void SetDebugBreak();
143   void ClearDebugBreak();
144 
145   void SetDebugBreakAtIC();
146   void ClearDebugBreakAtIC();
147 
148   bool IsDebugBreakAtReturn();
149   void SetDebugBreakAtReturn();
150   void ClearDebugBreakAtReturn();
151 
152   bool IsDebugBreakSlot();
153   bool IsDebugBreakAtSlot();
154   void SetDebugBreakAtSlot();
155   void ClearDebugBreakAtSlot();
156 
157   DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
158 };
159 
160 
161 // Cache of all script objects in the heap. When a script is added a weak handle
162 // to it is created and that weak handle is stored in the cache. The weak handle
163 // callback takes care of removing the script from the cache. The key used in
164 // the cache is the script id.
165 class ScriptCache : private HashMap {
166  public:
ScriptCache()167   ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {}
~ScriptCache()168   virtual ~ScriptCache() { Clear(); }
169 
170   // Add script to the cache.
171   void Add(Handle<Script> script);
172 
173   // Return the scripts in the cache.
174   Handle<FixedArray> GetScripts();
175 
176   // Generate debugger events for collected scripts.
177   void ProcessCollectedScripts();
178 
179  private:
180   // Calculate the hash value from the key (script id).
Hash(int key)181   static uint32_t Hash(int key) {
182     return ComputeIntegerHash(key, v8::internal::kZeroHashSeed);
183   }
184 
185   // Scripts match if their keys (script id) match.
ScriptMatch(void * key1,void * key2)186   static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
187 
188   // Clear the cache releasing all the weak handles.
189   void Clear();
190 
191   // Weak handle callback for scripts in the cache.
192   static void HandleWeakScript(v8::Persistent<v8::Value> obj, void* data);
193 
194   // List used during GC to temporarily store id's of collected scripts.
195   List<int> collected_scripts_;
196 };
197 
198 
199 // Linked list holding debug info objects. The debug info objects are kept as
200 // weak handles to avoid a debug info object to keep a function alive.
201 class DebugInfoListNode {
202  public:
203   explicit DebugInfoListNode(DebugInfo* debug_info);
204   virtual ~DebugInfoListNode();
205 
next()206   DebugInfoListNode* next() { return next_; }
set_next(DebugInfoListNode * next)207   void set_next(DebugInfoListNode* next) { next_ = next; }
debug_info()208   Handle<DebugInfo> debug_info() { return debug_info_; }
209 
210  private:
211   // Global (weak) handle to the debug info object.
212   Handle<DebugInfo> debug_info_;
213 
214   // Next pointer for linked list.
215   DebugInfoListNode* next_;
216 };
217 
218 // This class contains the debugger support. The main purpose is to handle
219 // setting break points in the code.
220 //
221 // This class controls the debug info for all functions which currently have
222 // active breakpoints in them. This debug info is held in the heap root object
223 // debug_info which is a FixedArray. Each entry in this list is of class
224 // DebugInfo.
225 class Debug {
226  public:
227   void SetUp(bool create_heap_objects);
228   bool Load();
229   void Unload();
IsLoaded()230   bool IsLoaded() { return !debug_context_.is_null(); }
InDebugger()231   bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
232   void PreemptionWhileInDebugger();
233   void Iterate(ObjectVisitor* v);
234 
235   Object* Break(Arguments args);
236   void SetBreakPoint(Handle<SharedFunctionInfo> shared,
237                      Handle<Object> break_point_object,
238                      int* source_position);
239   void ClearBreakPoint(Handle<Object> break_point_object);
240   void ClearAllBreakPoints();
241   void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
242   void FloodBoundFunctionWithOneShot(Handle<JSFunction> function);
243   void FloodHandlerWithOneShot();
244   void ChangeBreakOnException(ExceptionBreakType type, bool enable);
245   bool IsBreakOnException(ExceptionBreakType type);
246   void PrepareStep(StepAction step_action, int step_count);
247   void ClearStepping();
248   bool StepNextContinue(BreakLocationIterator* break_location_iterator,
249                         JavaScriptFrame* frame);
250   static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
251   static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
252 
253   void PrepareForBreakPoints();
254 
255   // Returns whether the operation succeeded.
256   bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
257 
258   // Returns true if the current stub call is patched to call the debugger.
259   static bool IsDebugBreak(Address addr);
260   // Returns true if the current return statement has been patched to be
261   // a debugger breakpoint.
262   static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
263 
264   // Check whether a code stub with the specified major key is a possible break
265   // point location.
266   static bool IsSourceBreakStub(Code* code);
267   static bool IsBreakStub(Code* code);
268 
269   // Find the builtin to use for invoking the debug break
270   static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
271 
272   static Handle<Object> GetSourceBreakLocations(
273       Handle<SharedFunctionInfo> shared);
274 
275   // Getter for the debug_context.
debug_context()276   inline Handle<Context> debug_context() { return debug_context_; }
277 
278   // Check whether a global object is the debug global object.
279   bool IsDebugGlobal(GlobalObject* global);
280 
281   // Check whether this frame is just about to return.
282   bool IsBreakAtReturn(JavaScriptFrame* frame);
283 
284   // Fast check to see if any break points are active.
has_break_points()285   inline bool has_break_points() { return has_break_points_; }
286 
287   void NewBreak(StackFrame::Id break_frame_id);
288   void SetBreak(StackFrame::Id break_frame_id, int break_id);
break_frame_id()289   StackFrame::Id break_frame_id() {
290     return thread_local_.break_frame_id_;
291   }
break_id()292   int break_id() { return thread_local_.break_id_; }
293 
StepInActive()294   bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
295   void HandleStepIn(Handle<JSFunction> function,
296                     Handle<Object> holder,
297                     Address fp,
298                     bool is_constructor);
step_in_fp()299   Address step_in_fp() { return thread_local_.step_into_fp_; }
step_in_fp_addr()300   Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
301 
StepOutActive()302   bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
step_out_fp()303   Address step_out_fp() { return thread_local_.step_out_fp_; }
304 
debugger_entry()305   EnterDebugger* debugger_entry() {
306     return thread_local_.debugger_entry_;
307   }
set_debugger_entry(EnterDebugger * entry)308   void set_debugger_entry(EnterDebugger* entry) {
309     thread_local_.debugger_entry_ = entry;
310   }
311 
312   // Check whether any of the specified interrupts are pending.
is_interrupt_pending(InterruptFlag what)313   bool is_interrupt_pending(InterruptFlag what) {
314     return (thread_local_.pending_interrupts_ & what) != 0;
315   }
316 
317   // Set specified interrupts as pending.
set_interrupts_pending(InterruptFlag what)318   void set_interrupts_pending(InterruptFlag what) {
319     thread_local_.pending_interrupts_ |= what;
320   }
321 
322   // Clear specified interrupts from pending.
clear_interrupt_pending(InterruptFlag what)323   void clear_interrupt_pending(InterruptFlag what) {
324     thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
325   }
326 
327   // Getter and setter for the disable break state.
disable_break()328   bool disable_break() { return disable_break_; }
set_disable_break(bool disable_break)329   void set_disable_break(bool disable_break) {
330     disable_break_ = disable_break;
331   }
332 
333   // Getters for the current exception break state.
break_on_exception()334   bool break_on_exception() { return break_on_exception_; }
break_on_uncaught_exception()335   bool break_on_uncaught_exception() {
336     return break_on_uncaught_exception_;
337   }
338 
339   enum AddressId {
340     k_after_break_target_address,
341     k_debug_break_return_address,
342     k_debug_break_slot_address,
343     k_restarter_frame_function_pointer
344   };
345 
346   // Support for setting the address to jump to when returning from break point.
after_break_target_address()347   Address* after_break_target_address() {
348     return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
349   }
restarter_frame_function_pointer_address()350   Address* restarter_frame_function_pointer_address() {
351     Object*** address = &thread_local_.restarter_frame_function_pointer_;
352     return reinterpret_cast<Address*>(address);
353   }
354 
355   // Support for saving/restoring registers when handling debug break calls.
register_address(int r)356   Object** register_address(int r) {
357     return &registers_[r];
358   }
359 
360   // Access to the debug break on return code.
debug_break_return()361   Code* debug_break_return() { return debug_break_return_; }
debug_break_return_address()362   Code** debug_break_return_address() {
363     return &debug_break_return_;
364   }
365 
366   // Access to the debug break in debug break slot code.
debug_break_slot()367   Code* debug_break_slot() { return debug_break_slot_; }
debug_break_slot_address()368   Code** debug_break_slot_address() {
369     return &debug_break_slot_;
370   }
371 
372   static const int kEstimatedNofDebugInfoEntries = 16;
373   static const int kEstimatedNofBreakPointsInFunction = 16;
374 
375   // Passed to MakeWeak.
376   static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
377 
378   friend class Debugger;
379   friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
380   friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
381 
382   // Threading support.
383   char* ArchiveDebug(char* to);
384   char* RestoreDebug(char* from);
385   static int ArchiveSpacePerThread();
FreeThreadResources()386   void FreeThreadResources() { }
387 
388   // Mirror cache handling.
389   void ClearMirrorCache();
390 
391   // Script cache handling.
392   void CreateScriptCache();
393   void DestroyScriptCache();
394   void AddScriptToScriptCache(Handle<Script> script);
395   Handle<FixedArray> GetLoadedScripts();
396 
397   // Garbage collection notifications.
398   void AfterGarbageCollection();
399 
400   // Code generator routines.
401   static void GenerateSlot(MacroAssembler* masm);
402   static void GenerateLoadICDebugBreak(MacroAssembler* masm);
403   static void GenerateStoreICDebugBreak(MacroAssembler* masm);
404   static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
405   static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
406   static void GenerateReturnDebugBreak(MacroAssembler* masm);
407   static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm);
408   static void GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm);
409   static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm);
410   static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm);
411   static void GenerateSlotDebugBreak(MacroAssembler* masm);
412   static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
413 
414   // FrameDropper is a code replacement for a JavaScript frame with possibly
415   // several frames above.
416   // There is no calling conventions here, because it never actually gets
417   // called, it only gets returned to.
418   static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
419 
420   // Called from stub-cache.cc.
421   static void GenerateCallICDebugBreak(MacroAssembler* masm);
422 
423   // Describes how exactly a frame has been dropped from stack.
424   enum FrameDropMode {
425     // No frame has been dropped.
426     FRAMES_UNTOUCHED,
427     // The top JS frame had been calling IC stub. IC stub mustn't be called now.
428     FRAME_DROPPED_IN_IC_CALL,
429     // The top JS frame had been calling debug break slot stub. Patch the
430     // address this stub jumps to in the end.
431     FRAME_DROPPED_IN_DEBUG_SLOT_CALL,
432     // The top JS frame had been calling some C++ function. The return address
433     // gets patched automatically.
434     FRAME_DROPPED_IN_DIRECT_CALL,
435     FRAME_DROPPED_IN_RETURN_CALL
436   };
437 
438   void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
439                                     FrameDropMode mode,
440                                     Object** restarter_frame_function_pointer);
441 
442   // Initializes an artificial stack frame. The data it contains is used for:
443   //  a. successful work of frame dropper code which eventually gets control,
444   //  b. being compatible with regular stack structure for various stack
445   //     iterators.
446   // Returns address of stack allocated pointer to restarted function,
447   // the value that is called 'restarter_frame_function_pointer'. The value
448   // at this address (possibly updated by GC) may be used later when preparing
449   // 'step in' operation.
450   static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
451                                          Handle<Code> code);
452 
453   static const int kFrameDropperFrameSize;
454 
455   // Architecture-specific constant.
456   static const bool kFrameDropperSupported;
457 
458  private:
459   explicit Debug(Isolate* isolate);
460   ~Debug();
461 
462   static bool CompileDebuggerScript(int index);
463   void ClearOneShot();
464   void ActivateStepIn(StackFrame* frame);
465   void ClearStepIn();
466   void ActivateStepOut(StackFrame* frame);
467   void ClearStepOut();
468   void ClearStepNext();
469   // Returns whether the compile succeeded.
470   void RemoveDebugInfo(Handle<DebugInfo> debug_info);
471   void SetAfterBreakTarget(JavaScriptFrame* frame);
472   Handle<Object> CheckBreakPoints(Handle<Object> break_point);
473   bool CheckBreakPoint(Handle<Object> break_point_object);
474 
475   // Global handle to debug context where all the debugger JavaScript code is
476   // loaded.
477   Handle<Context> debug_context_;
478 
479   // Boolean state indicating whether any break points are set.
480   bool has_break_points_;
481 
482   // Cache of all scripts in the heap.
483   ScriptCache* script_cache_;
484 
485   // List of active debug info objects.
486   DebugInfoListNode* debug_info_list_;
487 
488   bool disable_break_;
489   bool break_on_exception_;
490   bool break_on_uncaught_exception_;
491 
492   // Per-thread data.
493   class ThreadLocal {
494    public:
495     // Counter for generating next break id.
496     int break_count_;
497 
498     // Current break id.
499     int break_id_;
500 
501     // Frame id for the frame of the current break.
502     StackFrame::Id break_frame_id_;
503 
504     // Step action for last step performed.
505     StepAction last_step_action_;
506 
507     // Source statement position from last step next action.
508     int last_statement_position_;
509 
510     // Number of steps left to perform before debug event.
511     int step_count_;
512 
513     // Frame pointer from last step next action.
514     Address last_fp_;
515 
516     // Number of queued steps left to perform before debug event.
517     int queued_step_count_;
518 
519     // Frame pointer for frame from which step in was performed.
520     Address step_into_fp_;
521 
522     // Frame pointer for the frame where debugger should be called when current
523     // step out action is completed.
524     Address step_out_fp_;
525 
526     // Storage location for jump when exiting debug break calls.
527     Address after_break_target_;
528 
529     // Stores the way how LiveEdit has patched the stack. It is used when
530     // debugger returns control back to user script.
531     FrameDropMode frame_drop_mode_;
532 
533     // Top debugger entry.
534     EnterDebugger* debugger_entry_;
535 
536     // Pending interrupts scheduled while debugging.
537     int pending_interrupts_;
538 
539     // When restarter frame is on stack, stores the address
540     // of the pointer to function being restarted. Otherwise (most of the time)
541     // stores NULL. This pointer is used with 'step in' implementation.
542     Object** restarter_frame_function_pointer_;
543   };
544 
545   // Storage location for registers when handling debug break calls
546   JSCallerSavedBuffer registers_;
547   ThreadLocal thread_local_;
548   void ThreadInit();
549 
550   // Code to call for handling debug break on return.
551   Code* debug_break_return_;
552 
553   // Code to call for handling debug break in debug break slots.
554   Code* debug_break_slot_;
555 
556   Isolate* isolate_;
557 
558   friend class Isolate;
559 
560   DISALLOW_COPY_AND_ASSIGN(Debug);
561 };
562 
563 
564 DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break);
565 
566 
567 // Message delivered to the message handler callback. This is either a debugger
568 // event or the response to a command.
569 class MessageImpl: public v8::Debug::Message {
570  public:
571   // Create a message object for a debug event.
572   static MessageImpl NewEvent(DebugEvent event,
573                               bool running,
574                               Handle<JSObject> exec_state,
575                               Handle<JSObject> event_data);
576 
577   // Create a message object for the response to a debug command.
578   static MessageImpl NewResponse(DebugEvent event,
579                                  bool running,
580                                  Handle<JSObject> exec_state,
581                                  Handle<JSObject> event_data,
582                                  Handle<String> response_json,
583                                  v8::Debug::ClientData* client_data);
584 
585   // Implementation of interface v8::Debug::Message.
586   virtual bool IsEvent() const;
587   virtual bool IsResponse() const;
588   virtual DebugEvent GetEvent() const;
589   virtual bool WillStartRunning() const;
590   virtual v8::Handle<v8::Object> GetExecutionState() const;
591   virtual v8::Handle<v8::Object> GetEventData() const;
592   virtual v8::Handle<v8::String> GetJSON() const;
593   virtual v8::Handle<v8::Context> GetEventContext() const;
594   virtual v8::Debug::ClientData* GetClientData() const;
595 
596  private:
597   MessageImpl(bool is_event,
598               DebugEvent event,
599               bool running,
600               Handle<JSObject> exec_state,
601               Handle<JSObject> event_data,
602               Handle<String> response_json,
603               v8::Debug::ClientData* client_data);
604 
605   bool is_event_;  // Does this message represent a debug event?
606   DebugEvent event_;  // Debug event causing the break.
607   bool running_;  // Will the VM start running after this event?
608   Handle<JSObject> exec_state_;  // Current execution state.
609   Handle<JSObject> event_data_;  // Data associated with the event.
610   Handle<String> response_json_;  // Response JSON if message holds a response.
611   v8::Debug::ClientData* client_data_;  // Client data passed with the request.
612 };
613 
614 
615 // Details of the debug event delivered to the debug event listener.
616 class EventDetailsImpl : public v8::Debug::EventDetails {
617  public:
618   EventDetailsImpl(DebugEvent event,
619                    Handle<JSObject> exec_state,
620                    Handle<JSObject> event_data,
621                    Handle<Object> callback_data,
622                    v8::Debug::ClientData* client_data);
623   virtual DebugEvent GetEvent() const;
624   virtual v8::Handle<v8::Object> GetExecutionState() const;
625   virtual v8::Handle<v8::Object> GetEventData() const;
626   virtual v8::Handle<v8::Context> GetEventContext() const;
627   virtual v8::Handle<v8::Value> GetCallbackData() const;
628   virtual v8::Debug::ClientData* GetClientData() const;
629  private:
630   DebugEvent event_;  // Debug event causing the break.
631   Handle<JSObject> exec_state_;         // Current execution state.
632   Handle<JSObject> event_data_;         // Data associated with the event.
633   Handle<Object> callback_data_;        // User data passed with the callback
634                                         // when it was registered.
635   v8::Debug::ClientData* client_data_;  // Data passed to DebugBreakForCommand.
636 };
637 
638 
639 // Message send by user to v8 debugger or debugger output message.
640 // In addition to command text it may contain a pointer to some user data
641 // which are expected to be passed along with the command reponse to message
642 // handler.
643 class CommandMessage {
644  public:
645   static CommandMessage New(const Vector<uint16_t>& command,
646                             v8::Debug::ClientData* data);
647   CommandMessage();
648   ~CommandMessage();
649 
650   // Deletes user data and disposes of the text.
651   void Dispose();
text()652   Vector<uint16_t> text() const { return text_; }
client_data()653   v8::Debug::ClientData* client_data() const { return client_data_; }
654  private:
655   CommandMessage(const Vector<uint16_t>& text,
656                  v8::Debug::ClientData* data);
657 
658   Vector<uint16_t> text_;
659   v8::Debug::ClientData* client_data_;
660 };
661 
662 // A Queue of CommandMessage objects.  A thread-safe version is
663 // LockingCommandMessageQueue, based on this class.
664 class CommandMessageQueue BASE_EMBEDDED {
665  public:
666   explicit CommandMessageQueue(int size);
667   ~CommandMessageQueue();
IsEmpty()668   bool IsEmpty() const { return start_ == end_; }
669   CommandMessage Get();
670   void Put(const CommandMessage& message);
Clear()671   void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
672  private:
673   // Doubles the size of the message queue, and copies the messages.
674   void Expand();
675 
676   CommandMessage* messages_;
677   int start_;
678   int end_;
679   int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
680 };
681 
682 
683 class MessageDispatchHelperThread;
684 
685 
686 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
687 // messages.  The message data is not managed by LockingCommandMessageQueue.
688 // Pointers to the data are passed in and out. Implemented by adding a
689 // Mutex to CommandMessageQueue.  Includes logging of all puts and gets.
690 class LockingCommandMessageQueue BASE_EMBEDDED {
691  public:
692   LockingCommandMessageQueue(Logger* logger, int size);
693   ~LockingCommandMessageQueue();
694   bool IsEmpty() const;
695   CommandMessage Get();
696   void Put(const CommandMessage& message);
697   void Clear();
698  private:
699   Logger* logger_;
700   CommandMessageQueue queue_;
701   Mutex* lock_;
702   DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
703 };
704 
705 
706 class Debugger {
707  public:
708   ~Debugger();
709 
710   void DebugRequest(const uint16_t* json_request, int length);
711 
712   Handle<Object> MakeJSObject(Vector<const char> constructor_name,
713                               int argc,
714                               Handle<Object> argv[],
715                               bool* caught_exception);
716   Handle<Object> MakeExecutionState(bool* caught_exception);
717   Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
718                                 Handle<Object> break_points_hit,
719                                 bool* caught_exception);
720   Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
721                                     Handle<Object> exception,
722                                     bool uncaught,
723                                     bool* caught_exception);
724   Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
725                                       bool* caught_exception);
726   Handle<Object> MakeCompileEvent(Handle<Script> script,
727                                   bool before,
728                                   bool* caught_exception);
729   Handle<Object> MakeScriptCollectedEvent(int id,
730                                           bool* caught_exception);
731   void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
732   void OnException(Handle<Object> exception, bool uncaught);
733   void OnBeforeCompile(Handle<Script> script);
734 
735   enum AfterCompileFlags {
736     NO_AFTER_COMPILE_FLAGS,
737     SEND_WHEN_DEBUGGING
738   };
739   void OnAfterCompile(Handle<Script> script,
740                       AfterCompileFlags after_compile_flags);
741   void OnNewFunction(Handle<JSFunction> fun);
742   void OnScriptCollected(int id);
743   void ProcessDebugEvent(v8::DebugEvent event,
744                          Handle<JSObject> event_data,
745                          bool auto_continue);
746   void NotifyMessageHandler(v8::DebugEvent event,
747                             Handle<JSObject> exec_state,
748                             Handle<JSObject> event_data,
749                             bool auto_continue);
750   void SetEventListener(Handle<Object> callback, Handle<Object> data);
751   void SetMessageHandler(v8::Debug::MessageHandler2 handler);
752   void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
753                               int period);
754   void SetDebugMessageDispatchHandler(
755       v8::Debug::DebugMessageDispatchHandler handler,
756       bool provide_locker);
757 
758   // Invoke the message handler function.
759   void InvokeMessageHandler(MessageImpl message);
760 
761   // Add a debugger command to the command queue.
762   void ProcessCommand(Vector<const uint16_t> command,
763                       v8::Debug::ClientData* client_data = NULL);
764 
765   // Check whether there are commands in the command queue.
766   bool HasCommands();
767 
768   // Enqueue a debugger command to the command queue for event listeners.
769   void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
770 
771   Handle<Object> Call(Handle<JSFunction> fun,
772                       Handle<Object> data,
773                       bool* pending_exception);
774 
775   // Start the debugger agent listening on the provided port.
776   bool StartAgent(const char* name, int port,
777                   bool wait_for_connection = false);
778 
779   // Stop the debugger agent.
780   void StopAgent();
781 
782   // Blocks until the agent has started listening for connections
783   void WaitForAgent();
784 
785   void CallMessageDispatchHandler();
786 
787   Handle<Context> GetDebugContext();
788 
789   // Unload the debugger if possible. Only called when no debugger is currently
790   // active.
791   void UnloadDebugger();
792   friend void ForceUnloadDebugger();  // In test-debug.cc
793 
EventActive(v8::DebugEvent event)794   inline bool EventActive(v8::DebugEvent event) {
795     ScopedLock with(debugger_access_);
796 
797     // Check whether the message handler was been cleared.
798     if (debugger_unload_pending_) {
799       if (isolate_->debug()->debugger_entry() == NULL) {
800         UnloadDebugger();
801       }
802     }
803 
804     if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) &&
805         !FLAG_debug_compile_events) {
806       return false;
807 
808     } else if ((event == v8::ScriptCollected) &&
809                !FLAG_debug_script_collected_events) {
810       return false;
811     }
812 
813     // Currently argument event is not used.
814     return !compiling_natives_ && Debugger::IsDebuggerActive();
815   }
816 
set_compiling_natives(bool compiling_natives)817   void set_compiling_natives(bool compiling_natives) {
818     compiling_natives_ = compiling_natives;
819   }
compiling_natives()820   bool compiling_natives() const { return compiling_natives_; }
set_loading_debugger(bool v)821   void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
is_loading_debugger()822   bool is_loading_debugger() const { return is_loading_debugger_; }
set_force_debugger_active(bool force_debugger_active)823   void set_force_debugger_active(bool force_debugger_active) {
824     force_debugger_active_ = force_debugger_active;
825   }
force_debugger_active()826   bool force_debugger_active() const { return force_debugger_active_; }
827 
828   bool IsDebuggerActive();
829 
830  private:
831   explicit Debugger(Isolate* isolate);
832 
833   void CallEventCallback(v8::DebugEvent event,
834                          Handle<Object> exec_state,
835                          Handle<Object> event_data,
836                          v8::Debug::ClientData* client_data);
837   void CallCEventCallback(v8::DebugEvent event,
838                           Handle<Object> exec_state,
839                           Handle<Object> event_data,
840                           v8::Debug::ClientData* client_data);
841   void CallJSEventCallback(v8::DebugEvent event,
842                            Handle<Object> exec_state,
843                            Handle<Object> event_data);
844   void ListenersChanged();
845 
846   Mutex* debugger_access_;  // Mutex guarding debugger variables.
847   Handle<Object> event_listener_;  // Global handle to listener.
848   Handle<Object> event_listener_data_;
849   bool compiling_natives_;  // Are we compiling natives?
850   bool is_loading_debugger_;  // Are we loading the debugger?
851   bool never_unload_debugger_;  // Can we unload the debugger?
852   bool force_debugger_active_;  // Activate debugger without event listeners.
853   v8::Debug::MessageHandler2 message_handler_;
854   bool debugger_unload_pending_;  // Was message handler cleared?
855   v8::Debug::HostDispatchHandler host_dispatch_handler_;
856   Mutex* dispatch_handler_access_;  // Mutex guarding dispatch handler.
857   v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
858   MessageDispatchHelperThread* message_dispatch_helper_thread_;
859   int host_dispatch_micros_;
860 
861   DebuggerAgent* agent_;
862 
863   static const int kQueueInitialSize = 4;
864   LockingCommandMessageQueue command_queue_;
865   Semaphore* command_received_;  // Signaled for each command received.
866   LockingCommandMessageQueue event_command_queue_;
867 
868   Isolate* isolate_;
869 
870   friend class EnterDebugger;
871   friend class Isolate;
872 
873   DISALLOW_COPY_AND_ASSIGN(Debugger);
874 };
875 
876 
877 // This class is used for entering the debugger. Create an instance in the stack
878 // to enter the debugger. This will set the current break state, make sure the
879 // debugger is loaded and switch to the debugger context. If the debugger for
880 // some reason could not be entered FailedToEnter will return true.
881 class EnterDebugger BASE_EMBEDDED {
882  public:
883   EnterDebugger();
884   ~EnterDebugger();
885 
886   // Check whether the debugger could be entered.
FailedToEnter()887   inline bool FailedToEnter() { return load_failed_; }
888 
889   // Check whether there are any JavaScript frames on the stack.
HasJavaScriptFrames()890   inline bool HasJavaScriptFrames() { return has_js_frames_; }
891 
892   // Get the active context from before entering the debugger.
GetContext()893   inline Handle<Context> GetContext() { return save_.context(); }
894 
895  private:
896   Isolate* isolate_;
897   EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
898   JavaScriptFrameIterator it_;
899   const bool has_js_frames_;  // Were there any JavaScript frames?
900   StackFrame::Id break_frame_id_;  // Previous break frame id.
901   int break_id_;  // Previous break id.
902   bool load_failed_;  // Did the debugger fail to load?
903   SaveContext save_;  // Saves previous context.
904 };
905 
906 
907 // Stack allocated class for disabling break.
908 class DisableBreak BASE_EMBEDDED {
909  public:
DisableBreak(bool disable_break)910   explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) {
911     prev_disable_break_ = isolate_->debug()->disable_break();
912     isolate_->debug()->set_disable_break(disable_break);
913   }
~DisableBreak()914   ~DisableBreak() {
915     ASSERT(Isolate::Current() == isolate_);
916     isolate_->debug()->set_disable_break(prev_disable_break_);
917   }
918 
919  private:
920   Isolate* isolate_;
921   // The previous state of the disable break used to restore the value when this
922   // object is destructed.
923   bool prev_disable_break_;
924 };
925 
926 
927 // Debug_Address encapsulates the Address pointers used in generating debug
928 // code.
929 class Debug_Address {
930  public:
Debug_Address(Debug::AddressId id)931   explicit Debug_Address(Debug::AddressId id) : id_(id) { }
932 
AfterBreakTarget()933   static Debug_Address AfterBreakTarget() {
934     return Debug_Address(Debug::k_after_break_target_address);
935   }
936 
DebugBreakReturn()937   static Debug_Address DebugBreakReturn() {
938     return Debug_Address(Debug::k_debug_break_return_address);
939   }
940 
RestarterFrameFunctionPointer()941   static Debug_Address RestarterFrameFunctionPointer() {
942     return Debug_Address(Debug::k_restarter_frame_function_pointer);
943   }
944 
address(Isolate * isolate)945   Address address(Isolate* isolate) const {
946     Debug* debug = isolate->debug();
947     switch (id_) {
948       case Debug::k_after_break_target_address:
949         return reinterpret_cast<Address>(debug->after_break_target_address());
950       case Debug::k_debug_break_return_address:
951         return reinterpret_cast<Address>(debug->debug_break_return_address());
952       case Debug::k_debug_break_slot_address:
953         return reinterpret_cast<Address>(debug->debug_break_slot_address());
954       case Debug::k_restarter_frame_function_pointer:
955         return reinterpret_cast<Address>(
956             debug->restarter_frame_function_pointer_address());
957       default:
958         UNREACHABLE();
959         return NULL;
960     }
961   }
962 
963  private:
964   Debug::AddressId id_;
965 };
966 
967 // The optional thread that Debug Agent may use to temporary call V8 to process
968 // pending debug requests if debuggee is not running V8 at the moment.
969 // Techincally it does not call V8 itself, rather it asks embedding program
970 // to do this via v8::Debug::HostDispatchHandler
971 class MessageDispatchHelperThread: public Thread {
972  public:
973   explicit MessageDispatchHelperThread(Isolate* isolate);
974   ~MessageDispatchHelperThread();
975 
976   void Schedule();
977 
978  private:
979   void Run();
980 
981   Semaphore* const sem_;
982   Mutex* const mutex_;
983   bool already_signalled_;
984 
985   DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
986 };
987 
988 
989 } }  // namespace v8::internal
990 
991 #endif  // ENABLE_DEBUGGER_SUPPORT
992 
993 #endif  // V8_DEBUG_H_
994