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 @ 40c0f755

History | View | Annotate | Download (24.8 KB)

1 40c0f755 Ryan
// 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_V8_DEBUG_H_
29
#define V8_V8_DEBUG_H_
30
31
#include "../include/v8-debug.h"
32
#include "assembler.h"
33
#include "code-stubs.h"
34
#include "debug-agent.h"
35
#include "execution.h"
36
#include "factory.h"
37
#include "platform.h"
38
#include "string-stream.h"
39
#include "v8threads.h"
40
41
42
namespace v8 { namespace internal {
43
44
45
// Forward declarations.
46
class EnterDebugger;
47
48
49
// Step actions. NOTE: These values are in macros.py as well.
50
enum StepAction {
51
  StepNone = -1,  // Stepping not prepared.
52
  StepOut = 0,   // Step out of the current function.
53
  StepNext = 1,  // Step to the next statement in the current function.
54
  StepIn = 2,    // Step into new functions invoked or the next statement
55
                 // in the current function.
56
  StepMin = 3,   // Perform a minimum step in the current function.
57
  StepInMin = 4  // Step into new functions invoked or perform a minimum step
58
                 // in the current function.
59
};
60
61
62
// Type of exception break. NOTE: These values are in macros.py as well.
63
enum ExceptionBreakType {
64
  BreakException = 0,
65
  BreakUncaughtException = 1
66
};
67
68
69
// Type of exception break. NOTE: These values are in macros.py as well.
70
enum BreakLocatorType {
71
  ALL_BREAK_LOCATIONS = 0,
72
  SOURCE_BREAK_LOCATIONS = 1
73
};
74
75
76
// Class for iterating through the break points in a function and changing
77
// them.
78
class BreakLocationIterator {
79
 public:
80
  explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
81
                                 BreakLocatorType type);
82
  virtual ~BreakLocationIterator();
83
84
  void Next();
85
  void Next(int count);
86
  void FindBreakLocationFromAddress(Address pc);
87
  void FindBreakLocationFromPosition(int position);
88
  void Reset();
89
  bool Done() const;
90
  void SetBreakPoint(Handle<Object> break_point_object);
91
  void ClearBreakPoint(Handle<Object> break_point_object);
92
  void SetOneShot();
93
  void ClearOneShot();
94
  void PrepareStepIn();
95
  bool IsExit() const;
96
  bool HasBreakPoint();
97
  bool IsDebugBreak();
98
  Object* BreakPointObjects();
99
  void ClearAllDebugBreak();
100
101
102
  inline int code_position() { return pc() - debug_info_->code()->entry(); }
103
  inline int break_point() { return break_point_; }
104
  inline int position() { return position_; }
105
  inline int statement_position() { return statement_position_; }
106
  inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
107
  inline Code* code() { return debug_info_->code(); }
108
  inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
109
  inline RelocInfo::Mode rmode() const {
110
    return reloc_iterator_->rinfo()->rmode();
111
  }
112
  inline RelocInfo* original_rinfo() {
113
    return reloc_iterator_original_->rinfo();
114
  }
115
  inline RelocInfo::Mode original_rmode() const {
116
    return reloc_iterator_original_->rinfo()->rmode();
117
  }
118
119
 protected:
120
  bool RinfoDone() const;
121
  void RinfoNext();
122
123
  BreakLocatorType type_;
124
  int break_point_;
125
  int position_;
126
  int statement_position_;
127
  Handle<DebugInfo> debug_info_;
128
  RelocIterator* reloc_iterator_;
129
  RelocIterator* reloc_iterator_original_;
130
131
 private:
132
  void SetDebugBreak();
133
  void ClearDebugBreak();
134
  bool IsDebugBreakAtReturn();
135
  void SetDebugBreakAtReturn();
136
  void ClearDebugBreakAtReturn();
137
138
  DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
139
};
140
141
142
// Linked list holding debug info objects. The debug info objects are kept as
143
// weak handles to avoid a debug info object to keep a function alive.
144
class DebugInfoListNode {
145
 public:
146
  explicit DebugInfoListNode(DebugInfo* debug_info);
147
  virtual ~DebugInfoListNode();
148
149
  DebugInfoListNode* next() { return next_; }
150
  void set_next(DebugInfoListNode* next) { next_ = next; }
151
  Handle<DebugInfo> debug_info() { return debug_info_; }
152
153
 private:
154
  // Global (weak) handle to the debug info object.
155
  Handle<DebugInfo> debug_info_;
156
157
  // Next pointer for linked list.
158
  DebugInfoListNode* next_;
159
};
160
161
162
// This class contains the debugger support. The main purpose is to handle
163
// setting break points in the code.
164
//
165
// This class controls the debug info for all functions which currently have
166
// active breakpoints in them. This debug info is held in the heap root object
167
// debug_info which is a FixedArray. Each entry in this list is of class
168
// DebugInfo.
169
class Debug {
170
 public:
171
  static void Setup(bool create_heap_objects);
172
  static bool Load();
173
  static void Unload();
174
  static bool IsLoaded() { return !debug_context_.is_null(); }
175
  static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
176
  static void PreemptionWhileInDebugger();
177
  static void Iterate(ObjectVisitor* v);
178
179
  static Object* Break(Arguments args);
180
  static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
181
                            int source_position,
182
                            Handle<Object> break_point_object);
183
  static void ClearBreakPoint(Handle<Object> break_point_object);
184
  static void ClearAllBreakPoints();
185
  static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
186
  static void FloodHandlerWithOneShot();
187
  static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
188
  static void PrepareStep(StepAction step_action, int step_count);
189
  static void ClearStepping();
190
  static bool StepNextContinue(BreakLocationIterator* break_location_iterator,
191
                               JavaScriptFrame* frame);
192
  static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
193
  static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
194
195
  // Returns whether the operation succeeded.
196
  static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
197
198
  static bool IsDebugBreak(Address addr);
199
  static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
200
201
  // Check whether a code stub with the specified major key is a possible break
202
  // point location.
203
  static bool IsSourceBreakStub(Code* code);
204
  static bool IsBreakStub(Code* code);
205
206
  // Find the builtin to use for invoking the debug break
207
  static Handle<Code> FindDebugBreak(RelocInfo* rinfo);
208
209
  static Handle<Object> GetSourceBreakLocations(
210
      Handle<SharedFunctionInfo> shared);
211
212
  // Getter for the debug_context.
213
  inline static Handle<Context> debug_context() { return debug_context_; }
214
215
  // Check whether a global object is the debug global object.
216
  static bool IsDebugGlobal(GlobalObject* global);
217
218
  // Fast check to see if any break points are active.
219
  inline static bool has_break_points() { return has_break_points_; }
220
221
  static void NewBreak(StackFrame::Id break_frame_id);
222
  static void SetBreak(StackFrame::Id break_frame_id, int break_id);
223
  static StackFrame::Id break_frame_id() {
224
    return thread_local_.break_frame_id_;
225
  }
226
  static int break_id() { return thread_local_.break_id_; }
227
228
229
230
231
  static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
232
  static void HandleStepIn(Handle<JSFunction> function,
233
                           Address fp,
234
                           bool is_constructor);
235
  static Address step_in_fp() { return thread_local_.step_into_fp_; }
236
  static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
237
238
  static EnterDebugger* debugger_entry() {
239
    return thread_local_.debugger_entry_;
240
  }
241
  static void set_debugger_entry(EnterDebugger* entry) {
242
    thread_local_.debugger_entry_ = entry;
243
  }
244
245
  static bool preemption_pending() {
246
    return thread_local_.preemption_pending_;
247
  }
248
  static void set_preemption_pending(bool preemption_pending) {
249
    thread_local_.preemption_pending_ = preemption_pending;
250
  }
251
252
  // Getter and setter for the disable break state.
253
  static bool disable_break() { return disable_break_; }
254
  static void set_disable_break(bool disable_break) {
255
    disable_break_ = disable_break;
256
  }
257
258
  // Getters for the current exception break state.
259
  static bool break_on_exception() { return break_on_exception_; }
260
  static bool break_on_uncaught_exception() {
261
    return break_on_uncaught_exception_;
262
  }
263
264
  enum AddressId {
265
    k_after_break_target_address,
266
    k_debug_break_return_address,
267
    k_register_address
268
  };
269
270
  // Support for setting the address to jump to when returning from break point.
271
  static Address* after_break_target_address() {
272
    return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
273
  }
274
275
  // Support for saving/restoring registers when handling debug break calls.
276
  static Object** register_address(int r) {
277
    return &registers_[r];
278
  }
279
280
  // Address of the debug break return entry code.
281
  static Code* debug_break_return_entry() { return debug_break_return_entry_; }
282
283
  // Support for getting the address of the debug break on return code.
284
  static Code** debug_break_return_address() {
285
    return &debug_break_return_;
286
  }
287
288
  static const int kEstimatedNofDebugInfoEntries = 16;
289
  static const int kEstimatedNofBreakPointsInFunction = 16;
290
291
  static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
292
293
  friend class Debugger;
294
  friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
295
  friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
296
297
  // Threading support.
298
  static char* ArchiveDebug(char* to);
299
  static char* RestoreDebug(char* from);
300
  static int ArchiveSpacePerThread();
301
302
  // Mirror cache handling.
303
  static void ClearMirrorCache();
304
305
  // Code generation assumptions.
306
  static const int kIa32CallInstructionLength = 5;
307
  static const int kIa32JSReturnSequenceLength = 6;
308
309
  // Code generator routines.
310
  static void GenerateLoadICDebugBreak(MacroAssembler* masm);
311
  static void GenerateStoreICDebugBreak(MacroAssembler* masm);
312
  static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
313
  static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
314
  static void GenerateConstructCallDebugBreak(MacroAssembler* masm);
315
  static void GenerateReturnDebugBreak(MacroAssembler* masm);
316
  static void GenerateReturnDebugBreakEntry(MacroAssembler* masm);
317
  static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
318
319
  // Called from stub-cache.cc.
320
  static void GenerateCallICDebugBreak(MacroAssembler* masm);
321
322
 private:
323
  static bool CompileDebuggerScript(int index);
324
  static void ClearOneShot();
325
  static void ActivateStepIn(StackFrame* frame);
326
  static void ClearStepIn();
327
  static void ClearStepNext();
328
  // Returns whether the compile succeeded.
329
  static bool EnsureCompiled(Handle<SharedFunctionInfo> shared);
330
  static void RemoveDebugInfo(Handle<DebugInfo> debug_info);
331
  static void SetAfterBreakTarget(JavaScriptFrame* frame);
332
  static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
333
  static bool CheckBreakPoint(Handle<Object> break_point_object);
334
335
  // Global handle to debug context where all the debugger JavaScript code is
336
  // loaded.
337
  static Handle<Context> debug_context_;
338
339
  // Boolean state indicating whether any break points are set.
340
  static bool has_break_points_;
341
  static DebugInfoListNode* debug_info_list_;
342
343
  static bool disable_break_;
344
  static bool break_on_exception_;
345
  static bool break_on_uncaught_exception_;
346
347
  // Per-thread data.
348
  class ThreadLocal {
349
   public:
350
    // Counter for generating next break id.
351
    int break_count_;
352
353
    // Current break id.
354
    int break_id_;
355
356
    // Frame id for the frame of the current break.
357
    StackFrame::Id break_frame_id_;
358
359
    // Step action for last step performed.
360
    StepAction last_step_action_;
361
362
    // Source statement position from last step next action.
363
    int last_statement_position_;
364
365
    // Number of steps left to perform before debug event.
366
    int step_count_;
367
368
    // Frame pointer from last step next action.
369
    Address last_fp_;
370
371
    // Frame pointer for frame from which step in was performed.
372
    Address step_into_fp_;
373
374
    // Storage location for jump when exiting debug break calls.
375
    Address after_break_target_;
376
377
    // Top debugger entry.
378
    EnterDebugger* debugger_entry_;
379
380
    // Preemption happened while debugging.
381
    bool preemption_pending_;
382
  };
383
384
  // Storage location for registers when handling debug break calls
385
  static JSCallerSavedBuffer registers_;
386
  static ThreadLocal thread_local_;
387
  static void ThreadInit();
388
389
  // Code object for debug break return entry code.
390
  static Code* debug_break_return_entry_;
391
392
  // Code to call for handling debug break on return.
393
  static Code* debug_break_return_;
394
395
  DISALLOW_COPY_AND_ASSIGN(Debug);
396
};
397
398
399
// A Queue of Vector<uint16_t> objects.  A thread-safe version is
400
// LockingMessageQueue, based on this class.
401
class MessageQueue BASE_EMBEDDED {
402
 public:
403
  explicit MessageQueue(int size);
404
  ~MessageQueue();
405
  bool IsEmpty() const { return start_ == end_; }
406
  Vector<uint16_t> Get();
407
  void Put(const Vector<uint16_t>& message);
408
  void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
409
 private:
410
  // Doubles the size of the message queue, and copies the messages.
411
  void Expand();
412
413
  Vector<uint16_t>* messages_;
414
  int start_;
415
  int end_;
416
  int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
417
};
418
419
420
// LockingMessageQueue is a thread-safe circular buffer of Vector<uint16_t>
421
// messages.  The message data is not managed by LockingMessageQueue.
422
// Pointers to the data are passed in and out. Implemented by adding a
423
// Mutex to MessageQueue.  Includes logging of all puts and gets.
424
class LockingMessageQueue BASE_EMBEDDED {
425
 public:
426
  explicit LockingMessageQueue(int size);
427
  ~LockingMessageQueue();
428
  bool IsEmpty() const;
429
  Vector<uint16_t> Get();
430
  void Put(const Vector<uint16_t>& message);
431
  void Clear();
432
 private:
433
  MessageQueue queue_;
434
  Mutex* lock_;
435
  DISALLOW_COPY_AND_ASSIGN(LockingMessageQueue);
436
};
437
438
439
class DebugMessageThread;
440
441
class Debugger {
442
 public:
443
  static void DebugRequest(const uint16_t* json_request, int length);
444
445
  static Handle<Object> MakeJSObject(Vector<const char> constructor_name,
446
                                     int argc, Object*** argv,
447
                                     bool* caught_exception);
448
  static Handle<Object> MakeExecutionState(bool* caught_exception);
449
  static Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
450
                                       Handle<Object> break_points_hit,
451
                                       bool* caught_exception);
452
  static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
453
                                           Handle<Object> exception,
454
                                           bool uncaught,
455
                                           bool* caught_exception);
456
  static Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
457
                                             bool* caught_exception);
458
  static Handle<Object> MakeCompileEvent(Handle<Script> script,
459
                                         bool before,
460
                                         bool* caught_exception);
461
  static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
462
  static void OnException(Handle<Object> exception, bool uncaught);
463
  static void OnBeforeCompile(Handle<Script> script);
464
  static void OnAfterCompile(Handle<Script> script,
465
                           Handle<JSFunction> fun);
466
  static void OnNewFunction(Handle<JSFunction> fun);
467
  static void ProcessDebugEvent(v8::DebugEvent event,
468
                                Handle<Object> event_data,
469
                                bool auto_continue);
470
  static void NotifyMessageHandler(v8::DebugEvent event,
471
                                   Handle<Object> exec_state,
472
                                   Handle<Object> event_data,
473
                                   bool auto_continue);
474
  static void SetEventListener(Handle<Object> callback, Handle<Object> data);
475
  static void SetMessageHandler(v8::DebugMessageHandler handler, void* data,
476
                                bool message_handler_thread);
477
  static void TearDown();
478
  static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
479
                                     void* data);
480
481
  // Invoke the message handler function.
482
  static void InvokeMessageHandler(Vector< uint16_t> message);
483
484
  // Send a message to the message handler eiher through the message thread or
485
  // directly.
486
  static void SendMessage(Vector<uint16_t> message);
487
488
  // Send the JSON message for a debug event.
489
  static bool SendEventMessage(Handle<Object> event_data);
490
491
  // Add a debugger command to the command queue.
492
  static void ProcessCommand(Vector<const uint16_t> command);
493
494
  // Check whether there are commands in the command queue.
495
  static bool HasCommands();
496
497
  static void ProcessHostDispatch(void* dispatch);
498
  static Handle<Object> Call(Handle<JSFunction> fun,
499
                             Handle<Object> data,
500
                             bool* pending_exception);
501
502
  // Start the debugger agent listening on the provided port.
503
  static bool StartAgent(const char* name, int port);
504
505
  // Stop the debugger agent.
506
  static void StopAgent();
507
508
  // Unload the debugger if possible. Only called when no debugger is currently
509
  // active.
510
  static void UnloadDebugger();
511
512
  inline static bool EventActive(v8::DebugEvent event) {
513
    ScopedLock with(debugger_access_);
514
515
    // Check whether the message handler was been cleared.
516
    if (message_handler_cleared_) {
517
      UnloadDebugger();
518
    }
519
520
    // Currently argument event is not used.
521
    return !compiling_natives_ && Debugger::IsDebuggerActive();
522
  }
523
524
  static void set_compiling_natives(bool compiling_natives) {
525
    Debugger::compiling_natives_ = compiling_natives;
526
  }
527
  static bool compiling_natives() { return Debugger::compiling_natives_; }
528
  static void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
529
  static bool is_loading_debugger() { return Debugger::is_loading_debugger_; }
530
531
 private:
532
  static bool IsDebuggerActive();
533
534
  static Mutex* debugger_access_;  // Mutex guarding debugger variables.
535
  static Handle<Object> event_listener_;  // Global handle to listener.
536
  static Handle<Object> event_listener_data_;
537
  static bool compiling_natives_;  // Are we compiling natives?
538
  static bool is_loading_debugger_;  // Are we loading the debugger?
539
  static bool never_unload_debugger_;  // Can we unload the debugger?
540
  static DebugMessageThread* message_thread_;
541
  static v8::DebugMessageHandler message_handler_;
542
  static bool message_handler_cleared_;  // Was message handler cleared?
543
  static void* message_handler_data_;
544
  static v8::DebugHostDispatchHandler host_dispatch_handler_;
545
  static void* host_dispatch_handler_data_;
546
547
  static DebuggerAgent* agent_;
548
549
  static const int kQueueInitialSize = 4;
550
  static LockingMessageQueue command_queue_;
551
  static LockingMessageQueue message_queue_;
552
  static Semaphore* command_received_;  // Signaled for each command received.
553
  static Semaphore* message_received_;  // Signalled for each message send.
554
555
  friend class EnterDebugger;
556
  friend class DebugMessageThread;
557
};
558
559
560
// Thread to read messages from the message queue and invoke the debug message
561
// handler in another thread as the V8 thread. This thread is started if the
562
// registration of the debug message handler requested to be called in a thread
563
// seperate from the V8 thread.
564
class DebugMessageThread: public Thread {
565
 public:
566
  DebugMessageThread() : keep_running_(true) {}
567
  virtual ~DebugMessageThread() {}
568
569
  // Main function of DebugMessageThread thread.
570
  void Run();
571
  void Stop();
572
573
 private:
574
  bool keep_running_;
575
  DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
576
};
577
578
579
// This class is used for entering the debugger. Create an instance in the stack
580
// to enter the debugger. This will set the current break state, make sure the
581
// debugger is loaded and switch to the debugger context. If the debugger for
582
// some reason could not be entered FailedToEnter will return true.
583
class EnterDebugger BASE_EMBEDDED {
584
 public:
585
  EnterDebugger()
586
      : prev_(Debug::debugger_entry()),
587
        has_js_frames_(!it_.done()) {
588
    ASSERT(prev_ == NULL ? !Debug::preemption_pending() : true);
589
590
    // Link recursive debugger entry.
591
    Debug::set_debugger_entry(this);
592
593
    // Store the previous break id and frame id.
594
    break_id_ = Debug::break_id();
595
    break_frame_id_ = Debug::break_frame_id();
596
597
    // Create the new break info. If there is no JavaScript frames there is no
598
    // break frame id.
599
    if (has_js_frames_) {
600
      Debug::NewBreak(it_.frame()->id());
601
    } else {
602
      Debug::NewBreak(StackFrame::NO_ID);
603
    }
604
605
    // Make sure that debugger is loaded and enter the debugger context.
606
    load_failed_ = !Debug::Load();
607
    if (!load_failed_) {
608
      // NOTE the member variable save which saves the previous context before
609
      // this change.
610
      Top::set_context(*Debug::debug_context());
611
    }
612
  }
613
614
  ~EnterDebugger() {
615
    // Restore to the previous break state.
616
    Debug::SetBreak(break_frame_id_, break_id_);
617
618
    // Request preemption when leaving the last debugger entry and a preemption
619
    // had been recorded while debugging. This is to avoid starvation in some
620
    // debugging scenarios.
621
    if (prev_ == NULL && Debug::preemption_pending()) {
622
      StackGuard::Preempt();
623
      Debug::set_preemption_pending(false);
624
    }
625
626
    // If there are commands in the queue when leaving the debugger request that
627
    // these commands are processed.
628
    if (prev_ == NULL && Debugger::HasCommands()) {
629
      StackGuard::DebugCommand();
630
    }
631
632
    // If leaving the debugger with the debugger no longer active unload it.
633
    if (prev_ == NULL) {
634
      if (!Debugger::IsDebuggerActive()) {
635
        Debugger::UnloadDebugger();
636
      }
637
    }
638
639
    // Leaving this debugger entry.
640
    Debug::set_debugger_entry(prev_);
641
  }
642
643
  // Check whether the debugger could be entered.
644
  inline bool FailedToEnter() { return load_failed_; }
645
646
  // Check whether there are any JavaScript frames on the stack.
647
  inline bool HasJavaScriptFrames() { return has_js_frames_; }
648
649
 private:
650
  EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
651
  JavaScriptFrameIterator it_;
652
  const bool has_js_frames_;  // Were there any JavaScript frames?
653
  StackFrame::Id break_frame_id_;  // Previous break frame id.
654
  int break_id_;  // Previous break id.
655
  bool load_failed_;  // Did the debugger fail to load?
656
  SaveContext save_;  // Saves previous context.
657
};
658
659
660
// Stack allocated class for disabling break.
661
class DisableBreak BASE_EMBEDDED {
662
 public:
663
  // Enter the debugger by storing the previous top context and setting the
664
  // current top context to the debugger context.
665
  explicit DisableBreak(bool disable_break)  {
666
    prev_disable_break_ = Debug::disable_break();
667
    Debug::set_disable_break(disable_break);
668
  }
669
  ~DisableBreak() {
670
    Debug::set_disable_break(prev_disable_break_);
671
  }
672
673
 private:
674
  // The previous state of the disable break used to restore the value when this
675
  // object is destructed.
676
  bool prev_disable_break_;
677
};
678
679
680
// Debug_Address encapsulates the Address pointers used in generating debug
681
// code.
682
class Debug_Address {
683
 public:
684
  Debug_Address(Debug::AddressId id, int reg = 0)
685
    : id_(id), reg_(reg) {
686
    ASSERT(reg == 0 || id == Debug::k_register_address);
687
  }
688
689
  static Debug_Address AfterBreakTarget() {
690
    return Debug_Address(Debug::k_after_break_target_address);
691
  }
692
693
  static Debug_Address DebugBreakReturn() {
694
    return Debug_Address(Debug::k_debug_break_return_address);
695
  }
696
697
  static Debug_Address Register(int reg) {
698
    return Debug_Address(Debug::k_register_address, reg);
699
  }
700
701
  Address address() const {
702
    switch (id_) {
703
      case Debug::k_after_break_target_address:
704
        return reinterpret_cast<Address>(Debug::after_break_target_address());
705
      case Debug::k_debug_break_return_address:
706
        return reinterpret_cast<Address>(Debug::debug_break_return_address());
707
      case Debug::k_register_address:
708
        return reinterpret_cast<Address>(Debug::register_address(reg_));
709
      default:
710
        UNREACHABLE();
711
        return NULL;
712
    }
713
  }
714
 private:
715
  Debug::AddressId id_;
716
  int reg_;
717
};
718
719
720
} }  // namespace v8::internal
721
722
#endif  // V8_V8_DEBUG_H_