• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 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 "assembler.h"
32 #include "code-stubs.h"
33 #include "debug-agent.h"
34 #include "execution.h"
35 #include "factory.h"
36 #include "hashmap.h"
37 #include "platform.h"
38 #include "string-stream.h"
39 #include "v8threads.h"
40 
41 #ifdef ENABLE_DEBUGGER_SUPPORT
42 #include "../include/v8-debug.h"
43 
44 namespace v8 {
45 namespace internal {
46 
47 
48 // Forward declarations.
49 class EnterDebugger;
50 
51 
52 // Step actions. NOTE: These values are in macros.py as well.
53 enum StepAction {
54   StepNone = -1,  // Stepping not prepared.
55   StepOut = 0,   // Step out of the current function.
56   StepNext = 1,  // Step to the next statement in the current function.
57   StepIn = 2,    // Step into new functions invoked or the next statement
58                  // in the current function.
59   StepMin = 3,   // Perform a minimum step in the current function.
60   StepInMin = 4  // Step into new functions invoked or perform a minimum step
61                  // in the current function.
62 };
63 
64 
65 // Type of exception break. NOTE: These values are in macros.py as well.
66 enum ExceptionBreakType {
67   BreakException = 0,
68   BreakUncaughtException = 1
69 };
70 
71 
72 // Type of exception break. NOTE: These values are in macros.py as well.
73 enum BreakLocatorType {
74   ALL_BREAK_LOCATIONS = 0,
75   SOURCE_BREAK_LOCATIONS = 1
76 };
77 
78 
79 // Class for iterating through the break points in a function and changing
80 // them.
81 class BreakLocationIterator {
82  public:
83   explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
84                                  BreakLocatorType type);
85   virtual ~BreakLocationIterator();
86 
87   void Next();
88   void Next(int count);
89   void FindBreakLocationFromAddress(Address pc);
90   void FindBreakLocationFromPosition(int position);
91   void Reset();
92   bool Done() const;
93   void SetBreakPoint(Handle<Object> break_point_object);
94   void ClearBreakPoint(Handle<Object> break_point_object);
95   void SetOneShot();
96   void ClearOneShot();
97   void PrepareStepIn();
98   bool IsExit() const;
99   bool HasBreakPoint();
100   bool IsDebugBreak();
101   Object* BreakPointObjects();
102   void ClearAllDebugBreak();
103 
104 
code_position()105   inline int code_position() {
106     return static_cast<int>(pc() - debug_info_->code()->entry());
107   }
break_point()108   inline int break_point() { return break_point_; }
position()109   inline int position() { return position_; }
statement_position()110   inline int statement_position() { return statement_position_; }
pc()111   inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
code()112   inline Code* code() { return debug_info_->code(); }
rinfo()113   inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
rmode()114   inline RelocInfo::Mode rmode() const {
115     return reloc_iterator_->rinfo()->rmode();
116   }
original_rinfo()117   inline RelocInfo* original_rinfo() {
118     return reloc_iterator_original_->rinfo();
119   }
original_rmode()120   inline RelocInfo::Mode original_rmode() const {
121     return reloc_iterator_original_->rinfo()->rmode();
122   }
123 
124   bool IsDebuggerStatement();
125 
126  protected:
127   bool RinfoDone() const;
128   void RinfoNext();
129 
130   BreakLocatorType type_;
131   int break_point_;
132   int position_;
133   int statement_position_;
134   Handle<DebugInfo> debug_info_;
135   RelocIterator* reloc_iterator_;
136   RelocIterator* reloc_iterator_original_;
137 
138  private:
139   void SetDebugBreak();
140   void ClearDebugBreak();
141 
142   void SetDebugBreakAtIC();
143   void ClearDebugBreakAtIC();
144 
145   bool IsDebugBreakAtReturn();
146   void SetDebugBreakAtReturn();
147   void ClearDebugBreakAtReturn();
148 
149   DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
150 };
151 
152 
153 // Cache of all script objects in the heap. When a script is added a weak handle
154 // to it is created and that weak handle is stored in the cache. The weak handle
155 // callback takes care of removing the script from the cache. The key used in
156 // the cache is the script id.
157 class ScriptCache : private HashMap {
158  public:
ScriptCache()159   ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {}
~ScriptCache()160   virtual ~ScriptCache() { Clear(); }
161 
162   // Add script to the cache.
163   void Add(Handle<Script> script);
164 
165   // Return the scripts in the cache.
166   Handle<FixedArray> GetScripts();
167 
168   // Generate debugger events for collected scripts.
169   void ProcessCollectedScripts();
170 
171  private:
172   // Calculate the hash value from the key (script id).
Hash(int key)173   static uint32_t Hash(int key) { return ComputeIntegerHash(key); }
174 
175   // Scripts match if their keys (script id) match.
ScriptMatch(void * key1,void * key2)176   static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
177 
178   // Clear the cache releasing all the weak handles.
179   void Clear();
180 
181   // Weak handle callback for scripts in the cache.
182   static void HandleWeakScript(v8::Persistent<v8::Value> obj, void* data);
183 
184   // List used during GC to temporarily store id's of collected scripts.
185   List<int> collected_scripts_;
186 };
187 
188 
189 // Linked list holding debug info objects. The debug info objects are kept as
190 // weak handles to avoid a debug info object to keep a function alive.
191 class DebugInfoListNode {
192  public:
193   explicit DebugInfoListNode(DebugInfo* debug_info);
194   virtual ~DebugInfoListNode();
195 
next()196   DebugInfoListNode* next() { return next_; }
set_next(DebugInfoListNode * next)197   void set_next(DebugInfoListNode* next) { next_ = next; }
debug_info()198   Handle<DebugInfo> debug_info() { return debug_info_; }
199 
200  private:
201   // Global (weak) handle to the debug info object.
202   Handle<DebugInfo> debug_info_;
203 
204   // Next pointer for linked list.
205   DebugInfoListNode* next_;
206 };
207 
208 
209 // This class contains the debugger support. The main purpose is to handle
210 // setting break points in the code.
211 //
212 // This class controls the debug info for all functions which currently have
213 // active breakpoints in them. This debug info is held in the heap root object
214 // debug_info which is a FixedArray. Each entry in this list is of class
215 // DebugInfo.
216 class Debug {
217  public:
218   static void Setup(bool create_heap_objects);
219   static bool Load();
220   static void Unload();
IsLoaded()221   static bool IsLoaded() { return !debug_context_.is_null(); }
InDebugger()222   static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
223   static void PreemptionWhileInDebugger();
224   static void Iterate(ObjectVisitor* v);
225 
226   static Object* Break(Arguments args);
227   static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
228                             int source_position,
229                             Handle<Object> break_point_object);
230   static void ClearBreakPoint(Handle<Object> break_point_object);
231   static void ClearAllBreakPoints();
232   static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
233   static void FloodHandlerWithOneShot();
234   static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
235   static void PrepareStep(StepAction step_action, int step_count);
236   static void ClearStepping();
237   static bool StepNextContinue(BreakLocationIterator* break_location_iterator,
238                                JavaScriptFrame* frame);
239   static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
240   static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
241 
242   // Returns whether the operation succeeded.
243   static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
244 
245   // Returns true if the current stub call is patched to call the debugger.
246   static bool IsDebugBreak(Address addr);
247   // Returns true if the current return statement has been patched to be
248   // a debugger breakpoint.
249   static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
250 
251   // Check whether a code stub with the specified major key is a possible break
252   // point location.
253   static bool IsSourceBreakStub(Code* code);
254   static bool IsBreakStub(Code* code);
255 
256   // Find the builtin to use for invoking the debug break
257   static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
258 
259   static Handle<Object> GetSourceBreakLocations(
260       Handle<SharedFunctionInfo> shared);
261 
262   // Getter for the debug_context.
debug_context()263   inline static Handle<Context> debug_context() { return debug_context_; }
264 
265   // Check whether a global object is the debug global object.
266   static bool IsDebugGlobal(GlobalObject* global);
267 
268   // Fast check to see if any break points are active.
has_break_points()269   inline static bool has_break_points() { return has_break_points_; }
270 
271   static void NewBreak(StackFrame::Id break_frame_id);
272   static void SetBreak(StackFrame::Id break_frame_id, int break_id);
break_frame_id()273   static StackFrame::Id break_frame_id() {
274     return thread_local_.break_frame_id_;
275   }
break_id()276   static int break_id() { return thread_local_.break_id_; }
277 
StepInActive()278   static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
279   static void HandleStepIn(Handle<JSFunction> function,
280                            Handle<Object> holder,
281                            Address fp,
282                            bool is_constructor);
step_in_fp()283   static Address step_in_fp() { return thread_local_.step_into_fp_; }
step_in_fp_addr()284   static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
285 
StepOutActive()286   static bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
step_out_fp()287   static Address step_out_fp() { return thread_local_.step_out_fp_; }
288 
debugger_entry()289   static EnterDebugger* debugger_entry() {
290     return thread_local_.debugger_entry_;
291   }
set_debugger_entry(EnterDebugger * entry)292   static void set_debugger_entry(EnterDebugger* entry) {
293     thread_local_.debugger_entry_ = entry;
294   }
295 
296   // Check whether any of the specified interrupts are pending.
is_interrupt_pending(InterruptFlag what)297   static bool is_interrupt_pending(InterruptFlag what) {
298     return (thread_local_.pending_interrupts_ & what) != 0;
299   }
300 
301   // Set specified interrupts as pending.
set_interrupts_pending(InterruptFlag what)302   static void set_interrupts_pending(InterruptFlag what) {
303     thread_local_.pending_interrupts_ |= what;
304   }
305 
306   // Clear specified interrupts from pending.
clear_interrupt_pending(InterruptFlag what)307   static void clear_interrupt_pending(InterruptFlag what) {
308     thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
309   }
310 
311   // Getter and setter for the disable break state.
disable_break()312   static bool disable_break() { return disable_break_; }
set_disable_break(bool disable_break)313   static void set_disable_break(bool disable_break) {
314     disable_break_ = disable_break;
315   }
316 
317   // Getters for the current exception break state.
break_on_exception()318   static bool break_on_exception() { return break_on_exception_; }
break_on_uncaught_exception()319   static bool break_on_uncaught_exception() {
320     return break_on_uncaught_exception_;
321   }
322 
323   enum AddressId {
324     k_after_break_target_address,
325     k_debug_break_return_address,
326     k_register_address
327   };
328 
329   // Support for setting the address to jump to when returning from break point.
after_break_target_address()330   static Address* after_break_target_address() {
331     return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
332   }
333 
334   // Support for saving/restoring registers when handling debug break calls.
register_address(int r)335   static Object** register_address(int r) {
336     return &registers_[r];
337   }
338 
339   // Access to the debug break on return code.
debug_break_return()340   static Code* debug_break_return() { return debug_break_return_; }
debug_break_return_address()341   static Code** debug_break_return_address() {
342     return &debug_break_return_;
343   }
344 
345   static const int kEstimatedNofDebugInfoEntries = 16;
346   static const int kEstimatedNofBreakPointsInFunction = 16;
347 
348   static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
349 
350   friend class Debugger;
351   friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
352   friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
353 
354   // Threading support.
355   static char* ArchiveDebug(char* to);
356   static char* RestoreDebug(char* from);
357   static int ArchiveSpacePerThread();
FreeThreadResources()358   static void FreeThreadResources() { }
359 
360   // Mirror cache handling.
361   static void ClearMirrorCache();
362 
363   // Script cache handling.
364   static void CreateScriptCache();
365   static void DestroyScriptCache();
366   static void AddScriptToScriptCache(Handle<Script> script);
367   static Handle<FixedArray> GetLoadedScripts();
368 
369   // Garbage collection notifications.
370   static void AfterGarbageCollection();
371 
372   // Code generator routines.
373   static void GenerateLoadICDebugBreak(MacroAssembler* masm);
374   static void GenerateStoreICDebugBreak(MacroAssembler* masm);
375   static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
376   static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
377   static void GenerateConstructCallDebugBreak(MacroAssembler* masm);
378   static void GenerateReturnDebugBreak(MacroAssembler* masm);
379   static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
380 
381   // Called from stub-cache.cc.
382   static void GenerateCallICDebugBreak(MacroAssembler* masm);
383 
384  private:
385   static bool CompileDebuggerScript(int index);
386   static void ClearOneShot();
387   static void ActivateStepIn(StackFrame* frame);
388   static void ClearStepIn();
389   static void ActivateStepOut(StackFrame* frame);
390   static void ClearStepOut();
391   static void ClearStepNext();
392   // Returns whether the compile succeeded.
393   static void RemoveDebugInfo(Handle<DebugInfo> debug_info);
394   static void SetAfterBreakTarget(JavaScriptFrame* frame);
395   static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
396   static bool CheckBreakPoint(Handle<Object> break_point_object);
397 
398   // Global handle to debug context where all the debugger JavaScript code is
399   // loaded.
400   static Handle<Context> debug_context_;
401 
402   // Boolean state indicating whether any break points are set.
403   static bool has_break_points_;
404 
405   // Cache of all scripts in the heap.
406   static ScriptCache* script_cache_;
407 
408   // List of active debug info objects.
409   static DebugInfoListNode* debug_info_list_;
410 
411   static bool disable_break_;
412   static bool break_on_exception_;
413   static bool break_on_uncaught_exception_;
414 
415   // Per-thread data.
416   class ThreadLocal {
417    public:
418     // Counter for generating next break id.
419     int break_count_;
420 
421     // Current break id.
422     int break_id_;
423 
424     // Frame id for the frame of the current break.
425     StackFrame::Id break_frame_id_;
426 
427     // Step action for last step performed.
428     StepAction last_step_action_;
429 
430     // Source statement position from last step next action.
431     int last_statement_position_;
432 
433     // Number of steps left to perform before debug event.
434     int step_count_;
435 
436     // Frame pointer from last step next action.
437     Address last_fp_;
438 
439     // Frame pointer for frame from which step in was performed.
440     Address step_into_fp_;
441 
442     // Frame pointer for the frame where debugger should be called when current
443     // step out action is completed.
444     Address step_out_fp_;
445 
446     // Storage location for jump when exiting debug break calls.
447     Address after_break_target_;
448 
449     // Top debugger entry.
450     EnterDebugger* debugger_entry_;
451 
452     // Pending interrupts scheduled while debugging.
453     int pending_interrupts_;
454   };
455 
456   // Storage location for registers when handling debug break calls
457   static JSCallerSavedBuffer registers_;
458   static ThreadLocal thread_local_;
459   static void ThreadInit();
460 
461   // Code to call for handling debug break on return.
462   static Code* debug_break_return_;
463 
464   DISALLOW_COPY_AND_ASSIGN(Debug);
465 };
466 
467 
468 // Message delivered to the message handler callback. This is either a debugger
469 // event or the response to a command.
470 class MessageImpl: public v8::Debug::Message {
471  public:
472   // Create a message object for a debug event.
473   static MessageImpl NewEvent(DebugEvent event,
474                               bool running,
475                               Handle<JSObject> exec_state,
476                               Handle<JSObject> event_data);
477 
478   // Create a message object for the response to a debug command.
479   static MessageImpl NewResponse(DebugEvent event,
480                                  bool running,
481                                  Handle<JSObject> exec_state,
482                                  Handle<JSObject> event_data,
483                                  Handle<String> response_json,
484                                  v8::Debug::ClientData* client_data);
485 
486   // Implementation of interface v8::Debug::Message.
487   virtual bool IsEvent() const;
488   virtual bool IsResponse() const;
489   virtual DebugEvent GetEvent() const;
490   virtual bool WillStartRunning() const;
491   virtual v8::Handle<v8::Object> GetExecutionState() const;
492   virtual v8::Handle<v8::Object> GetEventData() const;
493   virtual v8::Handle<v8::String> GetJSON() const;
494   virtual v8::Handle<v8::Context> GetEventContext() const;
495   virtual v8::Debug::ClientData* GetClientData() const;
496 
497  private:
498   MessageImpl(bool is_event,
499               DebugEvent event,
500               bool running,
501               Handle<JSObject> exec_state,
502               Handle<JSObject> event_data,
503               Handle<String> response_json,
504               v8::Debug::ClientData* client_data);
505 
506   bool is_event_;  // Does this message represent a debug event?
507   DebugEvent event_;  // Debug event causing the break.
508   bool running_;  // Will the VM start running after this event?
509   Handle<JSObject> exec_state_;  // Current execution state.
510   Handle<JSObject> event_data_;  // Data associated with the event.
511   Handle<String> response_json_;  // Response JSON if message holds a response.
512   v8::Debug::ClientData* client_data_;  // Client data passed with the request.
513 };
514 
515 
516 // Message send by user to v8 debugger or debugger output message.
517 // In addition to command text it may contain a pointer to some user data
518 // which are expected to be passed along with the command reponse to message
519 // handler.
520 class CommandMessage {
521  public:
522   static CommandMessage New(const Vector<uint16_t>& command,
523                             v8::Debug::ClientData* data);
524   CommandMessage();
525   ~CommandMessage();
526 
527   // Deletes user data and disposes of the text.
528   void Dispose();
text()529   Vector<uint16_t> text() const { return text_; }
client_data()530   v8::Debug::ClientData* client_data() const { return client_data_; }
531  private:
532   CommandMessage(const Vector<uint16_t>& text,
533                  v8::Debug::ClientData* data);
534 
535   Vector<uint16_t> text_;
536   v8::Debug::ClientData* client_data_;
537 };
538 
539 // A Queue of CommandMessage objects.  A thread-safe version is
540 // LockingCommandMessageQueue, based on this class.
541 class CommandMessageQueue BASE_EMBEDDED {
542  public:
543   explicit CommandMessageQueue(int size);
544   ~CommandMessageQueue();
IsEmpty()545   bool IsEmpty() const { return start_ == end_; }
546   CommandMessage Get();
547   void Put(const CommandMessage& message);
Clear()548   void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
549  private:
550   // Doubles the size of the message queue, and copies the messages.
551   void Expand();
552 
553   CommandMessage* messages_;
554   int start_;
555   int end_;
556   int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
557 };
558 
559 
560 class MessageDispatchHelperThread;
561 
562 
563 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
564 // messages.  The message data is not managed by LockingCommandMessageQueue.
565 // Pointers to the data are passed in and out. Implemented by adding a
566 // Mutex to CommandMessageQueue.  Includes logging of all puts and gets.
567 class LockingCommandMessageQueue BASE_EMBEDDED {
568  public:
569   explicit LockingCommandMessageQueue(int size);
570   ~LockingCommandMessageQueue();
571   bool IsEmpty() const;
572   CommandMessage Get();
573   void Put(const CommandMessage& message);
574   void Clear();
575  private:
576   CommandMessageQueue queue_;
577   Mutex* lock_;
578   DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
579 };
580 
581 
582 class Debugger {
583  public:
584   static void DebugRequest(const uint16_t* json_request, int length);
585 
586   static Handle<Object> MakeJSObject(Vector<const char> constructor_name,
587                                      int argc, Object*** argv,
588                                      bool* caught_exception);
589   static Handle<Object> MakeExecutionState(bool* caught_exception);
590   static Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
591                                        Handle<Object> break_points_hit,
592                                        bool* caught_exception);
593   static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
594                                            Handle<Object> exception,
595                                            bool uncaught,
596                                            bool* caught_exception);
597   static Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
598                                              bool* caught_exception);
599   static Handle<Object> MakeCompileEvent(Handle<Script> script,
600                                          bool before,
601                                          bool* caught_exception);
602   static Handle<Object> MakeScriptCollectedEvent(int id,
603                                                  bool* caught_exception);
604   static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
605   static void OnException(Handle<Object> exception, bool uncaught);
606   static void OnBeforeCompile(Handle<Script> script);
607   static void OnAfterCompile(Handle<Script> script,
608                            Handle<JSFunction> fun);
609   static void OnNewFunction(Handle<JSFunction> fun);
610   static void OnScriptCollected(int id);
611   static void ProcessDebugEvent(v8::DebugEvent event,
612                                 Handle<JSObject> event_data,
613                                 bool auto_continue);
614   static void NotifyMessageHandler(v8::DebugEvent event,
615                                    Handle<JSObject> exec_state,
616                                    Handle<JSObject> event_data,
617                                    bool auto_continue);
618   static void SetEventListener(Handle<Object> callback, Handle<Object> data);
619   static void SetMessageHandler(v8::Debug::MessageHandler2 handler);
620   static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
621                                      int period);
622   static void SetDebugMessageDispatchHandler(
623       v8::Debug::DebugMessageDispatchHandler handler,
624       bool provide_locker);
625 
626   // Invoke the message handler function.
627   static void InvokeMessageHandler(MessageImpl message);
628 
629   // Add a debugger command to the command queue.
630   static void ProcessCommand(Vector<const uint16_t> command,
631                              v8::Debug::ClientData* client_data = NULL);
632 
633   // Check whether there are commands in the command queue.
634   static bool HasCommands();
635 
636   static Handle<Object> Call(Handle<JSFunction> fun,
637                              Handle<Object> data,
638                              bool* pending_exception);
639 
640   // Start the debugger agent listening on the provided port.
641   static bool StartAgent(const char* name, int port,
642                          bool wait_for_connection = false);
643 
644   // Stop the debugger agent.
645   static void StopAgent();
646 
647   // Blocks until the agent has started listening for connections
648   static void WaitForAgent();
649 
650   static void CallMessageDispatchHandler();
651 
652   // Unload the debugger if possible. Only called when no debugger is currently
653   // active.
654   static void UnloadDebugger();
655 
EventActive(v8::DebugEvent event)656   inline static bool EventActive(v8::DebugEvent event) {
657     ScopedLock with(debugger_access_);
658 
659     // Check whether the message handler was been cleared.
660     if (debugger_unload_pending_) {
661       if (Debug::debugger_entry() == NULL) {
662         UnloadDebugger();
663       }
664     }
665 
666     // Currently argument event is not used.
667     return !compiling_natives_ && Debugger::IsDebuggerActive();
668   }
669 
set_compiling_natives(bool compiling_natives)670   static void set_compiling_natives(bool compiling_natives) {
671     Debugger::compiling_natives_ = compiling_natives;
672   }
compiling_natives()673   static bool compiling_natives() { return Debugger::compiling_natives_; }
set_loading_debugger(bool v)674   static void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
is_loading_debugger()675   static bool is_loading_debugger() { return Debugger::is_loading_debugger_; }
676 
677  private:
678   static bool IsDebuggerActive();
679   static void ListenersChanged();
680 
681   static Mutex* debugger_access_;  // Mutex guarding debugger variables.
682   static Handle<Object> event_listener_;  // Global handle to listener.
683   static Handle<Object> event_listener_data_;
684   static bool compiling_natives_;  // Are we compiling natives?
685   static bool is_loading_debugger_;  // Are we loading the debugger?
686   static bool never_unload_debugger_;  // Can we unload the debugger?
687   static v8::Debug::MessageHandler2 message_handler_;
688   static bool debugger_unload_pending_;  // Was message handler cleared?
689   static v8::Debug::HostDispatchHandler host_dispatch_handler_;
690   static Mutex* dispatch_handler_access_;  // Mutex guarding dispatch handler.
691   static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
692   static MessageDispatchHelperThread* message_dispatch_helper_thread_;
693   static int host_dispatch_micros_;
694 
695   static DebuggerAgent* agent_;
696 
697   static const int kQueueInitialSize = 4;
698   static LockingCommandMessageQueue command_queue_;
699   static Semaphore* command_received_;  // Signaled for each command received.
700 
701   friend class EnterDebugger;
702 };
703 
704 
705 // This class is used for entering the debugger. Create an instance in the stack
706 // to enter the debugger. This will set the current break state, make sure the
707 // debugger is loaded and switch to the debugger context. If the debugger for
708 // some reason could not be entered FailedToEnter will return true.
709 class EnterDebugger BASE_EMBEDDED {
710  public:
EnterDebugger()711   EnterDebugger()
712       : prev_(Debug::debugger_entry()),
713         has_js_frames_(!it_.done()) {
714     ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT));
715     ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK));
716 
717     // Link recursive debugger entry.
718     Debug::set_debugger_entry(this);
719 
720     // Store the previous break id and frame id.
721     break_id_ = Debug::break_id();
722     break_frame_id_ = Debug::break_frame_id();
723 
724     // Create the new break info. If there is no JavaScript frames there is no
725     // break frame id.
726     if (has_js_frames_) {
727       Debug::NewBreak(it_.frame()->id());
728     } else {
729       Debug::NewBreak(StackFrame::NO_ID);
730     }
731 
732     // Make sure that debugger is loaded and enter the debugger context.
733     load_failed_ = !Debug::Load();
734     if (!load_failed_) {
735       // NOTE the member variable save which saves the previous context before
736       // this change.
737       Top::set_context(*Debug::debug_context());
738     }
739   }
740 
~EnterDebugger()741   ~EnterDebugger() {
742     // Restore to the previous break state.
743     Debug::SetBreak(break_frame_id_, break_id_);
744 
745     // Check for leaving the debugger.
746     if (prev_ == NULL) {
747       // Clear mirror cache when leaving the debugger. Skip this if there is a
748       // pending exception as clearing the mirror cache calls back into
749       // JavaScript. This can happen if the v8::Debug::Call is used in which
750       // case the exception should end up in the calling code.
751       if (!Top::has_pending_exception()) {
752         // Try to avoid any pending debug break breaking in the clear mirror
753         // cache JavaScript code.
754         if (StackGuard::IsDebugBreak()) {
755           Debug::set_interrupts_pending(DEBUGBREAK);
756           StackGuard::Continue(DEBUGBREAK);
757         }
758         Debug::ClearMirrorCache();
759       }
760 
761       // Request preemption and debug break when leaving the last debugger entry
762       // if any of these where recorded while debugging.
763       if (Debug::is_interrupt_pending(PREEMPT)) {
764         // This re-scheduling of preemption is to avoid starvation in some
765         // debugging scenarios.
766         Debug::clear_interrupt_pending(PREEMPT);
767         StackGuard::Preempt();
768       }
769       if (Debug::is_interrupt_pending(DEBUGBREAK)) {
770         Debug::clear_interrupt_pending(DEBUGBREAK);
771         StackGuard::DebugBreak();
772       }
773 
774       // If there are commands in the queue when leaving the debugger request
775       // that these commands are processed.
776       if (Debugger::HasCommands()) {
777         StackGuard::DebugCommand();
778       }
779 
780       // If leaving the debugger with the debugger no longer active unload it.
781       if (!Debugger::IsDebuggerActive()) {
782         Debugger::UnloadDebugger();
783       }
784     }
785 
786     // Leaving this debugger entry.
787     Debug::set_debugger_entry(prev_);
788   }
789 
790   // Check whether the debugger could be entered.
FailedToEnter()791   inline bool FailedToEnter() { return load_failed_; }
792 
793   // Check whether there are any JavaScript frames on the stack.
HasJavaScriptFrames()794   inline bool HasJavaScriptFrames() { return has_js_frames_; }
795 
796   // Get the active context from before entering the debugger.
GetContext()797   inline Handle<Context> GetContext() { return save_.context(); }
798 
799  private:
800   EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
801   JavaScriptFrameIterator it_;
802   const bool has_js_frames_;  // Were there any JavaScript frames?
803   StackFrame::Id break_frame_id_;  // Previous break frame id.
804   int break_id_;  // Previous break id.
805   bool load_failed_;  // Did the debugger fail to load?
806   SaveContext save_;  // Saves previous context.
807 };
808 
809 
810 // Stack allocated class for disabling break.
811 class DisableBreak BASE_EMBEDDED {
812  public:
813   // Enter the debugger by storing the previous top context and setting the
814   // current top context to the debugger context.
DisableBreak(bool disable_break)815   explicit DisableBreak(bool disable_break)  {
816     prev_disable_break_ = Debug::disable_break();
817     Debug::set_disable_break(disable_break);
818   }
~DisableBreak()819   ~DisableBreak() {
820     Debug::set_disable_break(prev_disable_break_);
821   }
822 
823  private:
824   // The previous state of the disable break used to restore the value when this
825   // object is destructed.
826   bool prev_disable_break_;
827 };
828 
829 
830 // Debug_Address encapsulates the Address pointers used in generating debug
831 // code.
832 class Debug_Address {
833  public:
834   Debug_Address(Debug::AddressId id, int reg = 0)
id_(id)835     : id_(id), reg_(reg) {
836     ASSERT(reg == 0 || id == Debug::k_register_address);
837   }
838 
AfterBreakTarget()839   static Debug_Address AfterBreakTarget() {
840     return Debug_Address(Debug::k_after_break_target_address);
841   }
842 
DebugBreakReturn()843   static Debug_Address DebugBreakReturn() {
844     return Debug_Address(Debug::k_debug_break_return_address);
845   }
846 
Register(int reg)847   static Debug_Address Register(int reg) {
848     return Debug_Address(Debug::k_register_address, reg);
849   }
850 
address()851   Address address() const {
852     switch (id_) {
853       case Debug::k_after_break_target_address:
854         return reinterpret_cast<Address>(Debug::after_break_target_address());
855       case Debug::k_debug_break_return_address:
856         return reinterpret_cast<Address>(Debug::debug_break_return_address());
857       case Debug::k_register_address:
858         return reinterpret_cast<Address>(Debug::register_address(reg_));
859       default:
860         UNREACHABLE();
861         return NULL;
862     }
863   }
864  private:
865   Debug::AddressId id_;
866   int reg_;
867 };
868 
869 // The optional thread that Debug Agent may use to temporary call V8 to process
870 // pending debug requests if debuggee is not running V8 at the moment.
871 // Techincally it does not call V8 itself, rather it asks embedding program
872 // to do this via v8::Debug::HostDispatchHandler
873 class MessageDispatchHelperThread: public Thread {
874  public:
875   MessageDispatchHelperThread();
876   ~MessageDispatchHelperThread();
877 
878   void Schedule();
879 
880  private:
881   void Run();
882 
883   Semaphore* const sem_;
884   Mutex* const mutex_;
885   bool already_signalled_;
886 
887   DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
888 };
889 
890 
891 } }  // namespace v8::internal
892 
893 #endif  // ENABLE_DEBUGGER_SUPPORT
894 
895 #endif  // V8_DEBUG_H_
896