v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
debug.h
Go to the documentation of this file.
1 // Copyright 2012 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 
108  inline int code_position() {
109  return static_cast<int>(pc() - debug_info_->code()->entry());
110  }
111  inline int break_point() { return break_point_; }
112  inline int position() { return position_; }
113  inline int statement_position() { return statement_position_; }
114  inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
115  inline Code* code() { return debug_info_->code(); }
116  inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
117  inline RelocInfo::Mode rmode() const {
118  return reloc_iterator_->rinfo()->rmode();
119  }
120  inline RelocInfo* original_rinfo() {
121  return reloc_iterator_original_->rinfo();
122  }
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:
167  ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {}
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).
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.
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 
206  DebugInfoListNode* next() { return next_; }
207  void set_next(DebugInfoListNode* next) { next_ = next; }
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();
230  bool IsLoaded() { return !debug_context_.is_null(); }
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<JSFunction> function,
237  Handle<Object> break_point_object,
238  int* source_position);
239  bool SetBreakPointForScript(Handle<Script> script,
240  Handle<Object> break_point_object,
241  int* source_position);
242  void ClearBreakPoint(Handle<Object> break_point_object);
243  void ClearAllBreakPoints();
244  void FloodWithOneShot(Handle<JSFunction> function);
245  void FloodBoundFunctionWithOneShot(Handle<JSFunction> function);
246  void FloodHandlerWithOneShot();
247  void ChangeBreakOnException(ExceptionBreakType type, bool enable);
248  bool IsBreakOnException(ExceptionBreakType type);
249  void PrepareStep(StepAction step_action, int step_count);
250  void ClearStepping();
251  void ClearStepOut();
252  bool IsStepping() { return thread_local_.step_count_ > 0; }
253  bool StepNextContinue(BreakLocationIterator* break_location_iterator,
254  JavaScriptFrame* frame);
255  static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
256  static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
257 
258  void PrepareForBreakPoints();
259 
260  // This function is used in FunctionNameUsing* tests.
261  Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position);
262 
263  // Returns whether the operation succeeded. Compilation can only be triggered
264  // if a valid closure is passed as the second argument, otherwise the shared
265  // function needs to be compiled already.
266  bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
267  Handle<JSFunction> function);
268 
269  // Returns true if the current stub call is patched to call the debugger.
270  static bool IsDebugBreak(Address addr);
271  // Returns true if the current return statement has been patched to be
272  // a debugger breakpoint.
273  static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
274 
275  // Check whether a code stub with the specified major key is a possible break
276  // point location.
277  static bool IsSourceBreakStub(Code* code);
278  static bool IsBreakStub(Code* code);
279 
280  // Find the builtin to use for invoking the debug break
281  static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
282 
283  static Handle<Object> GetSourceBreakLocations(
284  Handle<SharedFunctionInfo> shared);
285 
286  // Getter for the debug_context.
287  inline Handle<Context> debug_context() { return debug_context_; }
288 
289  // Check whether a global object is the debug global object.
290  bool IsDebugGlobal(GlobalObject* global);
291 
292  // Check whether this frame is just about to return.
293  bool IsBreakAtReturn(JavaScriptFrame* frame);
294 
295  // Fast check to see if any break points are active.
296  inline bool has_break_points() { return has_break_points_; }
297 
298  void NewBreak(StackFrame::Id break_frame_id);
299  void SetBreak(StackFrame::Id break_frame_id, int break_id);
300  StackFrame::Id break_frame_id() {
301  return thread_local_.break_frame_id_;
302  }
303  int break_id() { return thread_local_.break_id_; }
304 
305  bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
306  void HandleStepIn(Handle<JSFunction> function,
307  Handle<Object> holder,
308  Address fp,
309  bool is_constructor);
310  Address step_in_fp() { return thread_local_.step_into_fp_; }
311  Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
312 
313  bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
314  Address step_out_fp() { return thread_local_.step_out_fp_; }
315 
316  EnterDebugger* debugger_entry() {
317  return thread_local_.debugger_entry_;
318  }
319  void set_debugger_entry(EnterDebugger* entry) {
320  thread_local_.debugger_entry_ = entry;
321  }
322 
323  // Check whether any of the specified interrupts are pending.
324  bool is_interrupt_pending(InterruptFlag what) {
325  return (thread_local_.pending_interrupts_ & what) != 0;
326  }
327 
328  // Set specified interrupts as pending.
329  void set_interrupts_pending(InterruptFlag what) {
330  thread_local_.pending_interrupts_ |= what;
331  }
332 
333  // Clear specified interrupts from pending.
334  void clear_interrupt_pending(InterruptFlag what) {
335  thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
336  }
337 
338  // Getter and setter for the disable break state.
339  bool disable_break() { return disable_break_; }
340  void set_disable_break(bool disable_break) {
341  disable_break_ = disable_break;
342  }
343 
344  // Getters for the current exception break state.
345  bool break_on_exception() { return break_on_exception_; }
346  bool break_on_uncaught_exception() {
347  return break_on_uncaught_exception_;
348  }
349 
350  enum AddressId {
351  k_after_break_target_address,
352  k_debug_break_return_address,
353  k_debug_break_slot_address,
354  k_restarter_frame_function_pointer
355  };
356 
357  // Support for setting the address to jump to when returning from break point.
358  Address* after_break_target_address() {
359  return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
360  }
361  Address* restarter_frame_function_pointer_address() {
362  Object*** address = &thread_local_.restarter_frame_function_pointer_;
363  return reinterpret_cast<Address*>(address);
364  }
365 
366  // Support for saving/restoring registers when handling debug break calls.
367  Object** register_address(int r) {
368  return &registers_[r];
369  }
370 
371  // Access to the debug break on return code.
372  Code* debug_break_return() { return debug_break_return_; }
373  Code** debug_break_return_address() {
374  return &debug_break_return_;
375  }
376 
377  // Access to the debug break in debug break slot code.
378  Code* debug_break_slot() { return debug_break_slot_; }
379  Code** debug_break_slot_address() {
380  return &debug_break_slot_;
381  }
382 
383  static const int kEstimatedNofDebugInfoEntries = 16;
384  static const int kEstimatedNofBreakPointsInFunction = 16;
385 
386  // Passed to MakeWeak.
387  static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
388 
389  friend class Debugger;
390  friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
391  friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
392 
393  // Threading support.
394  char* ArchiveDebug(char* to);
395  char* RestoreDebug(char* from);
396  static int ArchiveSpacePerThread();
397  void FreeThreadResources() { }
398 
399  // Mirror cache handling.
400  void ClearMirrorCache();
401 
402  // Script cache handling.
403  void CreateScriptCache();
404  void DestroyScriptCache();
405  void AddScriptToScriptCache(Handle<Script> script);
406  Handle<FixedArray> GetLoadedScripts();
407 
408  // Garbage collection notifications.
409  void AfterGarbageCollection();
410 
411  // Code generator routines.
412  static void GenerateSlot(MacroAssembler* masm);
413  static void GenerateLoadICDebugBreak(MacroAssembler* masm);
414  static void GenerateStoreICDebugBreak(MacroAssembler* masm);
415  static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
416  static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
417  static void GenerateReturnDebugBreak(MacroAssembler* masm);
418  static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm);
419  static void GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm);
420  static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm);
421  static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm);
422  static void GenerateSlotDebugBreak(MacroAssembler* masm);
423  static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
424 
425  // FrameDropper is a code replacement for a JavaScript frame with possibly
426  // several frames above.
427  // There is no calling conventions here, because it never actually gets
428  // called, it only gets returned to.
429  static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
430 
431  // Called from stub-cache.cc.
432  static void GenerateCallICDebugBreak(MacroAssembler* masm);
433 
434  // Describes how exactly a frame has been dropped from stack.
435  enum FrameDropMode {
436  // No frame has been dropped.
437  FRAMES_UNTOUCHED,
438  // The top JS frame had been calling IC stub. IC stub mustn't be called now.
439  FRAME_DROPPED_IN_IC_CALL,
440  // The top JS frame had been calling debug break slot stub. Patch the
441  // address this stub jumps to in the end.
442  FRAME_DROPPED_IN_DEBUG_SLOT_CALL,
443  // The top JS frame had been calling some C++ function. The return address
444  // gets patched automatically.
445  FRAME_DROPPED_IN_DIRECT_CALL,
446  FRAME_DROPPED_IN_RETURN_CALL,
447  CURRENTLY_SET_MODE
448  };
449 
450  void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
451  FrameDropMode mode,
452  Object** restarter_frame_function_pointer);
453 
454  // Initializes an artificial stack frame. The data it contains is used for:
455  // a. successful work of frame dropper code which eventually gets control,
456  // b. being compatible with regular stack structure for various stack
457  // iterators.
458  // Returns address of stack allocated pointer to restarted function,
459  // the value that is called 'restarter_frame_function_pointer'. The value
460  // at this address (possibly updated by GC) may be used later when preparing
461  // 'step in' operation.
462  static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
463  Handle<Code> code);
464 
465  static const int kFrameDropperFrameSize;
466 
467  // Architecture-specific constant.
468  static const bool kFrameDropperSupported;
469 
497  class FramePaddingLayout : public AllStatic {
498  public:
499  // Architecture-specific constant.
500  static const bool kIsSupported;
501 
502  // A size of frame base including fp. Padding words starts right above
503  // the base.
504  static const int kFrameBaseSize = 4;
505 
506  // A number of words that should be reserved on stack for the LiveEdit use.
507  // Normally equals 1. Stored on stack in form of Smi.
508  static const int kInitialSize;
509  // A value that padding words are filled with (in form of Smi). Going
510  // bottom-top, the first word not having this value is a counter word.
511  static const int kPaddingValue;
512  };
513 
514  private:
515  explicit Debug(Isolate* isolate);
516  ~Debug();
517 
518  static bool CompileDebuggerScript(int index);
519  void ClearOneShot();
520  void ActivateStepIn(StackFrame* frame);
521  void ClearStepIn();
522  void ActivateStepOut(StackFrame* frame);
523  void ClearStepNext();
524  // Returns whether the compile succeeded.
525  void RemoveDebugInfo(Handle<DebugInfo> debug_info);
526  void SetAfterBreakTarget(JavaScriptFrame* frame);
527  Handle<Object> CheckBreakPoints(Handle<Object> break_point);
528  bool CheckBreakPoint(Handle<Object> break_point_object);
529 
530  // Global handle to debug context where all the debugger JavaScript code is
531  // loaded.
532  Handle<Context> debug_context_;
533 
534  // Boolean state indicating whether any break points are set.
535  bool has_break_points_;
536 
537  // Cache of all scripts in the heap.
538  ScriptCache* script_cache_;
539 
540  // List of active debug info objects.
541  DebugInfoListNode* debug_info_list_;
542 
543  bool disable_break_;
544  bool break_on_exception_;
545  bool break_on_uncaught_exception_;
546 
547  // Per-thread data.
548  class ThreadLocal {
549  public:
550  // Counter for generating next break id.
551  int break_count_;
552 
553  // Current break id.
554  int break_id_;
555 
556  // Frame id for the frame of the current break.
557  StackFrame::Id break_frame_id_;
558 
559  // Step action for last step performed.
560  StepAction last_step_action_;
561 
562  // Source statement position from last step next action.
563  int last_statement_position_;
564 
565  // Number of steps left to perform before debug event.
566  int step_count_;
567 
568  // Frame pointer from last step next action.
569  Address last_fp_;
570 
571  // Number of queued steps left to perform before debug event.
572  int queued_step_count_;
573 
574  // Frame pointer for frame from which step in was performed.
575  Address step_into_fp_;
576 
577  // Frame pointer for the frame where debugger should be called when current
578  // step out action is completed.
579  Address step_out_fp_;
580 
581  // Storage location for jump when exiting debug break calls.
582  Address after_break_target_;
583 
584  // Stores the way how LiveEdit has patched the stack. It is used when
585  // debugger returns control back to user script.
586  FrameDropMode frame_drop_mode_;
587 
588  // Top debugger entry.
589  EnterDebugger* debugger_entry_;
590 
591  // Pending interrupts scheduled while debugging.
592  int pending_interrupts_;
593 
594  // When restarter frame is on stack, stores the address
595  // of the pointer to function being restarted. Otherwise (most of the time)
596  // stores NULL. This pointer is used with 'step in' implementation.
597  Object** restarter_frame_function_pointer_;
598  };
599 
600  // Storage location for registers when handling debug break calls
601  JSCallerSavedBuffer registers_;
602  ThreadLocal thread_local_;
603  void ThreadInit();
604 
605  // Code to call for handling debug break on return.
606  Code* debug_break_return_;
607 
608  // Code to call for handling debug break in debug break slots.
609  Code* debug_break_slot_;
610 
611  Isolate* isolate_;
612 
613  friend class Isolate;
614 
616 };
617 
618 
619 DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break);
620 
621 
622 // Message delivered to the message handler callback. This is either a debugger
623 // event or the response to a command.
624 class MessageImpl: public v8::Debug::Message {
625  public:
626  // Create a message object for a debug event.
627  static MessageImpl NewEvent(DebugEvent event,
628  bool running,
629  Handle<JSObject> exec_state,
630  Handle<JSObject> event_data);
631 
632  // Create a message object for the response to a debug command.
633  static MessageImpl NewResponse(DebugEvent event,
634  bool running,
635  Handle<JSObject> exec_state,
636  Handle<JSObject> event_data,
637  Handle<String> response_json,
638  v8::Debug::ClientData* client_data);
639 
640  // Implementation of interface v8::Debug::Message.
641  virtual bool IsEvent() const;
642  virtual bool IsResponse() const;
643  virtual DebugEvent GetEvent() const;
644  virtual bool WillStartRunning() const;
645  virtual v8::Handle<v8::Object> GetExecutionState() const;
646  virtual v8::Handle<v8::Object> GetEventData() const;
647  virtual v8::Handle<v8::String> GetJSON() const;
648  virtual v8::Handle<v8::Context> GetEventContext() const;
649  virtual v8::Debug::ClientData* GetClientData() const;
650 
651  private:
652  MessageImpl(bool is_event,
653  DebugEvent event,
654  bool running,
655  Handle<JSObject> exec_state,
656  Handle<JSObject> event_data,
657  Handle<String> response_json,
658  v8::Debug::ClientData* client_data);
659 
660  bool is_event_; // Does this message represent a debug event?
661  DebugEvent event_; // Debug event causing the break.
662  bool running_; // Will the VM start running after this event?
663  Handle<JSObject> exec_state_; // Current execution state.
664  Handle<JSObject> event_data_; // Data associated with the event.
665  Handle<String> response_json_; // Response JSON if message holds a response.
666  v8::Debug::ClientData* client_data_; // Client data passed with the request.
667 };
668 
669 
670 // Details of the debug event delivered to the debug event listener.
671 class EventDetailsImpl : public v8::Debug::EventDetails {
672  public:
673  EventDetailsImpl(DebugEvent event,
674  Handle<JSObject> exec_state,
675  Handle<JSObject> event_data,
676  Handle<Object> callback_data,
677  v8::Debug::ClientData* client_data);
678  virtual DebugEvent GetEvent() const;
679  virtual v8::Handle<v8::Object> GetExecutionState() const;
680  virtual v8::Handle<v8::Object> GetEventData() const;
681  virtual v8::Handle<v8::Context> GetEventContext() const;
682  virtual v8::Handle<v8::Value> GetCallbackData() const;
683  virtual v8::Debug::ClientData* GetClientData() const;
684  private:
685  DebugEvent event_; // Debug event causing the break.
686  Handle<JSObject> exec_state_; // Current execution state.
687  Handle<JSObject> event_data_; // Data associated with the event.
688  Handle<Object> callback_data_; // User data passed with the callback
689  // when it was registered.
690  v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand.
691 };
692 
693 
694 // Message send by user to v8 debugger or debugger output message.
695 // In addition to command text it may contain a pointer to some user data
696 // which are expected to be passed along with the command reponse to message
697 // handler.
698 class CommandMessage {
699  public:
700  static CommandMessage New(const Vector<uint16_t>& command,
701  v8::Debug::ClientData* data);
702  CommandMessage();
703  ~CommandMessage();
704 
705  // Deletes user data and disposes of the text.
706  void Dispose();
707  Vector<uint16_t> text() const { return text_; }
708  v8::Debug::ClientData* client_data() const { return client_data_; }
709  private:
710  CommandMessage(const Vector<uint16_t>& text,
711  v8::Debug::ClientData* data);
712 
713  Vector<uint16_t> text_;
714  v8::Debug::ClientData* client_data_;
715 };
716 
717 // A Queue of CommandMessage objects. A thread-safe version is
718 // LockingCommandMessageQueue, based on this class.
719 class CommandMessageQueue BASE_EMBEDDED {
720  public:
721  explicit CommandMessageQueue(int size);
722  ~CommandMessageQueue();
723  bool IsEmpty() const { return start_ == end_; }
724  CommandMessage Get();
725  void Put(const CommandMessage& message);
726  void Clear() { start_ = end_ = 0; } // Queue is empty after Clear().
727  private:
728  // Doubles the size of the message queue, and copies the messages.
729  void Expand();
730 
731  CommandMessage* messages_;
732  int start_;
733  int end_;
734  int size_; // The size of the queue buffer. Queue can hold size-1 messages.
735 };
736 
737 
738 class MessageDispatchHelperThread;
739 
740 
741 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
742 // messages. The message data is not managed by LockingCommandMessageQueue.
743 // Pointers to the data are passed in and out. Implemented by adding a
744 // Mutex to CommandMessageQueue. Includes logging of all puts and gets.
745 class LockingCommandMessageQueue BASE_EMBEDDED {
746  public:
747  LockingCommandMessageQueue(Logger* logger, int size);
748  ~LockingCommandMessageQueue();
749  bool IsEmpty() const;
750  CommandMessage Get();
751  void Put(const CommandMessage& message);
752  void Clear();
753  private:
754  Logger* logger_;
755  CommandMessageQueue queue_;
756  Mutex* lock_;
757  DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
758 };
759 
760 
761 class Debugger {
762  public:
763  ~Debugger();
764 
765  void DebugRequest(const uint16_t* json_request, int length);
766 
767  Handle<Object> MakeJSObject(Vector<const char> constructor_name,
768  int argc,
769  Handle<Object> argv[],
770  bool* caught_exception);
771  Handle<Object> MakeExecutionState(bool* caught_exception);
772  Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
773  Handle<Object> break_points_hit,
774  bool* caught_exception);
775  Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
776  Handle<Object> exception,
777  bool uncaught,
778  bool* caught_exception);
779  Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
780  bool* caught_exception);
781  Handle<Object> MakeCompileEvent(Handle<Script> script,
782  bool before,
783  bool* caught_exception);
784  Handle<Object> MakeScriptCollectedEvent(int id,
785  bool* caught_exception);
786  void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
787  void OnException(Handle<Object> exception, bool uncaught);
788  void OnBeforeCompile(Handle<Script> script);
789 
790  enum AfterCompileFlags {
791  NO_AFTER_COMPILE_FLAGS,
792  SEND_WHEN_DEBUGGING
793  };
794  void OnAfterCompile(Handle<Script> script,
795  AfterCompileFlags after_compile_flags);
796  void OnScriptCollected(int id);
797  void ProcessDebugEvent(v8::DebugEvent event,
798  Handle<JSObject> event_data,
799  bool auto_continue);
800  void NotifyMessageHandler(v8::DebugEvent event,
801  Handle<JSObject> exec_state,
802  Handle<JSObject> event_data,
803  bool auto_continue);
804  void SetEventListener(Handle<Object> callback, Handle<Object> data);
805  void SetMessageHandler(v8::Debug::MessageHandler2 handler);
806  void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
807  int period);
808  void SetDebugMessageDispatchHandler(
810  bool provide_locker);
811 
812  // Invoke the message handler function.
813  void InvokeMessageHandler(MessageImpl message);
814 
815  // Add a debugger command to the command queue.
816  void ProcessCommand(Vector<const uint16_t> command,
817  v8::Debug::ClientData* client_data = NULL);
818 
819  // Check whether there are commands in the command queue.
820  bool HasCommands();
821 
822  // Enqueue a debugger command to the command queue for event listeners.
823  void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
824 
825  Handle<Object> Call(Handle<JSFunction> fun,
826  Handle<Object> data,
827  bool* pending_exception);
828 
829  // Start the debugger agent listening on the provided port.
830  bool StartAgent(const char* name, int port,
831  bool wait_for_connection = false);
832 
833  // Stop the debugger agent.
834  void StopAgent();
835 
836  // Blocks until the agent has started listening for connections
837  void WaitForAgent();
838 
839  void CallMessageDispatchHandler();
840 
841  Handle<Context> GetDebugContext();
842 
843  // Unload the debugger if possible. Only called when no debugger is currently
844  // active.
845  void UnloadDebugger();
846  friend void ForceUnloadDebugger(); // In test-debug.cc
847 
848  inline bool EventActive(v8::DebugEvent event) {
849  ScopedLock with(debugger_access_);
850 
851  // Check whether the message handler was been cleared.
852  if (debugger_unload_pending_) {
853  if (isolate_->debug()->debugger_entry() == NULL) {
854  UnloadDebugger();
855  }
856  }
857 
858  if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) &&
859  !FLAG_debug_compile_events) {
860  return false;
861 
862  } else if ((event == v8::ScriptCollected) &&
863  !FLAG_debug_script_collected_events) {
864  return false;
865  }
866 
867  // Currently argument event is not used.
868  return !compiling_natives_ && Debugger::IsDebuggerActive();
869  }
870 
871  void set_compiling_natives(bool compiling_natives) {
872  compiling_natives_ = compiling_natives;
873  }
874  bool compiling_natives() const { return compiling_natives_; }
875  void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
876  bool is_loading_debugger() const { return is_loading_debugger_; }
877  void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
878  bool live_edit_enabled() const { return live_edit_enabled_; }
879  void set_force_debugger_active(bool force_debugger_active) {
880  force_debugger_active_ = force_debugger_active;
881  }
882  bool force_debugger_active() const { return force_debugger_active_; }
883 
884  bool IsDebuggerActive();
885 
886  private:
887  explicit Debugger(Isolate* isolate);
888 
889  void CallEventCallback(v8::DebugEvent event,
890  Handle<Object> exec_state,
891  Handle<Object> event_data,
892  v8::Debug::ClientData* client_data);
893  void CallCEventCallback(v8::DebugEvent event,
894  Handle<Object> exec_state,
895  Handle<Object> event_data,
896  v8::Debug::ClientData* client_data);
897  void CallJSEventCallback(v8::DebugEvent event,
898  Handle<Object> exec_state,
899  Handle<Object> event_data);
900  void ListenersChanged();
901 
902  Mutex* debugger_access_; // Mutex guarding debugger variables.
903  Handle<Object> event_listener_; // Global handle to listener.
904  Handle<Object> event_listener_data_;
905  bool compiling_natives_; // Are we compiling natives?
906  bool is_loading_debugger_; // Are we loading the debugger?
907  bool live_edit_enabled_; // Enable LiveEdit.
908  bool never_unload_debugger_; // Can we unload the debugger?
909  bool force_debugger_active_; // Activate debugger without event listeners.
910  v8::Debug::MessageHandler2 message_handler_;
911  bool debugger_unload_pending_; // Was message handler cleared?
912  v8::Debug::HostDispatchHandler host_dispatch_handler_;
913  Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler.
914  v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
915  MessageDispatchHelperThread* message_dispatch_helper_thread_;
916  int host_dispatch_micros_;
917 
918  DebuggerAgent* agent_;
919 
920  static const int kQueueInitialSize = 4;
921  LockingCommandMessageQueue command_queue_;
922  Semaphore* command_received_; // Signaled for each command received.
923  LockingCommandMessageQueue event_command_queue_;
924 
925  Isolate* isolate_;
926 
927  friend class EnterDebugger;
928  friend class Isolate;
929 
930  DISALLOW_COPY_AND_ASSIGN(Debugger);
931 };
932 
933 
934 // This class is used for entering the debugger. Create an instance in the stack
935 // to enter the debugger. This will set the current break state, make sure the
936 // debugger is loaded and switch to the debugger context. If the debugger for
937 // some reason could not be entered FailedToEnter will return true.
938 class EnterDebugger BASE_EMBEDDED {
939  public:
940  EnterDebugger();
941  ~EnterDebugger();
942 
943  // Check whether the debugger could be entered.
944  inline bool FailedToEnter() { return load_failed_; }
945 
946  // Check whether there are any JavaScript frames on the stack.
947  inline bool HasJavaScriptFrames() { return has_js_frames_; }
948 
949  // Get the active context from before entering the debugger.
950  inline Handle<Context> GetContext() { return save_.context(); }
951 
952  private:
953  Isolate* isolate_;
954  EnterDebugger* prev_; // Previous debugger entry if entered recursively.
956  const bool has_js_frames_; // Were there any JavaScript frames?
957  StackFrame::Id break_frame_id_; // Previous break frame id.
958  int break_id_; // Previous break id.
959  bool load_failed_; // Did the debugger fail to load?
960  SaveContext save_; // Saves previous context.
961 };
962 
963 
964 // Stack allocated class for disabling break.
965 class DisableBreak BASE_EMBEDDED {
966  public:
967  explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) {
968  prev_disable_break_ = isolate_->debug()->disable_break();
969  isolate_->debug()->set_disable_break(disable_break);
970  }
971  ~DisableBreak() {
972  ASSERT(Isolate::Current() == isolate_);
973  isolate_->debug()->set_disable_break(prev_disable_break_);
974  }
975 
976  private:
977  Isolate* isolate_;
978  // The previous state of the disable break used to restore the value when this
979  // object is destructed.
980  bool prev_disable_break_;
981 };
982 
983 
984 // Debug_Address encapsulates the Address pointers used in generating debug
985 // code.
986 class Debug_Address {
987  public:
988  explicit Debug_Address(Debug::AddressId id) : id_(id) { }
989 
990  static Debug_Address AfterBreakTarget() {
991  return Debug_Address(Debug::k_after_break_target_address);
992  }
993 
994  static Debug_Address DebugBreakReturn() {
995  return Debug_Address(Debug::k_debug_break_return_address);
996  }
997 
998  static Debug_Address RestarterFrameFunctionPointer() {
999  return Debug_Address(Debug::k_restarter_frame_function_pointer);
1000  }
1001 
1002  Address address(Isolate* isolate) const {
1003  Debug* debug = isolate->debug();
1004  switch (id_) {
1005  case Debug::k_after_break_target_address:
1006  return reinterpret_cast<Address>(debug->after_break_target_address());
1007  case Debug::k_debug_break_return_address:
1008  return reinterpret_cast<Address>(debug->debug_break_return_address());
1009  case Debug::k_debug_break_slot_address:
1010  return reinterpret_cast<Address>(debug->debug_break_slot_address());
1011  case Debug::k_restarter_frame_function_pointer:
1012  return reinterpret_cast<Address>(
1013  debug->restarter_frame_function_pointer_address());
1014  default:
1015  UNREACHABLE();
1016  return NULL;
1017  }
1018  }
1019 
1020  private:
1021  Debug::AddressId id_;
1022 };
1023 
1024 // The optional thread that Debug Agent may use to temporary call V8 to process
1025 // pending debug requests if debuggee is not running V8 at the moment.
1026 // Techincally it does not call V8 itself, rather it asks embedding program
1027 // to do this via v8::Debug::HostDispatchHandler
1028 class MessageDispatchHelperThread: public Thread {
1029  public:
1030  explicit MessageDispatchHelperThread(Isolate* isolate);
1031  ~MessageDispatchHelperThread();
1032 
1033  void Schedule();
1034 
1035  private:
1036  void Run();
1037 
1038  Semaphore* const sem_;
1039  Mutex* const mutex_;
1040  bool already_signalled_;
1041 
1042  DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
1043 };
1044 
1045 
1046 } } // namespace v8::internal
1047 
1048 #endif // ENABLE_DEBUGGER_SUPPORT
1049 
1050 #endif // V8_DEBUG_H_
byte * Address
Definition: globals.h:157
DebugEvent
Definition: v8-debug.h:73
void(* DebugMessageDispatchHandler)()
Definition: v8-debug.h:245
#define ASSERT(condition)
Definition: checks.h:270
void(* MessageHandler2)(const Message &message)
Definition: v8-debug.h:235
unsigned short uint16_t
Definition: unicode.cc:46
HANDLE HANDLE LPSTACKFRAME64 StackFrame
#define UNREACHABLE()
Definition: checks.h:50
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:307
const Register pc
#define BASE_EMBEDDED
Definition: allocation.h:68
void(* HostDispatchHandler)()
Definition: v8-debug.h:240
uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed)
Definition: utils.h:286
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
Definition: frames.h:775
Object * JSCallerSavedBuffer[kNumJSCallerSaved]
Definition: frames-arm.h:55
v8::Handle< v8::Value > Load(const v8::Arguments &args)
Definition: shell.cc:159
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
Definition: hashmap.h:113
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
Definition: flags.cc:495
bool end_
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
DECLARE_RUNTIME_FUNCTION(MaybeObject *, LoadCallbackProperty)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const Register fp