The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / debug.h @ f230a1cf

History | View | Annotate | Download (37.5 KB)

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 "platform/socket.h"
42
#include "string-stream.h"
43
#include "v8threads.h"
44

    
45
#ifdef ENABLE_DEBUGGER_SUPPORT
46
#include "../include/v8-debug.h"
47

    
48
namespace v8 {
49
namespace internal {
50

    
51

    
52
// Forward declarations.
53
class EnterDebugger;
54

    
55

    
56
// Step actions. NOTE: These values are in macros.py as well.
57
enum StepAction {
58
  StepNone = -1,  // Stepping not prepared.
59
  StepOut = 0,   // Step out of the current function.
60
  StepNext = 1,  // Step to the next statement in the current function.
61
  StepIn = 2,    // Step into new functions invoked or the next statement
62
                 // in the current function.
63
  StepMin = 3,   // Perform a minimum step in the current function.
64
  StepInMin = 4  // Step into new functions invoked or perform a minimum step
65
                 // in the current function.
66
};
67

    
68

    
69
// Type of exception break. NOTE: These values are in macros.py as well.
70
enum ExceptionBreakType {
71
  BreakException = 0,
72
  BreakUncaughtException = 1
73
};
74

    
75

    
76
// Type of exception break. NOTE: These values are in macros.py as well.
77
enum BreakLocatorType {
78
  ALL_BREAK_LOCATIONS = 0,
79
  SOURCE_BREAK_LOCATIONS = 1
80
};
81

    
82

    
83
// The different types of breakpoint position alignments.
84
// Must match Debug.BreakPositionAlignment in debug-debugger.js
85
enum BreakPositionAlignment {
86
  STATEMENT_ALIGNED = 0,
87
  BREAK_POSITION_ALIGNED = 1
88
};
89

    
90

    
91
// Class for iterating through the break points in a function and changing
92
// them.
93
class BreakLocationIterator {
94
 public:
95
  explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
96
                                 BreakLocatorType type);
97
  virtual ~BreakLocationIterator();
98

    
99
  void Next();
100
  void Next(int count);
101
  void FindBreakLocationFromAddress(Address pc);
102
  void FindBreakLocationFromPosition(int position,
103
      BreakPositionAlignment alignment);
104
  void Reset();
105
  bool Done() const;
106
  void SetBreakPoint(Handle<Object> break_point_object);
107
  void ClearBreakPoint(Handle<Object> break_point_object);
108
  void SetOneShot();
109
  void ClearOneShot();
110
  bool IsStepInLocation(Isolate* isolate);
111
  void PrepareStepIn(Isolate* isolate);
112
  bool IsExit() const;
113
  bool HasBreakPoint();
114
  bool IsDebugBreak();
115
  Object* BreakPointObjects();
116
  void ClearAllDebugBreak();
117

    
118

    
119
  inline int code_position() {
120
    return static_cast<int>(pc() - debug_info_->code()->entry());
121
  }
122
  inline int break_point() { return break_point_; }
123
  inline int position() { return position_; }
124
  inline int statement_position() { return statement_position_; }
125
  inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
126
  inline Code* code() { return debug_info_->code(); }
127
  inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
128
  inline RelocInfo::Mode rmode() const {
129
    return reloc_iterator_->rinfo()->rmode();
130
  }
131
  inline RelocInfo* original_rinfo() {
132
    return reloc_iterator_original_->rinfo();
133
  }
134
  inline RelocInfo::Mode original_rmode() const {
135
    return reloc_iterator_original_->rinfo()->rmode();
136
  }
137

    
138
  bool IsDebuggerStatement();
139

    
140
 protected:
141
  bool RinfoDone() const;
142
  void RinfoNext();
143

    
144
  BreakLocatorType type_;
145
  int break_point_;
146
  int position_;
147
  int statement_position_;
148
  Handle<DebugInfo> debug_info_;
149
  RelocIterator* reloc_iterator_;
150
  RelocIterator* reloc_iterator_original_;
151

    
152
 private:
153
  void SetDebugBreak();
154
  void ClearDebugBreak();
155

    
156
  void SetDebugBreakAtIC();
157
  void ClearDebugBreakAtIC();
158

    
159
  bool IsDebugBreakAtReturn();
160
  void SetDebugBreakAtReturn();
161
  void ClearDebugBreakAtReturn();
162

    
163
  bool IsDebugBreakSlot();
164
  bool IsDebugBreakAtSlot();
165
  void SetDebugBreakAtSlot();
166
  void ClearDebugBreakAtSlot();
167

    
168
  DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
169
};
170

    
171

    
172
// Cache of all script objects in the heap. When a script is added a weak handle
173
// to it is created and that weak handle is stored in the cache. The weak handle
174
// callback takes care of removing the script from the cache. The key used in
175
// the cache is the script id.
176
class ScriptCache : private HashMap {
177
 public:
178
  explicit ScriptCache(Isolate* isolate)
179
    : HashMap(ScriptMatch), isolate_(isolate), collected_scripts_(10) {}
180
  virtual ~ScriptCache() { Clear(); }
181

    
182
  // Add script to the cache.
183
  void Add(Handle<Script> script);
184

    
185
  // Return the scripts in the cache.
186
  Handle<FixedArray> GetScripts();
187

    
188
  // Generate debugger events for collected scripts.
189
  void ProcessCollectedScripts();
190

    
191
 private:
192
  // Calculate the hash value from the key (script id).
193
  static uint32_t Hash(int key) {
194
    return ComputeIntegerHash(key, v8::internal::kZeroHashSeed);
195
  }
196

    
197
  // Scripts match if their keys (script id) match.
198
  static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
199

    
200
  // Clear the cache releasing all the weak handles.
201
  void Clear();
202

    
203
  // Weak handle callback for scripts in the cache.
204
  static void HandleWeakScript(v8::Isolate* isolate,
205
                               v8::Persistent<v8::Value>* obj,
206
                               void* data);
207

    
208
  Isolate* isolate_;
209
  // List used during GC to temporarily store id's of collected scripts.
210
  List<int> collected_scripts_;
211
};
212

    
213

    
214
// Linked list holding debug info objects. The debug info objects are kept as
215
// weak handles to avoid a debug info object to keep a function alive.
216
class DebugInfoListNode {
217
 public:
218
  explicit DebugInfoListNode(DebugInfo* debug_info);
219
  virtual ~DebugInfoListNode();
220

    
221
  DebugInfoListNode* next() { return next_; }
222
  void set_next(DebugInfoListNode* next) { next_ = next; }
223
  Handle<DebugInfo> debug_info() { return debug_info_; }
224

    
225
 private:
226
  // Global (weak) handle to the debug info object.
227
  Handle<DebugInfo> debug_info_;
228

    
229
  // Next pointer for linked list.
230
  DebugInfoListNode* next_;
231
};
232

    
233
// This class contains the debugger support. The main purpose is to handle
234
// setting break points in the code.
235
//
236
// This class controls the debug info for all functions which currently have
237
// active breakpoints in them. This debug info is held in the heap root object
238
// debug_info which is a FixedArray. Each entry in this list is of class
239
// DebugInfo.
240
class Debug {
241
 public:
242
  void SetUp(bool create_heap_objects);
243
  bool Load();
244
  void Unload();
245
  bool IsLoaded() { return !debug_context_.is_null(); }
246
  bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
247
  void PreemptionWhileInDebugger();
248
  void Iterate(ObjectVisitor* v);
249

    
250
  Object* Break(Arguments args);
251
  void SetBreakPoint(Handle<JSFunction> function,
252
                     Handle<Object> break_point_object,
253
                     int* source_position);
254
  bool SetBreakPointForScript(Handle<Script> script,
255
                              Handle<Object> break_point_object,
256
                              int* source_position,
257
                              BreakPositionAlignment alignment);
258
  void ClearBreakPoint(Handle<Object> break_point_object);
259
  void ClearAllBreakPoints();
260
  void FloodWithOneShot(Handle<JSFunction> function);
261
  void FloodBoundFunctionWithOneShot(Handle<JSFunction> function);
262
  void FloodHandlerWithOneShot();
263
  void ChangeBreakOnException(ExceptionBreakType type, bool enable);
264
  bool IsBreakOnException(ExceptionBreakType type);
265
  void PrepareStep(StepAction step_action,
266
                   int step_count,
267
                   StackFrame::Id frame_id);
268
  void ClearStepping();
269
  void ClearStepOut();
270
  bool IsStepping() { return thread_local_.step_count_ > 0; }
271
  bool StepNextContinue(BreakLocationIterator* break_location_iterator,
272
                        JavaScriptFrame* frame);
273
  static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
274
  static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
275

    
276
  void PrepareForBreakPoints();
277

    
278
  // This function is used in FunctionNameUsing* tests.
279
  Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position);
280

    
281
  // Returns whether the operation succeeded. Compilation can only be triggered
282
  // if a valid closure is passed as the second argument, otherwise the shared
283
  // function needs to be compiled already.
284
  bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
285
                       Handle<JSFunction> function);
286

    
287
  // Returns true if the current stub call is patched to call the debugger.
288
  static bool IsDebugBreak(Address addr);
289
  // Returns true if the current return statement has been patched to be
290
  // a debugger breakpoint.
291
  static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
292

    
293
  // Check whether a code stub with the specified major key is a possible break
294
  // point location.
295
  static bool IsSourceBreakStub(Code* code);
296
  static bool IsBreakStub(Code* code);
297

    
298
  // Find the builtin to use for invoking the debug break
299
  static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
300

    
301
  static Handle<Object> GetSourceBreakLocations(
302
      Handle<SharedFunctionInfo> shared,
303
      BreakPositionAlignment position_aligment);
304

    
305
  // Getter for the debug_context.
306
  inline Handle<Context> debug_context() { return debug_context_; }
307

    
308
  // Check whether a global object is the debug global object.
309
  bool IsDebugGlobal(GlobalObject* global);
310

    
311
  // Check whether this frame is just about to return.
312
  bool IsBreakAtReturn(JavaScriptFrame* frame);
313

    
314
  // Fast check to see if any break points are active.
315
  inline bool has_break_points() { return has_break_points_; }
316

    
317
  void NewBreak(StackFrame::Id break_frame_id);
318
  void SetBreak(StackFrame::Id break_frame_id, int break_id);
319
  StackFrame::Id break_frame_id() {
320
    return thread_local_.break_frame_id_;
321
  }
322
  int break_id() { return thread_local_.break_id_; }
323

    
324
  bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
325
  void HandleStepIn(Handle<JSFunction> function,
326
                    Handle<Object> holder,
327
                    Address fp,
328
                    bool is_constructor);
329
  Address step_in_fp() { return thread_local_.step_into_fp_; }
330
  Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
331

    
332
  bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
333
  Address step_out_fp() { return thread_local_.step_out_fp_; }
334

    
335
  EnterDebugger* debugger_entry() {
336
    return thread_local_.debugger_entry_;
337
  }
338
  void set_debugger_entry(EnterDebugger* entry) {
339
    thread_local_.debugger_entry_ = entry;
340
  }
341

    
342
  // Check whether any of the specified interrupts are pending.
343
  bool is_interrupt_pending(InterruptFlag what) {
344
    return (thread_local_.pending_interrupts_ & what) != 0;
345
  }
346

    
347
  // Set specified interrupts as pending.
348
  void set_interrupts_pending(InterruptFlag what) {
349
    thread_local_.pending_interrupts_ |= what;
350
  }
351

    
352
  // Clear specified interrupts from pending.
353
  void clear_interrupt_pending(InterruptFlag what) {
354
    thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
355
  }
356

    
357
  // Getter and setter for the disable break state.
358
  bool disable_break() { return disable_break_; }
359
  void set_disable_break(bool disable_break) {
360
    disable_break_ = disable_break;
361
  }
362

    
363
  // Getters for the current exception break state.
364
  bool break_on_exception() { return break_on_exception_; }
365
  bool break_on_uncaught_exception() {
366
    return break_on_uncaught_exception_;
367
  }
368

    
369
  enum AddressId {
370
    k_after_break_target_address,
371
    k_debug_break_return_address,
372
    k_debug_break_slot_address,
373
    k_restarter_frame_function_pointer
374
  };
375

    
376
  // Support for setting the address to jump to when returning from break point.
377
  Address* after_break_target_address() {
378
    return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
379
  }
380
  Address* restarter_frame_function_pointer_address() {
381
    Object*** address = &thread_local_.restarter_frame_function_pointer_;
382
    return reinterpret_cast<Address*>(address);
383
  }
384

    
385
  // Support for saving/restoring registers when handling debug break calls.
386
  Object** register_address(int r) {
387
    return &registers_[r];
388
  }
389

    
390
  // Access to the debug break on return code.
391
  Code* debug_break_return() { return debug_break_return_; }
392
  Code** debug_break_return_address() {
393
    return &debug_break_return_;
394
  }
395

    
396
  // Access to the debug break in debug break slot code.
397
  Code* debug_break_slot() { return debug_break_slot_; }
398
  Code** debug_break_slot_address() {
399
    return &debug_break_slot_;
400
  }
401

    
402
  static const int kEstimatedNofDebugInfoEntries = 16;
403
  static const int kEstimatedNofBreakPointsInFunction = 16;
404

    
405
  // Passed to MakeWeak.
406
  static void HandleWeakDebugInfo(v8::Isolate* isolate,
407
                                  v8::Persistent<v8::Value>* obj,
408
                                  void* data);
409

    
410
  friend class Debugger;
411
  friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
412
  friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
413

    
414
  // Threading support.
415
  char* ArchiveDebug(char* to);
416
  char* RestoreDebug(char* from);
417
  static int ArchiveSpacePerThread();
418
  void FreeThreadResources() { }
419

    
420
  // Mirror cache handling.
421
  void ClearMirrorCache();
422

    
423
  // Script cache handling.
424
  void CreateScriptCache();
425
  void DestroyScriptCache();
426
  void AddScriptToScriptCache(Handle<Script> script);
427
  Handle<FixedArray> GetLoadedScripts();
428

    
429
  // Garbage collection notifications.
430
  void AfterGarbageCollection();
431

    
432
  // Code generator routines.
433
  static void GenerateSlot(MacroAssembler* masm);
434
  static void GenerateLoadICDebugBreak(MacroAssembler* masm);
435
  static void GenerateStoreICDebugBreak(MacroAssembler* masm);
436
  static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
437
  static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
438
  static void GenerateCompareNilICDebugBreak(MacroAssembler* masm);
439
  static void GenerateReturnDebugBreak(MacroAssembler* masm);
440
  static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm);
441
  static void GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm);
442
  static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm);
443
  static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm);
444
  static void GenerateSlotDebugBreak(MacroAssembler* masm);
445
  static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
446

    
447
  // FrameDropper is a code replacement for a JavaScript frame with possibly
448
  // several frames above.
449
  // There is no calling conventions here, because it never actually gets
450
  // called, it only gets returned to.
451
  static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
452

    
453
  // Called from stub-cache.cc.
454
  static void GenerateCallICDebugBreak(MacroAssembler* masm);
455

    
456
  // Describes how exactly a frame has been dropped from stack.
457
  enum FrameDropMode {
458
    // No frame has been dropped.
459
    FRAMES_UNTOUCHED,
460
    // The top JS frame had been calling IC stub. IC stub mustn't be called now.
461
    FRAME_DROPPED_IN_IC_CALL,
462
    // The top JS frame had been calling debug break slot stub. Patch the
463
    // address this stub jumps to in the end.
464
    FRAME_DROPPED_IN_DEBUG_SLOT_CALL,
465
    // The top JS frame had been calling some C++ function. The return address
466
    // gets patched automatically.
467
    FRAME_DROPPED_IN_DIRECT_CALL,
468
    FRAME_DROPPED_IN_RETURN_CALL,
469
    CURRENTLY_SET_MODE
470
  };
471

    
472
  void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
473
                                    FrameDropMode mode,
474
                                    Object** restarter_frame_function_pointer);
475

    
476
  // Initializes an artificial stack frame. The data it contains is used for:
477
  //  a. successful work of frame dropper code which eventually gets control,
478
  //  b. being compatible with regular stack structure for various stack
479
  //     iterators.
480
  // Returns address of stack allocated pointer to restarted function,
481
  // the value that is called 'restarter_frame_function_pointer'. The value
482
  // at this address (possibly updated by GC) may be used later when preparing
483
  // 'step in' operation.
484
  static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
485
                                         Handle<Code> code);
486

    
487
  static const int kFrameDropperFrameSize;
488

    
489
  // Architecture-specific constant.
490
  static const bool kFrameDropperSupported;
491

    
492
  /**
493
   * Defines layout of a stack frame that supports padding. This is a regular
494
   * internal frame that has a flexible stack structure. LiveEdit can shift
495
   * its lower part up the stack, taking up the 'padding' space when additional
496
   * stack memory is required.
497
   * Such frame is expected immediately above the topmost JavaScript frame.
498
   *
499
   * Stack Layout:
500
   *   --- Top
501
   *   LiveEdit routine frames
502
   *   ---
503
   *   C frames of debug handler
504
   *   ---
505
   *   ...
506
   *   ---
507
   *      An internal frame that has n padding words:
508
   *      - any number of words as needed by code -- upper part of frame
509
   *      - padding size: a Smi storing n -- current size of padding
510
   *      - padding: n words filled with kPaddingValue in form of Smi
511
   *      - 3 context/type words of a regular InternalFrame
512
   *      - fp
513
   *   ---
514
   *      Topmost JavaScript frame
515
   *   ---
516
   *   ...
517
   *   --- Bottom
518
   */
519
  class FramePaddingLayout : public AllStatic {
520
   public:
521
    // Architecture-specific constant.
522
    static const bool kIsSupported;
523

    
524
    // A size of frame base including fp. Padding words starts right above
525
    // the base.
526
    static const int kFrameBaseSize = 4;
527

    
528
    // A number of words that should be reserved on stack for the LiveEdit use.
529
    // Normally equals 1. Stored on stack in form of Smi.
530
    static const int kInitialSize;
531
    // A value that padding words are filled with (in form of Smi). Going
532
    // bottom-top, the first word not having this value is a counter word.
533
    static const int kPaddingValue;
534
  };
535

    
536
 private:
537
  explicit Debug(Isolate* isolate);
538
  ~Debug();
539

    
540
  static bool CompileDebuggerScript(Isolate* isolate, int index);
541
  void ClearOneShot();
542
  void ActivateStepIn(StackFrame* frame);
543
  void ClearStepIn();
544
  void ActivateStepOut(StackFrame* frame);
545
  void ClearStepNext();
546
  // Returns whether the compile succeeded.
547
  void RemoveDebugInfo(Handle<DebugInfo> debug_info);
548
  void SetAfterBreakTarget(JavaScriptFrame* frame);
549
  Handle<Object> CheckBreakPoints(Handle<Object> break_point);
550
  bool CheckBreakPoint(Handle<Object> break_point_object);
551

    
552
  // Global handle to debug context where all the debugger JavaScript code is
553
  // loaded.
554
  Handle<Context> debug_context_;
555

    
556
  // Boolean state indicating whether any break points are set.
557
  bool has_break_points_;
558

    
559
  // Cache of all scripts in the heap.
560
  ScriptCache* script_cache_;
561

    
562
  // List of active debug info objects.
563
  DebugInfoListNode* debug_info_list_;
564

    
565
  bool disable_break_;
566
  bool break_on_exception_;
567
  bool break_on_uncaught_exception_;
568

    
569
  // Per-thread data.
570
  class ThreadLocal {
571
   public:
572
    // Counter for generating next break id.
573
    int break_count_;
574

    
575
    // Current break id.
576
    int break_id_;
577

    
578
    // Frame id for the frame of the current break.
579
    StackFrame::Id break_frame_id_;
580

    
581
    // Step action for last step performed.
582
    StepAction last_step_action_;
583

    
584
    // Source statement position from last step next action.
585
    int last_statement_position_;
586

    
587
    // Number of steps left to perform before debug event.
588
    int step_count_;
589

    
590
    // Frame pointer from last step next action.
591
    Address last_fp_;
592

    
593
    // Number of queued steps left to perform before debug event.
594
    int queued_step_count_;
595

    
596
    // Frame pointer for frame from which step in was performed.
597
    Address step_into_fp_;
598

    
599
    // Frame pointer for the frame where debugger should be called when current
600
    // step out action is completed.
601
    Address step_out_fp_;
602

    
603
    // Storage location for jump when exiting debug break calls.
604
    Address after_break_target_;
605

    
606
    // Stores the way how LiveEdit has patched the stack. It is used when
607
    // debugger returns control back to user script.
608
    FrameDropMode frame_drop_mode_;
609

    
610
    // Top debugger entry.
611
    EnterDebugger* debugger_entry_;
612

    
613
    // Pending interrupts scheduled while debugging.
614
    int pending_interrupts_;
615

    
616
    // When restarter frame is on stack, stores the address
617
    // of the pointer to function being restarted. Otherwise (most of the time)
618
    // stores NULL. This pointer is used with 'step in' implementation.
619
    Object** restarter_frame_function_pointer_;
620
  };
621

    
622
  // Storage location for registers when handling debug break calls
623
  JSCallerSavedBuffer registers_;
624
  ThreadLocal thread_local_;
625
  void ThreadInit();
626

    
627
  // Code to call for handling debug break on return.
628
  Code* debug_break_return_;
629

    
630
  // Code to call for handling debug break in debug break slots.
631
  Code* debug_break_slot_;
632

    
633
  Isolate* isolate_;
634

    
635
  friend class Isolate;
636

    
637
  DISALLOW_COPY_AND_ASSIGN(Debug);
638
};
639

    
640

    
641
DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break);
642

    
643

    
644
// Message delivered to the message handler callback. This is either a debugger
645
// event or the response to a command.
646
class MessageImpl: public v8::Debug::Message {
647
 public:
648
  // Create a message object for a debug event.
649
  static MessageImpl NewEvent(DebugEvent event,
650
                              bool running,
651
                              Handle<JSObject> exec_state,
652
                              Handle<JSObject> event_data);
653

    
654
  // Create a message object for the response to a debug command.
655
  static MessageImpl NewResponse(DebugEvent event,
656
                                 bool running,
657
                                 Handle<JSObject> exec_state,
658
                                 Handle<JSObject> event_data,
659
                                 Handle<String> response_json,
660
                                 v8::Debug::ClientData* client_data);
661

    
662
  // Implementation of interface v8::Debug::Message.
663
  virtual bool IsEvent() const;
664
  virtual bool IsResponse() const;
665
  virtual DebugEvent GetEvent() const;
666
  virtual bool WillStartRunning() const;
667
  virtual v8::Handle<v8::Object> GetExecutionState() const;
668
  virtual v8::Handle<v8::Object> GetEventData() const;
669
  virtual v8::Handle<v8::String> GetJSON() const;
670
  virtual v8::Handle<v8::Context> GetEventContext() const;
671
  virtual v8::Debug::ClientData* GetClientData() const;
672
  virtual v8::Isolate* GetIsolate() const;
673

    
674
 private:
675
  MessageImpl(bool is_event,
676
              DebugEvent event,
677
              bool running,
678
              Handle<JSObject> exec_state,
679
              Handle<JSObject> event_data,
680
              Handle<String> response_json,
681
              v8::Debug::ClientData* client_data);
682

    
683
  bool is_event_;  // Does this message represent a debug event?
684
  DebugEvent event_;  // Debug event causing the break.
685
  bool running_;  // Will the VM start running after this event?
686
  Handle<JSObject> exec_state_;  // Current execution state.
687
  Handle<JSObject> event_data_;  // Data associated with the event.
688
  Handle<String> response_json_;  // Response JSON if message holds a response.
689
  v8::Debug::ClientData* client_data_;  // Client data passed with the request.
690
};
691

    
692

    
693
// Details of the debug event delivered to the debug event listener.
694
class EventDetailsImpl : public v8::Debug::EventDetails {
695
 public:
696
  EventDetailsImpl(DebugEvent event,
697
                   Handle<JSObject> exec_state,
698
                   Handle<JSObject> event_data,
699
                   Handle<Object> callback_data,
700
                   v8::Debug::ClientData* client_data);
701
  virtual DebugEvent GetEvent() const;
702
  virtual v8::Handle<v8::Object> GetExecutionState() const;
703
  virtual v8::Handle<v8::Object> GetEventData() const;
704
  virtual v8::Handle<v8::Context> GetEventContext() const;
705
  virtual v8::Handle<v8::Value> GetCallbackData() const;
706
  virtual v8::Debug::ClientData* GetClientData() const;
707
 private:
708
  DebugEvent event_;  // Debug event causing the break.
709
  Handle<JSObject> exec_state_;         // Current execution state.
710
  Handle<JSObject> event_data_;         // Data associated with the event.
711
  Handle<Object> callback_data_;        // User data passed with the callback
712
                                        // when it was registered.
713
  v8::Debug::ClientData* client_data_;  // Data passed to DebugBreakForCommand.
714
};
715

    
716

    
717
// Message send by user to v8 debugger or debugger output message.
718
// In addition to command text it may contain a pointer to some user data
719
// which are expected to be passed along with the command reponse to message
720
// handler.
721
class CommandMessage {
722
 public:
723
  static CommandMessage New(const Vector<uint16_t>& command,
724
                            v8::Debug::ClientData* data);
725
  CommandMessage();
726
  ~CommandMessage();
727

    
728
  // Deletes user data and disposes of the text.
729
  void Dispose();
730
  Vector<uint16_t> text() const { return text_; }
731
  v8::Debug::ClientData* client_data() const { return client_data_; }
732
 private:
733
  CommandMessage(const Vector<uint16_t>& text,
734
                 v8::Debug::ClientData* data);
735

    
736
  Vector<uint16_t> text_;
737
  v8::Debug::ClientData* client_data_;
738
};
739

    
740
// A Queue of CommandMessage objects.  A thread-safe version is
741
// LockingCommandMessageQueue, based on this class.
742
class CommandMessageQueue BASE_EMBEDDED {
743
 public:
744
  explicit CommandMessageQueue(int size);
745
  ~CommandMessageQueue();
746
  bool IsEmpty() const { return start_ == end_; }
747
  CommandMessage Get();
748
  void Put(const CommandMessage& message);
749
  void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
750
 private:
751
  // Doubles the size of the message queue, and copies the messages.
752
  void Expand();
753

    
754
  CommandMessage* messages_;
755
  int start_;
756
  int end_;
757
  int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
758
};
759

    
760

    
761
class MessageDispatchHelperThread;
762

    
763

    
764
// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
765
// messages.  The message data is not managed by LockingCommandMessageQueue.
766
// Pointers to the data are passed in and out. Implemented by adding a
767
// Mutex to CommandMessageQueue.  Includes logging of all puts and gets.
768
class LockingCommandMessageQueue BASE_EMBEDDED {
769
 public:
770
  LockingCommandMessageQueue(Logger* logger, int size);
771
  bool IsEmpty() const;
772
  CommandMessage Get();
773
  void Put(const CommandMessage& message);
774
  void Clear();
775
 private:
776
  Logger* logger_;
777
  CommandMessageQueue queue_;
778
  mutable Mutex mutex_;
779
  DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
780
};
781

    
782

    
783
class Debugger {
784
 public:
785
  ~Debugger();
786

    
787
  void DebugRequest(const uint16_t* json_request, int length);
788

    
789
  Handle<Object> MakeJSObject(Vector<const char> constructor_name,
790
                              int argc,
791
                              Handle<Object> argv[],
792
                              bool* caught_exception);
793
  Handle<Object> MakeExecutionState(bool* caught_exception);
794
  Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
795
                                Handle<Object> break_points_hit,
796
                                bool* caught_exception);
797
  Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
798
                                    Handle<Object> exception,
799
                                    bool uncaught,
800
                                    bool* caught_exception);
801
  Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
802
                                      bool* caught_exception);
803
  Handle<Object> MakeCompileEvent(Handle<Script> script,
804
                                  bool before,
805
                                  bool* caught_exception);
806
  Handle<Object> MakeScriptCollectedEvent(int id,
807
                                          bool* caught_exception);
808
  void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
809
  void OnException(Handle<Object> exception, bool uncaught);
810
  void OnBeforeCompile(Handle<Script> script);
811

    
812
  enum AfterCompileFlags {
813
    NO_AFTER_COMPILE_FLAGS,
814
    SEND_WHEN_DEBUGGING
815
  };
816
  void OnAfterCompile(Handle<Script> script,
817
                      AfterCompileFlags after_compile_flags);
818
  void OnScriptCollected(int id);
819
  void ProcessDebugEvent(v8::DebugEvent event,
820
                         Handle<JSObject> event_data,
821
                         bool auto_continue);
822
  void NotifyMessageHandler(v8::DebugEvent event,
823
                            Handle<JSObject> exec_state,
824
                            Handle<JSObject> event_data,
825
                            bool auto_continue);
826
  void SetEventListener(Handle<Object> callback, Handle<Object> data);
827
  void SetMessageHandler(v8::Debug::MessageHandler2 handler);
828
  void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
829
                              TimeDelta period);
830
  void SetDebugMessageDispatchHandler(
831
      v8::Debug::DebugMessageDispatchHandler handler,
832
      bool provide_locker);
833

    
834
  // Invoke the message handler function.
835
  void InvokeMessageHandler(MessageImpl message);
836

    
837
  // Add a debugger command to the command queue.
838
  void ProcessCommand(Vector<const uint16_t> command,
839
                      v8::Debug::ClientData* client_data = NULL);
840

    
841
  // Check whether there are commands in the command queue.
842
  bool HasCommands();
843

    
844
  // Enqueue a debugger command to the command queue for event listeners.
845
  void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
846

    
847
  Handle<Object> Call(Handle<JSFunction> fun,
848
                      Handle<Object> data,
849
                      bool* pending_exception);
850

    
851
  // Start the debugger agent listening on the provided port.
852
  bool StartAgent(const char* name, int port,
853
                  bool wait_for_connection = false);
854

    
855
  // Stop the debugger agent.
856
  void StopAgent();
857

    
858
  // Blocks until the agent has started listening for connections
859
  void WaitForAgent();
860

    
861
  void CallMessageDispatchHandler();
862

    
863
  Handle<Context> GetDebugContext();
864

    
865
  // Unload the debugger if possible. Only called when no debugger is currently
866
  // active.
867
  void UnloadDebugger();
868
  friend void ForceUnloadDebugger();  // In test-debug.cc
869

    
870
  inline bool EventActive(v8::DebugEvent event) {
871
    LockGuard<RecursiveMutex> lock_guard(debugger_access_);
872

    
873
    // Check whether the message handler was been cleared.
874
    if (debugger_unload_pending_) {
875
      if (isolate_->debug()->debugger_entry() == NULL) {
876
        UnloadDebugger();
877
      }
878
    }
879

    
880
    if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) &&
881
        !FLAG_debug_compile_events) {
882
      return false;
883

    
884
    } else if ((event == v8::ScriptCollected) &&
885
               !FLAG_debug_script_collected_events) {
886
      return false;
887
    }
888

    
889
    // Currently argument event is not used.
890
    return !compiling_natives_ && Debugger::IsDebuggerActive();
891
  }
892

    
893
  void set_compiling_natives(bool compiling_natives) {
894
    compiling_natives_ = compiling_natives;
895
  }
896
  bool compiling_natives() const { return compiling_natives_; }
897
  void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
898
  bool is_loading_debugger() const { return is_loading_debugger_; }
899
  void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
900
  bool live_edit_enabled() const {
901
    return FLAG_enable_liveedit && live_edit_enabled_ ;
902
  }
903
  void set_force_debugger_active(bool force_debugger_active) {
904
    force_debugger_active_ = force_debugger_active;
905
  }
906
  bool force_debugger_active() const { return force_debugger_active_; }
907

    
908
  bool IsDebuggerActive();
909

    
910
 private:
911
  explicit Debugger(Isolate* isolate);
912

    
913
  void CallEventCallback(v8::DebugEvent event,
914
                         Handle<Object> exec_state,
915
                         Handle<Object> event_data,
916
                         v8::Debug::ClientData* client_data);
917
  void CallCEventCallback(v8::DebugEvent event,
918
                          Handle<Object> exec_state,
919
                          Handle<Object> event_data,
920
                          v8::Debug::ClientData* client_data);
921
  void CallJSEventCallback(v8::DebugEvent event,
922
                           Handle<Object> exec_state,
923
                           Handle<Object> event_data);
924
  void ListenersChanged();
925

    
926
  RecursiveMutex* debugger_access_;  // Mutex guarding debugger variables.
927
  Handle<Object> event_listener_;  // Global handle to listener.
928
  Handle<Object> event_listener_data_;
929
  bool compiling_natives_;  // Are we compiling natives?
930
  bool is_loading_debugger_;  // Are we loading the debugger?
931
  bool live_edit_enabled_;  // Enable LiveEdit.
932
  bool never_unload_debugger_;  // Can we unload the debugger?
933
  bool force_debugger_active_;  // Activate debugger without event listeners.
934
  v8::Debug::MessageHandler2 message_handler_;
935
  bool debugger_unload_pending_;  // Was message handler cleared?
936
  v8::Debug::HostDispatchHandler host_dispatch_handler_;
937
  Mutex dispatch_handler_access_;  // Mutex guarding dispatch handler.
938
  v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
939
  MessageDispatchHelperThread* message_dispatch_helper_thread_;
940
  TimeDelta host_dispatch_period_;
941

    
942
  DebuggerAgent* agent_;
943

    
944
  static const int kQueueInitialSize = 4;
945
  LockingCommandMessageQueue command_queue_;
946
  Semaphore command_received_;  // Signaled for each command received.
947
  LockingCommandMessageQueue event_command_queue_;
948

    
949
  Isolate* isolate_;
950

    
951
  friend class EnterDebugger;
952
  friend class Isolate;
953

    
954
  DISALLOW_COPY_AND_ASSIGN(Debugger);
955
};
956

    
957

    
958
// This class is used for entering the debugger. Create an instance in the stack
959
// to enter the debugger. This will set the current break state, make sure the
960
// debugger is loaded and switch to the debugger context. If the debugger for
961
// some reason could not be entered FailedToEnter will return true.
962
class EnterDebugger BASE_EMBEDDED {
963
 public:
964
  explicit EnterDebugger(Isolate* isolate);
965
  ~EnterDebugger();
966

    
967
  // Check whether the debugger could be entered.
968
  inline bool FailedToEnter() { return load_failed_; }
969

    
970
  // Check whether there are any JavaScript frames on the stack.
971
  inline bool HasJavaScriptFrames() { return has_js_frames_; }
972

    
973
  // Get the active context from before entering the debugger.
974
  inline Handle<Context> GetContext() { return save_.context(); }
975

    
976
 private:
977
  Isolate* isolate_;
978
  EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
979
  JavaScriptFrameIterator it_;
980
  const bool has_js_frames_;  // Were there any JavaScript frames?
981
  StackFrame::Id break_frame_id_;  // Previous break frame id.
982
  int break_id_;  // Previous break id.
983
  bool load_failed_;  // Did the debugger fail to load?
984
  SaveContext save_;  // Saves previous context.
985
};
986

    
987

    
988
// Stack allocated class for disabling break.
989
class DisableBreak BASE_EMBEDDED {
990
 public:
991
  explicit DisableBreak(Isolate* isolate, bool disable_break)
992
    : isolate_(isolate) {
993
    prev_disable_break_ = isolate_->debug()->disable_break();
994
    isolate_->debug()->set_disable_break(disable_break);
995
  }
996
  ~DisableBreak() {
997
    isolate_->debug()->set_disable_break(prev_disable_break_);
998
  }
999

    
1000
 private:
1001
  Isolate* isolate_;
1002
  // The previous state of the disable break used to restore the value when this
1003
  // object is destructed.
1004
  bool prev_disable_break_;
1005
};
1006

    
1007

    
1008
// Debug_Address encapsulates the Address pointers used in generating debug
1009
// code.
1010
class Debug_Address {
1011
 public:
1012
  explicit Debug_Address(Debug::AddressId id) : id_(id) { }
1013

    
1014
  static Debug_Address AfterBreakTarget() {
1015
    return Debug_Address(Debug::k_after_break_target_address);
1016
  }
1017

    
1018
  static Debug_Address DebugBreakReturn() {
1019
    return Debug_Address(Debug::k_debug_break_return_address);
1020
  }
1021

    
1022
  static Debug_Address RestarterFrameFunctionPointer() {
1023
    return Debug_Address(Debug::k_restarter_frame_function_pointer);
1024
  }
1025

    
1026
  Address address(Isolate* isolate) const {
1027
    Debug* debug = isolate->debug();
1028
    switch (id_) {
1029
      case Debug::k_after_break_target_address:
1030
        return reinterpret_cast<Address>(debug->after_break_target_address());
1031
      case Debug::k_debug_break_return_address:
1032
        return reinterpret_cast<Address>(debug->debug_break_return_address());
1033
      case Debug::k_debug_break_slot_address:
1034
        return reinterpret_cast<Address>(debug->debug_break_slot_address());
1035
      case Debug::k_restarter_frame_function_pointer:
1036
        return reinterpret_cast<Address>(
1037
            debug->restarter_frame_function_pointer_address());
1038
      default:
1039
        UNREACHABLE();
1040
        return NULL;
1041
    }
1042
  }
1043

    
1044
 private:
1045
  Debug::AddressId id_;
1046
};
1047

    
1048
// The optional thread that Debug Agent may use to temporary call V8 to process
1049
// pending debug requests if debuggee is not running V8 at the moment.
1050
// Techincally it does not call V8 itself, rather it asks embedding program
1051
// to do this via v8::Debug::HostDispatchHandler
1052
class MessageDispatchHelperThread: public Thread {
1053
 public:
1054
  explicit MessageDispatchHelperThread(Isolate* isolate);
1055
  ~MessageDispatchHelperThread() {}
1056

    
1057
  void Schedule();
1058

    
1059
 private:
1060
  void Run();
1061

    
1062
  Isolate* isolate_;
1063
  Semaphore sem_;
1064
  Mutex mutex_;
1065
  bool already_signalled_;
1066

    
1067
  DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
1068
};
1069

    
1070

    
1071
} }  // namespace v8::internal
1072

    
1073
#endif  // ENABLE_DEBUGGER_SUPPORT
1074

    
1075
#endif  // V8_DEBUG_H_