blob: a098040c0dfefd5c5ebc84660f39f0638cb1de65 [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Steve Block44f0eee2011-05-26 01:26:41 +010032#include "arguments.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033#include "assembler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "debug-agent.h"
35#include "execution.h"
36#include "factory.h"
Ben Murdoch086aeea2011-05-13 15:57:08 +010037#include "flags.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000038#include "frames-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "hashmap.h"
40#include "platform.h"
41#include "string-stream.h"
42#include "v8threads.h"
43
44#ifdef ENABLE_DEBUGGER_SUPPORT
45#include "../include/v8-debug.h"
46
47namespace v8 {
48namespace internal {
49
50
51// Forward declarations.
52class EnterDebugger;
53
54
55// Step actions. NOTE: These values are in macros.py as well.
56enum StepAction {
57 StepNone = -1, // Stepping not prepared.
58 StepOut = 0, // Step out of the current function.
59 StepNext = 1, // Step to the next statement in the current function.
60 StepIn = 2, // Step into new functions invoked or the next statement
61 // in the current function.
62 StepMin = 3, // Perform a minimum step in the current function.
63 StepInMin = 4 // Step into new functions invoked or perform a minimum step
64 // in the current function.
65};
66
67
68// Type of exception break. NOTE: These values are in macros.py as well.
69enum ExceptionBreakType {
70 BreakException = 0,
71 BreakUncaughtException = 1
72};
73
74
75// Type of exception break. NOTE: These values are in macros.py as well.
76enum BreakLocatorType {
77 ALL_BREAK_LOCATIONS = 0,
78 SOURCE_BREAK_LOCATIONS = 1
79};
80
81
82// Class for iterating through the break points in a function and changing
83// them.
84class BreakLocationIterator {
85 public:
86 explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
87 BreakLocatorType type);
88 virtual ~BreakLocationIterator();
89
90 void Next();
91 void Next(int count);
92 void FindBreakLocationFromAddress(Address pc);
93 void FindBreakLocationFromPosition(int position);
94 void Reset();
95 bool Done() const;
96 void SetBreakPoint(Handle<Object> break_point_object);
97 void ClearBreakPoint(Handle<Object> break_point_object);
98 void SetOneShot();
99 void ClearOneShot();
100 void PrepareStepIn();
101 bool IsExit() const;
102 bool HasBreakPoint();
103 bool IsDebugBreak();
104 Object* BreakPointObjects();
105 void ClearAllDebugBreak();
106
107
Steve Blockd0582a62009-12-15 09:54:21 +0000108 inline int code_position() {
109 return static_cast<int>(pc() - debug_info_->code()->entry());
110 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 inline int break_point() { return break_point_; }
112 inline int position() { return position_; }
113 inline int statement_position() { return statement_position_; }
114 inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
115 inline Code* code() { return debug_info_->code(); }
116 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
117 inline RelocInfo::Mode rmode() const {
118 return reloc_iterator_->rinfo()->rmode();
119 }
120 inline RelocInfo* original_rinfo() {
121 return reloc_iterator_original_->rinfo();
122 }
123 inline RelocInfo::Mode original_rmode() const {
124 return reloc_iterator_original_->rinfo()->rmode();
125 }
126
127 bool IsDebuggerStatement();
128
129 protected:
130 bool RinfoDone() const;
131 void RinfoNext();
132
133 BreakLocatorType type_;
134 int break_point_;
135 int position_;
136 int statement_position_;
137 Handle<DebugInfo> debug_info_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000138 RelocIterator* reloc_iterator_;
139 RelocIterator* reloc_iterator_original_;
140
141 private:
142 void SetDebugBreak();
143 void ClearDebugBreak();
144
145 void SetDebugBreakAtIC();
146 void ClearDebugBreakAtIC();
147
148 bool IsDebugBreakAtReturn();
149 void SetDebugBreakAtReturn();
150 void ClearDebugBreakAtReturn();
151
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100152 bool IsDebugBreakSlot();
153 bool IsDebugBreakAtSlot();
154 void SetDebugBreakAtSlot();
155 void ClearDebugBreakAtSlot();
156
Steve Blocka7e24c12009-10-30 11:49:00 +0000157 DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
158};
159
160
161// Cache of all script objects in the heap. When a script is added a weak handle
162// to it is created and that weak handle is stored in the cache. The weak handle
163// callback takes care of removing the script from the cache. The key used in
164// the cache is the script id.
165class ScriptCache : private HashMap {
166 public:
167 ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {}
168 virtual ~ScriptCache() { Clear(); }
169
170 // Add script to the cache.
171 void Add(Handle<Script> script);
172
173 // Return the scripts in the cache.
174 Handle<FixedArray> GetScripts();
175
176 // Generate debugger events for collected scripts.
177 void ProcessCollectedScripts();
178
179 private:
180 // Calculate the hash value from the key (script id).
181 static uint32_t Hash(int key) { return ComputeIntegerHash(key); }
182
183 // Scripts match if their keys (script id) match.
184 static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
185
186 // Clear the cache releasing all the weak handles.
187 void Clear();
188
189 // Weak handle callback for scripts in the cache.
190 static void HandleWeakScript(v8::Persistent<v8::Value> obj, void* data);
191
192 // List used during GC to temporarily store id's of collected scripts.
193 List<int> collected_scripts_;
194};
195
196
197// Linked list holding debug info objects. The debug info objects are kept as
198// weak handles to avoid a debug info object to keep a function alive.
199class DebugInfoListNode {
200 public:
201 explicit DebugInfoListNode(DebugInfo* debug_info);
202 virtual ~DebugInfoListNode();
203
204 DebugInfoListNode* next() { return next_; }
205 void set_next(DebugInfoListNode* next) { next_ = next; }
206 Handle<DebugInfo> debug_info() { return debug_info_; }
207
208 private:
209 // Global (weak) handle to the debug info object.
210 Handle<DebugInfo> debug_info_;
211
212 // Next pointer for linked list.
213 DebugInfoListNode* next_;
214};
215
Steve Blocka7e24c12009-10-30 11:49:00 +0000216// This class contains the debugger support. The main purpose is to handle
217// setting break points in the code.
218//
219// This class controls the debug info for all functions which currently have
220// active breakpoints in them. This debug info is held in the heap root object
221// debug_info which is a FixedArray. Each entry in this list is of class
222// DebugInfo.
223class Debug {
224 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100225 void Setup(bool create_heap_objects);
226 bool Load();
227 void Unload();
228 bool IsLoaded() { return !debug_context_.is_null(); }
229 bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
230 void PreemptionWhileInDebugger();
231 void Iterate(ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232
Ben Murdoch8b112d22011-06-08 16:22:53 +0100233 Object* Break(Arguments args);
Steve Block44f0eee2011-05-26 01:26:41 +0100234 void SetBreakPoint(Handle<SharedFunctionInfo> shared,
235 Handle<Object> break_point_object,
236 int* source_position);
237 void ClearBreakPoint(Handle<Object> break_point_object);
238 void ClearAllBreakPoints();
239 void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
240 void FloodHandlerWithOneShot();
241 void ChangeBreakOnException(ExceptionBreakType type, bool enable);
242 bool IsBreakOnException(ExceptionBreakType type);
243 void PrepareStep(StepAction step_action, int step_count);
244 void ClearStepping();
245 bool StepNextContinue(BreakLocationIterator* break_location_iterator,
246 JavaScriptFrame* frame);
Steve Blocka7e24c12009-10-30 11:49:00 +0000247 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
248 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
249
Ben Murdoch589d6972011-11-30 16:04:58 +0000250 void PrepareForBreakPoints();
251
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 // Returns whether the operation succeeded.
Steve Block44f0eee2011-05-26 01:26:41 +0100253 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000254
255 // Returns true if the current stub call is patched to call the debugger.
256 static bool IsDebugBreak(Address addr);
257 // Returns true if the current return statement has been patched to be
258 // a debugger breakpoint.
259 static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
260
261 // Check whether a code stub with the specified major key is a possible break
262 // point location.
263 static bool IsSourceBreakStub(Code* code);
264 static bool IsBreakStub(Code* code);
265
266 // Find the builtin to use for invoking the debug break
267 static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
268
269 static Handle<Object> GetSourceBreakLocations(
270 Handle<SharedFunctionInfo> shared);
271
272 // Getter for the debug_context.
Steve Block44f0eee2011-05-26 01:26:41 +0100273 inline Handle<Context> debug_context() { return debug_context_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000274
275 // Check whether a global object is the debug global object.
Steve Block44f0eee2011-05-26 01:26:41 +0100276 bool IsDebugGlobal(GlobalObject* global);
Steve Blocka7e24c12009-10-30 11:49:00 +0000277
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100278 // Check whether this frame is just about to return.
Steve Block44f0eee2011-05-26 01:26:41 +0100279 bool IsBreakAtReturn(JavaScriptFrame* frame);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100280
Steve Blocka7e24c12009-10-30 11:49:00 +0000281 // Fast check to see if any break points are active.
Steve Block44f0eee2011-05-26 01:26:41 +0100282 inline bool has_break_points() { return has_break_points_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000283
Steve Block44f0eee2011-05-26 01:26:41 +0100284 void NewBreak(StackFrame::Id break_frame_id);
285 void SetBreak(StackFrame::Id break_frame_id, int break_id);
286 StackFrame::Id break_frame_id() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000287 return thread_local_.break_frame_id_;
288 }
Steve Block44f0eee2011-05-26 01:26:41 +0100289 int break_id() { return thread_local_.break_id_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000290
Steve Block44f0eee2011-05-26 01:26:41 +0100291 bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
292 void HandleStepIn(Handle<JSFunction> function,
293 Handle<Object> holder,
294 Address fp,
295 bool is_constructor);
296 Address step_in_fp() { return thread_local_.step_into_fp_; }
297 Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000298
Steve Block44f0eee2011-05-26 01:26:41 +0100299 bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
300 Address step_out_fp() { return thread_local_.step_out_fp_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000301
Steve Block44f0eee2011-05-26 01:26:41 +0100302 EnterDebugger* debugger_entry() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 return thread_local_.debugger_entry_;
304 }
Steve Block44f0eee2011-05-26 01:26:41 +0100305 void set_debugger_entry(EnterDebugger* entry) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 thread_local_.debugger_entry_ = entry;
307 }
308
309 // Check whether any of the specified interrupts are pending.
Steve Block44f0eee2011-05-26 01:26:41 +0100310 bool is_interrupt_pending(InterruptFlag what) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 return (thread_local_.pending_interrupts_ & what) != 0;
312 }
313
314 // Set specified interrupts as pending.
Steve Block44f0eee2011-05-26 01:26:41 +0100315 void set_interrupts_pending(InterruptFlag what) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 thread_local_.pending_interrupts_ |= what;
317 }
318
319 // Clear specified interrupts from pending.
Steve Block44f0eee2011-05-26 01:26:41 +0100320 void clear_interrupt_pending(InterruptFlag what) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000321 thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
322 }
323
324 // Getter and setter for the disable break state.
Steve Block44f0eee2011-05-26 01:26:41 +0100325 bool disable_break() { return disable_break_; }
326 void set_disable_break(bool disable_break) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 disable_break_ = disable_break;
328 }
329
330 // Getters for the current exception break state.
Steve Block44f0eee2011-05-26 01:26:41 +0100331 bool break_on_exception() { return break_on_exception_; }
332 bool break_on_uncaught_exception() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000333 return break_on_uncaught_exception_;
334 }
335
336 enum AddressId {
337 k_after_break_target_address,
338 k_debug_break_return_address,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100339 k_debug_break_slot_address,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100340 k_restarter_frame_function_pointer
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 };
342
343 // Support for setting the address to jump to when returning from break point.
Steve Block44f0eee2011-05-26 01:26:41 +0100344 Address* after_break_target_address() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
346 }
Steve Block44f0eee2011-05-26 01:26:41 +0100347 Address* restarter_frame_function_pointer_address() {
Ben Murdochbb769b22010-08-11 14:56:33 +0100348 Object*** address = &thread_local_.restarter_frame_function_pointer_;
349 return reinterpret_cast<Address*>(address);
350 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000351
352 // Support for saving/restoring registers when handling debug break calls.
Steve Block44f0eee2011-05-26 01:26:41 +0100353 Object** register_address(int r) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 return &registers_[r];
355 }
356
357 // Access to the debug break on return code.
Steve Block44f0eee2011-05-26 01:26:41 +0100358 Code* debug_break_return() { return debug_break_return_; }
359 Code** debug_break_return_address() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 return &debug_break_return_;
361 }
362
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100363 // Access to the debug break in debug break slot code.
Steve Block44f0eee2011-05-26 01:26:41 +0100364 Code* debug_break_slot() { return debug_break_slot_; }
365 Code** debug_break_slot_address() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100366 return &debug_break_slot_;
367 }
368
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 static const int kEstimatedNofDebugInfoEntries = 16;
370 static const int kEstimatedNofBreakPointsInFunction = 16;
371
Steve Block44f0eee2011-05-26 01:26:41 +0100372 // Passed to MakeWeak.
Steve Blocka7e24c12009-10-30 11:49:00 +0000373 static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
374
375 friend class Debugger;
376 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
377 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
378
379 // Threading support.
Steve Block44f0eee2011-05-26 01:26:41 +0100380 char* ArchiveDebug(char* to);
381 char* RestoreDebug(char* from);
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 static int ArchiveSpacePerThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100383 void FreeThreadResources() { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000384
385 // Mirror cache handling.
Steve Block44f0eee2011-05-26 01:26:41 +0100386 void ClearMirrorCache();
Steve Blocka7e24c12009-10-30 11:49:00 +0000387
388 // Script cache handling.
Steve Block44f0eee2011-05-26 01:26:41 +0100389 void CreateScriptCache();
390 void DestroyScriptCache();
391 void AddScriptToScriptCache(Handle<Script> script);
392 Handle<FixedArray> GetLoadedScripts();
Steve Blocka7e24c12009-10-30 11:49:00 +0000393
394 // Garbage collection notifications.
Steve Block44f0eee2011-05-26 01:26:41 +0100395 void AfterGarbageCollection();
Steve Blocka7e24c12009-10-30 11:49:00 +0000396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 // Code generator routines.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100398 static void GenerateSlot(MacroAssembler* masm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 static void GenerateLoadICDebugBreak(MacroAssembler* masm);
400 static void GenerateStoreICDebugBreak(MacroAssembler* masm);
401 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
402 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
403 static void GenerateConstructCallDebugBreak(MacroAssembler* masm);
404 static void GenerateReturnDebugBreak(MacroAssembler* masm);
405 static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100406 static void GenerateSlotDebugBreak(MacroAssembler* masm);
Steve Block6ded16b2010-05-10 14:33:55 +0100407 static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
Iain Merrick75681382010-08-19 15:07:18 +0100408
409 // FrameDropper is a code replacement for a JavaScript frame with possibly
410 // several frames above.
411 // There is no calling conventions here, because it never actually gets
412 // called, it only gets returned to.
Steve Block6ded16b2010-05-10 14:33:55 +0100413 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000414
415 // Called from stub-cache.cc.
416 static void GenerateCallICDebugBreak(MacroAssembler* masm);
417
Steve Block8defd9f2010-07-08 12:39:36 +0100418 // Describes how exactly a frame has been dropped from stack.
419 enum FrameDropMode {
420 // No frame has been dropped.
421 FRAMES_UNTOUCHED,
422 // The top JS frame had been calling IC stub. IC stub mustn't be called now.
423 FRAME_DROPPED_IN_IC_CALL,
424 // The top JS frame had been calling debug break slot stub. Patch the
425 // address this stub jumps to in the end.
426 FRAME_DROPPED_IN_DEBUG_SLOT_CALL,
427 // The top JS frame had been calling some C++ function. The return address
428 // gets patched automatically.
Ben Murdoch257744e2011-11-30 15:57:28 +0000429 FRAME_DROPPED_IN_DIRECT_CALL,
430 FRAME_DROPPED_IN_RETURN_CALL
Steve Block8defd9f2010-07-08 12:39:36 +0100431 };
432
Steve Block44f0eee2011-05-26 01:26:41 +0100433 void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
Ben Murdochbb769b22010-08-11 14:56:33 +0100434 FrameDropMode mode,
435 Object** restarter_frame_function_pointer);
Steve Block6ded16b2010-05-10 14:33:55 +0100436
Ben Murdochbb769b22010-08-11 14:56:33 +0100437 // Initializes an artificial stack frame. The data it contains is used for:
438 // a. successful work of frame dropper code which eventually gets control,
439 // b. being compatible with regular stack structure for various stack
440 // iterators.
441 // Returns address of stack allocated pointer to restarted function,
442 // the value that is called 'restarter_frame_function_pointer'. The value
443 // at this address (possibly updated by GC) may be used later when preparing
444 // 'step in' operation.
Ben Murdochbb769b22010-08-11 14:56:33 +0100445 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
446 Handle<Code> code);
447
Steve Block6ded16b2010-05-10 14:33:55 +0100448 static const int kFrameDropperFrameSize;
449
Iain Merrick75681382010-08-19 15:07:18 +0100450 // Architecture-specific constant.
451 static const bool kFrameDropperSupported;
452
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100454 explicit Debug(Isolate* isolate);
455 ~Debug();
456
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 static bool CompileDebuggerScript(int index);
Steve Block44f0eee2011-05-26 01:26:41 +0100458 void ClearOneShot();
459 void ActivateStepIn(StackFrame* frame);
460 void ClearStepIn();
461 void ActivateStepOut(StackFrame* frame);
462 void ClearStepOut();
463 void ClearStepNext();
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 // Returns whether the compile succeeded.
Steve Block44f0eee2011-05-26 01:26:41 +0100465 void RemoveDebugInfo(Handle<DebugInfo> debug_info);
466 void SetAfterBreakTarget(JavaScriptFrame* frame);
467 Handle<Object> CheckBreakPoints(Handle<Object> break_point);
468 bool CheckBreakPoint(Handle<Object> break_point_object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000469
470 // Global handle to debug context where all the debugger JavaScript code is
471 // loaded.
Steve Block44f0eee2011-05-26 01:26:41 +0100472 Handle<Context> debug_context_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000473
474 // Boolean state indicating whether any break points are set.
Steve Block44f0eee2011-05-26 01:26:41 +0100475 bool has_break_points_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000476
477 // Cache of all scripts in the heap.
Steve Block44f0eee2011-05-26 01:26:41 +0100478 ScriptCache* script_cache_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000479
480 // List of active debug info objects.
Steve Block44f0eee2011-05-26 01:26:41 +0100481 DebugInfoListNode* debug_info_list_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000482
Steve Block44f0eee2011-05-26 01:26:41 +0100483 bool disable_break_;
484 bool break_on_exception_;
485 bool break_on_uncaught_exception_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000486
487 // Per-thread data.
488 class ThreadLocal {
489 public:
490 // Counter for generating next break id.
491 int break_count_;
492
493 // Current break id.
494 int break_id_;
495
496 // Frame id for the frame of the current break.
497 StackFrame::Id break_frame_id_;
498
499 // Step action for last step performed.
500 StepAction last_step_action_;
501
502 // Source statement position from last step next action.
503 int last_statement_position_;
504
505 // Number of steps left to perform before debug event.
506 int step_count_;
507
508 // Frame pointer from last step next action.
509 Address last_fp_;
510
Ben Murdoch589d6972011-11-30 16:04:58 +0000511 // Number of queued steps left to perform before debug event.
512 int queued_step_count_;
513
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 // Frame pointer for frame from which step in was performed.
515 Address step_into_fp_;
516
517 // Frame pointer for the frame where debugger should be called when current
518 // step out action is completed.
519 Address step_out_fp_;
520
521 // Storage location for jump when exiting debug break calls.
522 Address after_break_target_;
523
Steve Block8defd9f2010-07-08 12:39:36 +0100524 // Stores the way how LiveEdit has patched the stack. It is used when
525 // debugger returns control back to user script.
526 FrameDropMode frame_drop_mode_;
Steve Block6ded16b2010-05-10 14:33:55 +0100527
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 // Top debugger entry.
529 EnterDebugger* debugger_entry_;
530
531 // Pending interrupts scheduled while debugging.
532 int pending_interrupts_;
Ben Murdochbb769b22010-08-11 14:56:33 +0100533
534 // When restarter frame is on stack, stores the address
535 // of the pointer to function being restarted. Otherwise (most of the time)
536 // stores NULL. This pointer is used with 'step in' implementation.
537 Object** restarter_frame_function_pointer_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 };
539
540 // Storage location for registers when handling debug break calls
Steve Block44f0eee2011-05-26 01:26:41 +0100541 JSCallerSavedBuffer registers_;
542 ThreadLocal thread_local_;
543 void ThreadInit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000544
545 // Code to call for handling debug break on return.
Steve Block44f0eee2011-05-26 01:26:41 +0100546 Code* debug_break_return_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000547
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100548 // Code to call for handling debug break in debug break slots.
Steve Block44f0eee2011-05-26 01:26:41 +0100549 Code* debug_break_slot_;
550
551 Isolate* isolate_;
552
553 friend class Isolate;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100554
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 DISALLOW_COPY_AND_ASSIGN(Debug);
556};
557
558
Ben Murdoch8b112d22011-06-08 16:22:53 +0100559DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break);
560
561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562// Message delivered to the message handler callback. This is either a debugger
563// event or the response to a command.
564class MessageImpl: public v8::Debug::Message {
565 public:
566 // Create a message object for a debug event.
567 static MessageImpl NewEvent(DebugEvent event,
568 bool running,
569 Handle<JSObject> exec_state,
570 Handle<JSObject> event_data);
571
572 // Create a message object for the response to a debug command.
573 static MessageImpl NewResponse(DebugEvent event,
574 bool running,
575 Handle<JSObject> exec_state,
576 Handle<JSObject> event_data,
577 Handle<String> response_json,
578 v8::Debug::ClientData* client_data);
579
580 // Implementation of interface v8::Debug::Message.
581 virtual bool IsEvent() const;
582 virtual bool IsResponse() const;
583 virtual DebugEvent GetEvent() const;
584 virtual bool WillStartRunning() const;
585 virtual v8::Handle<v8::Object> GetExecutionState() const;
586 virtual v8::Handle<v8::Object> GetEventData() const;
587 virtual v8::Handle<v8::String> GetJSON() const;
588 virtual v8::Handle<v8::Context> GetEventContext() const;
589 virtual v8::Debug::ClientData* GetClientData() const;
590
591 private:
592 MessageImpl(bool is_event,
593 DebugEvent event,
594 bool running,
595 Handle<JSObject> exec_state,
596 Handle<JSObject> event_data,
597 Handle<String> response_json,
598 v8::Debug::ClientData* client_data);
599
600 bool is_event_; // Does this message represent a debug event?
601 DebugEvent event_; // Debug event causing the break.
602 bool running_; // Will the VM start running after this event?
603 Handle<JSObject> exec_state_; // Current execution state.
604 Handle<JSObject> event_data_; // Data associated with the event.
605 Handle<String> response_json_; // Response JSON if message holds a response.
606 v8::Debug::ClientData* client_data_; // Client data passed with the request.
607};
608
609
Leon Clarkef7060e22010-06-03 12:02:55 +0100610// Details of the debug event delivered to the debug event listener.
611class EventDetailsImpl : public v8::Debug::EventDetails {
612 public:
613 EventDetailsImpl(DebugEvent event,
614 Handle<JSObject> exec_state,
615 Handle<JSObject> event_data,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100616 Handle<Object> callback_data,
617 v8::Debug::ClientData* client_data);
Leon Clarkef7060e22010-06-03 12:02:55 +0100618 virtual DebugEvent GetEvent() const;
619 virtual v8::Handle<v8::Object> GetExecutionState() const;
620 virtual v8::Handle<v8::Object> GetEventData() const;
621 virtual v8::Handle<v8::Context> GetEventContext() const;
622 virtual v8::Handle<v8::Value> GetCallbackData() const;
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100623 virtual v8::Debug::ClientData* GetClientData() const;
Leon Clarkef7060e22010-06-03 12:02:55 +0100624 private:
625 DebugEvent event_; // Debug event causing the break.
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100626 Handle<JSObject> exec_state_; // Current execution state.
627 Handle<JSObject> event_data_; // Data associated with the event.
628 Handle<Object> callback_data_; // User data passed with the callback
629 // when it was registered.
630 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand.
Leon Clarkef7060e22010-06-03 12:02:55 +0100631};
632
633
Steve Blocka7e24c12009-10-30 11:49:00 +0000634// Message send by user to v8 debugger or debugger output message.
635// In addition to command text it may contain a pointer to some user data
636// which are expected to be passed along with the command reponse to message
637// handler.
638class CommandMessage {
639 public:
640 static CommandMessage New(const Vector<uint16_t>& command,
641 v8::Debug::ClientData* data);
642 CommandMessage();
643 ~CommandMessage();
644
645 // Deletes user data and disposes of the text.
646 void Dispose();
647 Vector<uint16_t> text() const { return text_; }
648 v8::Debug::ClientData* client_data() const { return client_data_; }
649 private:
650 CommandMessage(const Vector<uint16_t>& text,
651 v8::Debug::ClientData* data);
652
653 Vector<uint16_t> text_;
654 v8::Debug::ClientData* client_data_;
655};
656
657// A Queue of CommandMessage objects. A thread-safe version is
658// LockingCommandMessageQueue, based on this class.
659class CommandMessageQueue BASE_EMBEDDED {
660 public:
661 explicit CommandMessageQueue(int size);
662 ~CommandMessageQueue();
663 bool IsEmpty() const { return start_ == end_; }
664 CommandMessage Get();
665 void Put(const CommandMessage& message);
666 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear().
667 private:
668 // Doubles the size of the message queue, and copies the messages.
669 void Expand();
670
671 CommandMessage* messages_;
672 int start_;
673 int end_;
674 int size_; // The size of the queue buffer. Queue can hold size-1 messages.
675};
676
677
Leon Clarkee46be812010-01-19 14:06:41 +0000678class MessageDispatchHelperThread;
679
680
Steve Blocka7e24c12009-10-30 11:49:00 +0000681// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
682// messages. The message data is not managed by LockingCommandMessageQueue.
683// Pointers to the data are passed in and out. Implemented by adding a
684// Mutex to CommandMessageQueue. Includes logging of all puts and gets.
685class LockingCommandMessageQueue BASE_EMBEDDED {
686 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000687 LockingCommandMessageQueue(Logger* logger, int size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000688 ~LockingCommandMessageQueue();
689 bool IsEmpty() const;
690 CommandMessage Get();
691 void Put(const CommandMessage& message);
692 void Clear();
693 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000694 Logger* logger_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000695 CommandMessageQueue queue_;
696 Mutex* lock_;
697 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
698};
699
700
701class Debugger {
702 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100703 ~Debugger();
Steve Blocka7e24c12009-10-30 11:49:00 +0000704
Steve Block44f0eee2011-05-26 01:26:41 +0100705 void DebugRequest(const uint16_t* json_request, int length);
706
707 Handle<Object> MakeJSObject(Vector<const char> constructor_name,
708 int argc, Object*** argv,
709 bool* caught_exception);
710 Handle<Object> MakeExecutionState(bool* caught_exception);
711 Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
712 Handle<Object> break_points_hit,
713 bool* caught_exception);
714 Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
715 Handle<Object> exception,
716 bool uncaught,
717 bool* caught_exception);
718 Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
719 bool* caught_exception);
720 Handle<Object> MakeCompileEvent(Handle<Script> script,
721 bool before,
722 bool* caught_exception);
723 Handle<Object> MakeScriptCollectedEvent(int id,
724 bool* caught_exception);
725 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
726 void OnException(Handle<Object> exception, bool uncaught);
727 void OnBeforeCompile(Handle<Script> script);
Steve Block6ded16b2010-05-10 14:33:55 +0100728
729 enum AfterCompileFlags {
730 NO_AFTER_COMPILE_FLAGS,
731 SEND_WHEN_DEBUGGING
732 };
Steve Block44f0eee2011-05-26 01:26:41 +0100733 void OnAfterCompile(Handle<Script> script,
734 AfterCompileFlags after_compile_flags);
735 void OnNewFunction(Handle<JSFunction> fun);
736 void OnScriptCollected(int id);
737 void ProcessDebugEvent(v8::DebugEvent event,
738 Handle<JSObject> event_data,
739 bool auto_continue);
740 void NotifyMessageHandler(v8::DebugEvent event,
741 Handle<JSObject> exec_state,
742 Handle<JSObject> event_data,
743 bool auto_continue);
744 void SetEventListener(Handle<Object> callback, Handle<Object> data);
745 void SetMessageHandler(v8::Debug::MessageHandler2 handler);
746 void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
747 int period);
748 void SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +0000749 v8::Debug::DebugMessageDispatchHandler handler,
750 bool provide_locker);
Steve Blocka7e24c12009-10-30 11:49:00 +0000751
752 // Invoke the message handler function.
Steve Block44f0eee2011-05-26 01:26:41 +0100753 void InvokeMessageHandler(MessageImpl message);
Steve Blocka7e24c12009-10-30 11:49:00 +0000754
755 // Add a debugger command to the command queue.
Steve Block44f0eee2011-05-26 01:26:41 +0100756 void ProcessCommand(Vector<const uint16_t> command,
757 v8::Debug::ClientData* client_data = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000758
759 // Check whether there are commands in the command queue.
Steve Block44f0eee2011-05-26 01:26:41 +0100760 bool HasCommands();
Steve Blocka7e24c12009-10-30 11:49:00 +0000761
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100762 // Enqueue a debugger command to the command queue for event listeners.
Steve Block44f0eee2011-05-26 01:26:41 +0100763 void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100764
Steve Block44f0eee2011-05-26 01:26:41 +0100765 Handle<Object> Call(Handle<JSFunction> fun,
766 Handle<Object> data,
767 bool* pending_exception);
Steve Blocka7e24c12009-10-30 11:49:00 +0000768
769 // Start the debugger agent listening on the provided port.
Steve Block44f0eee2011-05-26 01:26:41 +0100770 bool StartAgent(const char* name, int port,
771 bool wait_for_connection = false);
Steve Blocka7e24c12009-10-30 11:49:00 +0000772
773 // Stop the debugger agent.
Steve Block44f0eee2011-05-26 01:26:41 +0100774 void StopAgent();
Steve Blocka7e24c12009-10-30 11:49:00 +0000775
776 // Blocks until the agent has started listening for connections
Steve Block44f0eee2011-05-26 01:26:41 +0100777 void WaitForAgent();
Steve Blocka7e24c12009-10-30 11:49:00 +0000778
Steve Block44f0eee2011-05-26 01:26:41 +0100779 void CallMessageDispatchHandler();
Leon Clarkee46be812010-01-19 14:06:41 +0000780
Steve Block44f0eee2011-05-26 01:26:41 +0100781 Handle<Context> GetDebugContext();
Steve Block6ded16b2010-05-10 14:33:55 +0100782
Steve Blocka7e24c12009-10-30 11:49:00 +0000783 // Unload the debugger if possible. Only called when no debugger is currently
784 // active.
Steve Block44f0eee2011-05-26 01:26:41 +0100785 void UnloadDebugger();
Steve Block6ded16b2010-05-10 14:33:55 +0100786 friend void ForceUnloadDebugger(); // In test-debug.cc
Steve Blocka7e24c12009-10-30 11:49:00 +0000787
Steve Block44f0eee2011-05-26 01:26:41 +0100788 inline bool EventActive(v8::DebugEvent event) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000789 ScopedLock with(debugger_access_);
790
791 // Check whether the message handler was been cleared.
792 if (debugger_unload_pending_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100793 if (isolate_->debug()->debugger_entry() == NULL) {
Leon Clarkee46be812010-01-19 14:06:41 +0000794 UnloadDebugger();
795 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000796 }
797
Ben Murdoch086aeea2011-05-13 15:57:08 +0100798 if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) &&
799 !FLAG_debug_compile_events) {
800 return false;
801
802 } else if ((event == v8::ScriptCollected) &&
803 !FLAG_debug_script_collected_events) {
804 return false;
805 }
806
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 // Currently argument event is not used.
808 return !compiling_natives_ && Debugger::IsDebuggerActive();
809 }
810
Steve Block44f0eee2011-05-26 01:26:41 +0100811 void set_compiling_natives(bool compiling_natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000812 Debugger::compiling_natives_ = compiling_natives;
813 }
Steve Block44f0eee2011-05-26 01:26:41 +0100814 bool compiling_natives() const { return compiling_natives_; }
815 void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
816 bool is_loading_debugger() const { return is_loading_debugger_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000817
Steve Block44f0eee2011-05-26 01:26:41 +0100818 bool IsDebuggerActive();
Leon Clarkef7060e22010-06-03 12:02:55 +0100819
820 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000821 explicit Debugger(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000822
Steve Block44f0eee2011-05-26 01:26:41 +0100823 void CallEventCallback(v8::DebugEvent event,
824 Handle<Object> exec_state,
825 Handle<Object> event_data,
826 v8::Debug::ClientData* client_data);
827 void CallCEventCallback(v8::DebugEvent event,
828 Handle<Object> exec_state,
829 Handle<Object> event_data,
830 v8::Debug::ClientData* client_data);
831 void CallJSEventCallback(v8::DebugEvent event,
832 Handle<Object> exec_state,
833 Handle<Object> event_data);
834 void ListenersChanged();
Steve Blocka7e24c12009-10-30 11:49:00 +0000835
Steve Block44f0eee2011-05-26 01:26:41 +0100836 Mutex* debugger_access_; // Mutex guarding debugger variables.
837 Handle<Object> event_listener_; // Global handle to listener.
838 Handle<Object> event_listener_data_;
839 bool compiling_natives_; // Are we compiling natives?
840 bool is_loading_debugger_; // Are we loading the debugger?
841 bool never_unload_debugger_; // Can we unload the debugger?
842 v8::Debug::MessageHandler2 message_handler_;
843 bool debugger_unload_pending_; // Was message handler cleared?
844 v8::Debug::HostDispatchHandler host_dispatch_handler_;
845 Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler.
846 v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
847 MessageDispatchHelperThread* message_dispatch_helper_thread_;
848 int host_dispatch_micros_;
849
850 DebuggerAgent* agent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000851
852 static const int kQueueInitialSize = 4;
Steve Block44f0eee2011-05-26 01:26:41 +0100853 LockingCommandMessageQueue command_queue_;
854 Semaphore* command_received_; // Signaled for each command received.
855 LockingCommandMessageQueue event_command_queue_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000856
Steve Block44f0eee2011-05-26 01:26:41 +0100857 Isolate* isolate_;
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100858
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 friend class EnterDebugger;
Steve Block44f0eee2011-05-26 01:26:41 +0100860 friend class Isolate;
861
862 DISALLOW_COPY_AND_ASSIGN(Debugger);
Steve Blocka7e24c12009-10-30 11:49:00 +0000863};
864
865
866// This class is used for entering the debugger. Create an instance in the stack
867// to enter the debugger. This will set the current break state, make sure the
868// debugger is loaded and switch to the debugger context. If the debugger for
869// some reason could not be entered FailedToEnter will return true.
870class EnterDebugger BASE_EMBEDDED {
871 public:
872 EnterDebugger()
Steve Block44f0eee2011-05-26 01:26:41 +0100873 : isolate_(Isolate::Current()),
874 prev_(isolate_->debug()->debugger_entry()),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100875 it_(isolate_),
Steve Block44f0eee2011-05-26 01:26:41 +0100876 has_js_frames_(!it_.done()),
877 save_(isolate_) {
878 Debug* debug = isolate_->debug();
879 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
880 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
Steve Blocka7e24c12009-10-30 11:49:00 +0000881
882 // Link recursive debugger entry.
Steve Block44f0eee2011-05-26 01:26:41 +0100883 debug->set_debugger_entry(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000884
885 // Store the previous break id and frame id.
Steve Block44f0eee2011-05-26 01:26:41 +0100886 break_id_ = debug->break_id();
887 break_frame_id_ = debug->break_frame_id();
Steve Blocka7e24c12009-10-30 11:49:00 +0000888
889 // Create the new break info. If there is no JavaScript frames there is no
890 // break frame id.
891 if (has_js_frames_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100892 debug->NewBreak(it_.frame()->id());
Steve Blocka7e24c12009-10-30 11:49:00 +0000893 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100894 debug->NewBreak(StackFrame::NO_ID);
Steve Blocka7e24c12009-10-30 11:49:00 +0000895 }
896
897 // Make sure that debugger is loaded and enter the debugger context.
Steve Block44f0eee2011-05-26 01:26:41 +0100898 load_failed_ = !debug->Load();
Steve Blocka7e24c12009-10-30 11:49:00 +0000899 if (!load_failed_) {
900 // NOTE the member variable save which saves the previous context before
901 // this change.
Steve Block44f0eee2011-05-26 01:26:41 +0100902 isolate_->set_context(*debug->debug_context());
Steve Blocka7e24c12009-10-30 11:49:00 +0000903 }
904 }
905
906 ~EnterDebugger() {
Steve Block44f0eee2011-05-26 01:26:41 +0100907 ASSERT(Isolate::Current() == isolate_);
908 Debug* debug = isolate_->debug();
909
Steve Blocka7e24c12009-10-30 11:49:00 +0000910 // Restore to the previous break state.
Steve Block44f0eee2011-05-26 01:26:41 +0100911 debug->SetBreak(break_frame_id_, break_id_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000912
913 // Check for leaving the debugger.
914 if (prev_ == NULL) {
915 // Clear mirror cache when leaving the debugger. Skip this if there is a
916 // pending exception as clearing the mirror cache calls back into
917 // JavaScript. This can happen if the v8::Debug::Call is used in which
918 // case the exception should end up in the calling code.
Steve Block44f0eee2011-05-26 01:26:41 +0100919 if (!isolate_->has_pending_exception()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000920 // Try to avoid any pending debug break breaking in the clear mirror
921 // cache JavaScript code.
Steve Block44f0eee2011-05-26 01:26:41 +0100922 if (isolate_->stack_guard()->IsDebugBreak()) {
923 debug->set_interrupts_pending(DEBUGBREAK);
924 isolate_->stack_guard()->Continue(DEBUGBREAK);
Steve Blocka7e24c12009-10-30 11:49:00 +0000925 }
Steve Block44f0eee2011-05-26 01:26:41 +0100926 debug->ClearMirrorCache();
Steve Blocka7e24c12009-10-30 11:49:00 +0000927 }
928
929 // Request preemption and debug break when leaving the last debugger entry
930 // if any of these where recorded while debugging.
Steve Block44f0eee2011-05-26 01:26:41 +0100931 if (debug->is_interrupt_pending(PREEMPT)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 // This re-scheduling of preemption is to avoid starvation in some
933 // debugging scenarios.
Steve Block44f0eee2011-05-26 01:26:41 +0100934 debug->clear_interrupt_pending(PREEMPT);
935 isolate_->stack_guard()->Preempt();
Steve Blocka7e24c12009-10-30 11:49:00 +0000936 }
Steve Block44f0eee2011-05-26 01:26:41 +0100937 if (debug->is_interrupt_pending(DEBUGBREAK)) {
938 debug->clear_interrupt_pending(DEBUGBREAK);
939 isolate_->stack_guard()->DebugBreak();
Steve Blocka7e24c12009-10-30 11:49:00 +0000940 }
941
942 // If there are commands in the queue when leaving the debugger request
943 // that these commands are processed.
Steve Block44f0eee2011-05-26 01:26:41 +0100944 if (isolate_->debugger()->HasCommands()) {
945 isolate_->stack_guard()->DebugCommand();
Steve Blocka7e24c12009-10-30 11:49:00 +0000946 }
947
948 // If leaving the debugger with the debugger no longer active unload it.
Steve Block44f0eee2011-05-26 01:26:41 +0100949 if (!isolate_->debugger()->IsDebuggerActive()) {
950 isolate_->debugger()->UnloadDebugger();
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 }
952 }
953
954 // Leaving this debugger entry.
Steve Block44f0eee2011-05-26 01:26:41 +0100955 debug->set_debugger_entry(prev_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000956 }
957
958 // Check whether the debugger could be entered.
959 inline bool FailedToEnter() { return load_failed_; }
960
961 // Check whether there are any JavaScript frames on the stack.
962 inline bool HasJavaScriptFrames() { return has_js_frames_; }
963
964 // Get the active context from before entering the debugger.
965 inline Handle<Context> GetContext() { return save_.context(); }
966
967 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100968 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000969 EnterDebugger* prev_; // Previous debugger entry if entered recursively.
970 JavaScriptFrameIterator it_;
971 const bool has_js_frames_; // Were there any JavaScript frames?
972 StackFrame::Id break_frame_id_; // Previous break frame id.
973 int break_id_; // Previous break id.
974 bool load_failed_; // Did the debugger fail to load?
975 SaveContext save_; // Saves previous context.
976};
977
978
979// Stack allocated class for disabling break.
980class DisableBreak BASE_EMBEDDED {
981 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100982 explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) {
983 prev_disable_break_ = isolate_->debug()->disable_break();
984 isolate_->debug()->set_disable_break(disable_break);
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 }
986 ~DisableBreak() {
Steve Block44f0eee2011-05-26 01:26:41 +0100987 ASSERT(Isolate::Current() == isolate_);
988 isolate_->debug()->set_disable_break(prev_disable_break_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000989 }
990
991 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100992 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000993 // The previous state of the disable break used to restore the value when this
994 // object is destructed.
995 bool prev_disable_break_;
996};
997
998
999// Debug_Address encapsulates the Address pointers used in generating debug
1000// code.
1001class Debug_Address {
1002 public:
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001003 explicit Debug_Address(Debug::AddressId id) : id_(id) { }
Steve Blocka7e24c12009-10-30 11:49:00 +00001004
1005 static Debug_Address AfterBreakTarget() {
1006 return Debug_Address(Debug::k_after_break_target_address);
1007 }
1008
1009 static Debug_Address DebugBreakReturn() {
1010 return Debug_Address(Debug::k_debug_break_return_address);
1011 }
1012
Ben Murdochbb769b22010-08-11 14:56:33 +01001013 static Debug_Address RestarterFrameFunctionPointer() {
1014 return Debug_Address(Debug::k_restarter_frame_function_pointer);
1015 }
1016
Steve Block44f0eee2011-05-26 01:26:41 +01001017 Address address(Isolate* isolate) const {
1018 Debug* debug = isolate->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 switch (id_) {
1020 case Debug::k_after_break_target_address:
Steve Block44f0eee2011-05-26 01:26:41 +01001021 return reinterpret_cast<Address>(debug->after_break_target_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001022 case Debug::k_debug_break_return_address:
Steve Block44f0eee2011-05-26 01:26:41 +01001023 return reinterpret_cast<Address>(debug->debug_break_return_address());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001024 case Debug::k_debug_break_slot_address:
Steve Block44f0eee2011-05-26 01:26:41 +01001025 return reinterpret_cast<Address>(debug->debug_break_slot_address());
Ben Murdochbb769b22010-08-11 14:56:33 +01001026 case Debug::k_restarter_frame_function_pointer:
1027 return reinterpret_cast<Address>(
Steve Block44f0eee2011-05-26 01:26:41 +01001028 debug->restarter_frame_function_pointer_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 default:
1030 UNREACHABLE();
1031 return NULL;
1032 }
1033 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001034
Steve Blocka7e24c12009-10-30 11:49:00 +00001035 private:
1036 Debug::AddressId id_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001037};
1038
Leon Clarkee46be812010-01-19 14:06:41 +00001039// The optional thread that Debug Agent may use to temporary call V8 to process
1040// pending debug requests if debuggee is not running V8 at the moment.
1041// Techincally it does not call V8 itself, rather it asks embedding program
1042// to do this via v8::Debug::HostDispatchHandler
1043class MessageDispatchHelperThread: public Thread {
1044 public:
Steve Block44f0eee2011-05-26 01:26:41 +01001045 explicit MessageDispatchHelperThread(Isolate* isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00001046 ~MessageDispatchHelperThread();
1047
1048 void Schedule();
1049
1050 private:
1051 void Run();
1052
1053 Semaphore* const sem_;
1054 Mutex* const mutex_;
1055 bool already_signalled_;
1056
1057 DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
1058};
1059
Steve Blocka7e24c12009-10-30 11:49:00 +00001060
1061} } // namespace v8::internal
1062
1063#endif // ENABLE_DEBUGGER_SUPPORT
1064
1065#endif // V8_DEBUG_H_