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
// 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_