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