OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 10 matching lines...) Expand all Loading... |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_DEBUG_H_ | 28 #ifndef V8_DEBUG_H_ |
29 #define V8_DEBUG_H_ | 29 #define V8_DEBUG_H_ |
30 | 30 |
| 31 #include "arguments.h" |
31 #include "assembler.h" | 32 #include "assembler.h" |
32 #include "debug-agent.h" | 33 #include "debug-agent.h" |
33 #include "execution.h" | 34 #include "execution.h" |
34 #include "factory.h" | 35 #include "factory.h" |
35 #include "flags.h" | 36 #include "flags.h" |
36 #include "hashmap.h" | 37 #include "hashmap.h" |
37 #include "platform.h" | 38 #include "platform.h" |
38 #include "string-stream.h" | 39 #include "string-stream.h" |
39 #include "v8threads.h" | 40 #include "v8threads.h" |
40 | 41 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 Handle<DebugInfo> debug_info() { return debug_info_; } | 204 Handle<DebugInfo> debug_info() { return debug_info_; } |
204 | 205 |
205 private: | 206 private: |
206 // Global (weak) handle to the debug info object. | 207 // Global (weak) handle to the debug info object. |
207 Handle<DebugInfo> debug_info_; | 208 Handle<DebugInfo> debug_info_; |
208 | 209 |
209 // Next pointer for linked list. | 210 // Next pointer for linked list. |
210 DebugInfoListNode* next_; | 211 DebugInfoListNode* next_; |
211 }; | 212 }; |
212 | 213 |
213 | |
214 // This class contains the debugger support. The main purpose is to handle | 214 // This class contains the debugger support. The main purpose is to handle |
215 // setting break points in the code. | 215 // setting break points in the code. |
216 // | 216 // |
217 // This class controls the debug info for all functions which currently have | 217 // This class controls the debug info for all functions which currently have |
218 // active breakpoints in them. This debug info is held in the heap root object | 218 // active breakpoints in them. This debug info is held in the heap root object |
219 // debug_info which is a FixedArray. Each entry in this list is of class | 219 // debug_info which is a FixedArray. Each entry in this list is of class |
220 // DebugInfo. | 220 // DebugInfo. |
221 class Debug { | 221 class Debug { |
222 public: | 222 public: |
223 static void Setup(bool create_heap_objects); | 223 void Setup(bool create_heap_objects); |
224 static bool Load(); | 224 bool Load(); |
225 static void Unload(); | 225 void Unload(); |
226 static bool IsLoaded() { return !debug_context_.is_null(); } | 226 bool IsLoaded() { return !debug_context_.is_null(); } |
227 static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } | 227 bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } |
228 static void PreemptionWhileInDebugger(); | 228 void PreemptionWhileInDebugger(); |
229 static void Iterate(ObjectVisitor* v); | 229 void Iterate(ObjectVisitor* v); |
230 | 230 |
231 static Object* Break(Arguments args); | 231 static Object* Break(RUNTIME_CALLING_CONVENTION); |
232 static void SetBreakPoint(Handle<SharedFunctionInfo> shared, | 232 void SetBreakPoint(Handle<SharedFunctionInfo> shared, |
233 Handle<Object> break_point_object, | 233 Handle<Object> break_point_object, |
234 int* source_position); | 234 int* source_position); |
235 static void ClearBreakPoint(Handle<Object> break_point_object); | 235 void ClearBreakPoint(Handle<Object> break_point_object); |
236 static void ClearAllBreakPoints(); | 236 void ClearAllBreakPoints(); |
237 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared); | 237 void FloodWithOneShot(Handle<SharedFunctionInfo> shared); |
238 static void FloodHandlerWithOneShot(); | 238 void FloodHandlerWithOneShot(); |
239 static void ChangeBreakOnException(ExceptionBreakType type, bool enable); | 239 void ChangeBreakOnException(ExceptionBreakType type, bool enable); |
240 static bool IsBreakOnException(ExceptionBreakType type); | 240 bool IsBreakOnException(ExceptionBreakType type); |
241 static void PrepareStep(StepAction step_action, int step_count); | 241 void PrepareStep(StepAction step_action, int step_count); |
242 static void ClearStepping(); | 242 void ClearStepping(); |
243 static bool StepNextContinue(BreakLocationIterator* break_location_iterator, | 243 bool StepNextContinue(BreakLocationIterator* break_location_iterator, |
244 JavaScriptFrame* frame); | 244 JavaScriptFrame* frame); |
245 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); | 245 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); |
246 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); | 246 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); |
247 | 247 |
248 // Returns whether the operation succeeded. | 248 // Returns whether the operation succeeded. |
249 static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared); | 249 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared); |
250 | 250 |
251 // Returns true if the current stub call is patched to call the debugger. | 251 // Returns true if the current stub call is patched to call the debugger. |
252 static bool IsDebugBreak(Address addr); | 252 static bool IsDebugBreak(Address addr); |
253 // Returns true if the current return statement has been patched to be | 253 // Returns true if the current return statement has been patched to be |
254 // a debugger breakpoint. | 254 // a debugger breakpoint. |
255 static bool IsDebugBreakAtReturn(RelocInfo* rinfo); | 255 static bool IsDebugBreakAtReturn(RelocInfo* rinfo); |
256 | 256 |
257 // Check whether a code stub with the specified major key is a possible break | 257 // Check whether a code stub with the specified major key is a possible break |
258 // point location. | 258 // point location. |
259 static bool IsSourceBreakStub(Code* code); | 259 static bool IsSourceBreakStub(Code* code); |
260 static bool IsBreakStub(Code* code); | 260 static bool IsBreakStub(Code* code); |
261 | 261 |
262 // Find the builtin to use for invoking the debug break | 262 // Find the builtin to use for invoking the debug break |
263 static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode); | 263 static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode); |
264 | 264 |
265 static Handle<Object> GetSourceBreakLocations( | 265 static Handle<Object> GetSourceBreakLocations( |
266 Handle<SharedFunctionInfo> shared); | 266 Handle<SharedFunctionInfo> shared); |
267 | 267 |
268 // Getter for the debug_context. | 268 // Getter for the debug_context. |
269 inline static Handle<Context> debug_context() { return debug_context_; } | 269 inline Handle<Context> debug_context() { return debug_context_; } |
270 | 270 |
271 // Check whether a global object is the debug global object. | 271 // Check whether a global object is the debug global object. |
272 static bool IsDebugGlobal(GlobalObject* global); | 272 bool IsDebugGlobal(GlobalObject* global); |
273 | 273 |
274 // Check whether this frame is just about to return. | 274 // Check whether this frame is just about to return. |
275 static bool IsBreakAtReturn(JavaScriptFrame* frame); | 275 bool IsBreakAtReturn(JavaScriptFrame* frame); |
276 | 276 |
277 // Fast check to see if any break points are active. | 277 // Fast check to see if any break points are active. |
278 inline static bool has_break_points() { return has_break_points_; } | 278 inline bool has_break_points() { return has_break_points_; } |
279 | 279 |
280 static void NewBreak(StackFrame::Id break_frame_id); | 280 void NewBreak(StackFrame::Id break_frame_id); |
281 static void SetBreak(StackFrame::Id break_frame_id, int break_id); | 281 void SetBreak(StackFrame::Id break_frame_id, int break_id); |
282 static StackFrame::Id break_frame_id() { | 282 StackFrame::Id break_frame_id() { |
283 return thread_local_.break_frame_id_; | 283 return thread_local_.break_frame_id_; |
284 } | 284 } |
285 static int break_id() { return thread_local_.break_id_; } | 285 int break_id() { return thread_local_.break_id_; } |
286 | 286 |
287 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } | 287 bool StepInActive() { return thread_local_.step_into_fp_ != 0; } |
288 static void HandleStepIn(Handle<JSFunction> function, | 288 void HandleStepIn(Handle<JSFunction> function, |
289 Handle<Object> holder, | 289 Handle<Object> holder, |
290 Address fp, | 290 Address fp, |
291 bool is_constructor); | 291 bool is_constructor); |
292 static Address step_in_fp() { return thread_local_.step_into_fp_; } | 292 Address step_in_fp() { return thread_local_.step_into_fp_; } |
293 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } | 293 Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } |
294 | 294 |
295 static bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } | 295 bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } |
296 static Address step_out_fp() { return thread_local_.step_out_fp_; } | 296 Address step_out_fp() { return thread_local_.step_out_fp_; } |
297 | 297 |
298 static EnterDebugger* debugger_entry() { | 298 EnterDebugger* debugger_entry() { |
299 return thread_local_.debugger_entry_; | 299 return thread_local_.debugger_entry_; |
300 } | 300 } |
301 static void set_debugger_entry(EnterDebugger* entry) { | 301 void set_debugger_entry(EnterDebugger* entry) { |
302 thread_local_.debugger_entry_ = entry; | 302 thread_local_.debugger_entry_ = entry; |
303 } | 303 } |
304 | 304 |
305 // Check whether any of the specified interrupts are pending. | 305 // Check whether any of the specified interrupts are pending. |
306 static bool is_interrupt_pending(InterruptFlag what) { | 306 bool is_interrupt_pending(InterruptFlag what) { |
307 return (thread_local_.pending_interrupts_ & what) != 0; | 307 return (thread_local_.pending_interrupts_ & what) != 0; |
308 } | 308 } |
309 | 309 |
310 // Set specified interrupts as pending. | 310 // Set specified interrupts as pending. |
311 static void set_interrupts_pending(InterruptFlag what) { | 311 void set_interrupts_pending(InterruptFlag what) { |
312 thread_local_.pending_interrupts_ |= what; | 312 thread_local_.pending_interrupts_ |= what; |
313 } | 313 } |
314 | 314 |
315 // Clear specified interrupts from pending. | 315 // Clear specified interrupts from pending. |
316 static void clear_interrupt_pending(InterruptFlag what) { | 316 void clear_interrupt_pending(InterruptFlag what) { |
317 thread_local_.pending_interrupts_ &= ~static_cast<int>(what); | 317 thread_local_.pending_interrupts_ &= ~static_cast<int>(what); |
318 } | 318 } |
319 | 319 |
320 // Getter and setter for the disable break state. | 320 // Getter and setter for the disable break state. |
321 static bool disable_break() { return disable_break_; } | 321 bool disable_break() { return disable_break_; } |
322 static void set_disable_break(bool disable_break) { | 322 void set_disable_break(bool disable_break) { |
323 disable_break_ = disable_break; | 323 disable_break_ = disable_break; |
324 } | 324 } |
325 | 325 |
326 // Getters for the current exception break state. | 326 // Getters for the current exception break state. |
327 static bool break_on_exception() { return break_on_exception_; } | 327 bool break_on_exception() { return break_on_exception_; } |
328 static bool break_on_uncaught_exception() { | 328 bool break_on_uncaught_exception() { |
329 return break_on_uncaught_exception_; | 329 return break_on_uncaught_exception_; |
330 } | 330 } |
331 | 331 |
332 enum AddressId { | 332 enum AddressId { |
333 k_after_break_target_address, | 333 k_after_break_target_address, |
334 k_debug_break_return_address, | 334 k_debug_break_return_address, |
335 k_debug_break_slot_address, | 335 k_debug_break_slot_address, |
336 k_restarter_frame_function_pointer | 336 k_restarter_frame_function_pointer |
337 }; | 337 }; |
338 | 338 |
339 // Support for setting the address to jump to when returning from break point. | 339 // Support for setting the address to jump to when returning from break point. |
340 static Address* after_break_target_address() { | 340 Address* after_break_target_address() { |
341 return reinterpret_cast<Address*>(&thread_local_.after_break_target_); | 341 return reinterpret_cast<Address*>(&thread_local_.after_break_target_); |
342 } | 342 } |
343 static Address* restarter_frame_function_pointer_address() { | 343 Address* restarter_frame_function_pointer_address() { |
344 Object*** address = &thread_local_.restarter_frame_function_pointer_; | 344 Object*** address = &thread_local_.restarter_frame_function_pointer_; |
345 return reinterpret_cast<Address*>(address); | 345 return reinterpret_cast<Address*>(address); |
346 } | 346 } |
347 | 347 |
348 // Support for saving/restoring registers when handling debug break calls. | 348 // Support for saving/restoring registers when handling debug break calls. |
349 static Object** register_address(int r) { | 349 Object** register_address(int r) { |
350 return ®isters_[r]; | 350 return ®isters_[r]; |
351 } | 351 } |
352 | 352 |
353 // Access to the debug break on return code. | 353 // Access to the debug break on return code. |
354 static Code* debug_break_return() { return debug_break_return_; } | 354 Code* debug_break_return() { return debug_break_return_; } |
355 static Code** debug_break_return_address() { | 355 Code** debug_break_return_address() { |
356 return &debug_break_return_; | 356 return &debug_break_return_; |
357 } | 357 } |
358 | 358 |
359 // Access to the debug break in debug break slot code. | 359 // Access to the debug break in debug break slot code. |
360 static Code* debug_break_slot() { return debug_break_slot_; } | 360 Code* debug_break_slot() { return debug_break_slot_; } |
361 static Code** debug_break_slot_address() { | 361 Code** debug_break_slot_address() { |
362 return &debug_break_slot_; | 362 return &debug_break_slot_; |
363 } | 363 } |
364 | 364 |
365 static const int kEstimatedNofDebugInfoEntries = 16; | 365 static const int kEstimatedNofDebugInfoEntries = 16; |
366 static const int kEstimatedNofBreakPointsInFunction = 16; | 366 static const int kEstimatedNofBreakPointsInFunction = 16; |
367 | 367 |
| 368 // Passed to MakeWeak. |
368 static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data); | 369 static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data); |
369 | 370 |
370 friend class Debugger; | 371 friend class Debugger; |
371 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc | 372 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc |
372 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc | 373 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc |
373 | 374 |
374 // Threading support. | 375 // Threading support. |
375 static char* ArchiveDebug(char* to); | 376 char* ArchiveDebug(char* to); |
376 static char* RestoreDebug(char* from); | 377 char* RestoreDebug(char* from); |
377 static int ArchiveSpacePerThread(); | 378 static int ArchiveSpacePerThread(); |
378 static void FreeThreadResources() { } | 379 void FreeThreadResources() { } |
379 | 380 |
380 // Mirror cache handling. | 381 // Mirror cache handling. |
381 static void ClearMirrorCache(); | 382 void ClearMirrorCache(); |
382 | 383 |
383 // Script cache handling. | 384 // Script cache handling. |
384 static void CreateScriptCache(); | 385 void CreateScriptCache(); |
385 static void DestroyScriptCache(); | 386 void DestroyScriptCache(); |
386 static void AddScriptToScriptCache(Handle<Script> script); | 387 void AddScriptToScriptCache(Handle<Script> script); |
387 static Handle<FixedArray> GetLoadedScripts(); | 388 Handle<FixedArray> GetLoadedScripts(); |
388 | 389 |
389 // Garbage collection notifications. | 390 // Garbage collection notifications. |
390 static void AfterGarbageCollection(); | 391 void AfterGarbageCollection(); |
391 | 392 |
392 // Code generator routines. | 393 // Code generator routines. |
393 static void GenerateSlot(MacroAssembler* masm); | 394 static void GenerateSlot(MacroAssembler* masm); |
394 static void GenerateLoadICDebugBreak(MacroAssembler* masm); | 395 static void GenerateLoadICDebugBreak(MacroAssembler* masm); |
395 static void GenerateStoreICDebugBreak(MacroAssembler* masm); | 396 static void GenerateStoreICDebugBreak(MacroAssembler* masm); |
396 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); | 397 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); |
397 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); | 398 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); |
398 static void GenerateConstructCallDebugBreak(MacroAssembler* masm); | 399 static void GenerateConstructCallDebugBreak(MacroAssembler* masm); |
399 static void GenerateReturnDebugBreak(MacroAssembler* masm); | 400 static void GenerateReturnDebugBreak(MacroAssembler* masm); |
400 static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm); | 401 static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm); |
(...skipping 16 matching lines...) Expand all Loading... |
417 // The top JS frame had been calling IC stub. IC stub mustn't be called now. | 418 // The top JS frame had been calling IC stub. IC stub mustn't be called now. |
418 FRAME_DROPPED_IN_IC_CALL, | 419 FRAME_DROPPED_IN_IC_CALL, |
419 // The top JS frame had been calling debug break slot stub. Patch the | 420 // The top JS frame had been calling debug break slot stub. Patch the |
420 // address this stub jumps to in the end. | 421 // address this stub jumps to in the end. |
421 FRAME_DROPPED_IN_DEBUG_SLOT_CALL, | 422 FRAME_DROPPED_IN_DEBUG_SLOT_CALL, |
422 // The top JS frame had been calling some C++ function. The return address | 423 // The top JS frame had been calling some C++ function. The return address |
423 // gets patched automatically. | 424 // gets patched automatically. |
424 FRAME_DROPPED_IN_DIRECT_CALL | 425 FRAME_DROPPED_IN_DIRECT_CALL |
425 }; | 426 }; |
426 | 427 |
427 static void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 428 void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
428 FrameDropMode mode, | 429 FrameDropMode mode, |
429 Object** restarter_frame_function_pointer); | 430 Object** restarter_frame_function_pointer); |
430 | 431 |
431 // Initializes an artificial stack frame. The data it contains is used for: | 432 // Initializes an artificial stack frame. The data it contains is used for: |
432 // a. successful work of frame dropper code which eventually gets control, | 433 // a. successful work of frame dropper code which eventually gets control, |
433 // b. being compatible with regular stack structure for various stack | 434 // b. being compatible with regular stack structure for various stack |
434 // iterators. | 435 // iterators. |
435 // Returns address of stack allocated pointer to restarted function, | 436 // Returns address of stack allocated pointer to restarted function, |
436 // the value that is called 'restarter_frame_function_pointer'. The value | 437 // the value that is called 'restarter_frame_function_pointer'. The value |
437 // at this address (possibly updated by GC) may be used later when preparing | 438 // at this address (possibly updated by GC) may be used later when preparing |
438 // 'step in' operation. | 439 // 'step in' operation. |
439 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame, | 440 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame, |
440 Handle<Code> code); | 441 Handle<Code> code); |
441 | 442 |
442 static const int kFrameDropperFrameSize; | 443 static const int kFrameDropperFrameSize; |
443 | 444 |
444 // Architecture-specific constant. | 445 // Architecture-specific constant. |
445 static const bool kFrameDropperSupported; | 446 static const bool kFrameDropperSupported; |
446 | 447 |
447 private: | 448 private: |
| 449 explicit Debug(Isolate* isolate); |
| 450 ~Debug(); |
| 451 |
448 static bool CompileDebuggerScript(int index); | 452 static bool CompileDebuggerScript(int index); |
449 static void ClearOneShot(); | 453 void ClearOneShot(); |
450 static void ActivateStepIn(StackFrame* frame); | 454 void ActivateStepIn(StackFrame* frame); |
451 static void ClearStepIn(); | 455 void ClearStepIn(); |
452 static void ActivateStepOut(StackFrame* frame); | 456 void ActivateStepOut(StackFrame* frame); |
453 static void ClearStepOut(); | 457 void ClearStepOut(); |
454 static void ClearStepNext(); | 458 void ClearStepNext(); |
455 // Returns whether the compile succeeded. | 459 // Returns whether the compile succeeded. |
456 static void RemoveDebugInfo(Handle<DebugInfo> debug_info); | 460 void RemoveDebugInfo(Handle<DebugInfo> debug_info); |
457 static void SetAfterBreakTarget(JavaScriptFrame* frame); | 461 void SetAfterBreakTarget(JavaScriptFrame* frame); |
458 static Handle<Object> CheckBreakPoints(Handle<Object> break_point); | 462 Handle<Object> CheckBreakPoints(Handle<Object> break_point); |
459 static bool CheckBreakPoint(Handle<Object> break_point_object); | 463 bool CheckBreakPoint(Handle<Object> break_point_object); |
460 | 464 |
461 // Global handle to debug context where all the debugger JavaScript code is | 465 // Global handle to debug context where all the debugger JavaScript code is |
462 // loaded. | 466 // loaded. |
463 static Handle<Context> debug_context_; | 467 Handle<Context> debug_context_; |
464 | 468 |
465 // Boolean state indicating whether any break points are set. | 469 // Boolean state indicating whether any break points are set. |
466 static bool has_break_points_; | 470 bool has_break_points_; |
467 | 471 |
468 // Cache of all scripts in the heap. | 472 // Cache of all scripts in the heap. |
469 static ScriptCache* script_cache_; | 473 ScriptCache* script_cache_; |
470 | 474 |
471 // List of active debug info objects. | 475 // List of active debug info objects. |
472 static DebugInfoListNode* debug_info_list_; | 476 DebugInfoListNode* debug_info_list_; |
473 | 477 |
474 static bool disable_break_; | 478 bool disable_break_; |
475 static bool break_on_exception_; | 479 bool break_on_exception_; |
476 static bool break_on_uncaught_exception_; | 480 bool break_on_uncaught_exception_; |
477 | 481 |
478 // Per-thread data. | 482 // Per-thread data. |
479 class ThreadLocal { | 483 class ThreadLocal { |
480 public: | 484 public: |
481 // Counter for generating next break id. | 485 // Counter for generating next break id. |
482 int break_count_; | 486 int break_count_; |
483 | 487 |
484 // Current break id. | 488 // Current break id. |
485 int break_id_; | 489 int break_id_; |
486 | 490 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 // Pending interrupts scheduled while debugging. | 523 // Pending interrupts scheduled while debugging. |
520 int pending_interrupts_; | 524 int pending_interrupts_; |
521 | 525 |
522 // When restarter frame is on stack, stores the address | 526 // When restarter frame is on stack, stores the address |
523 // of the pointer to function being restarted. Otherwise (most of the time) | 527 // of the pointer to function being restarted. Otherwise (most of the time) |
524 // stores NULL. This pointer is used with 'step in' implementation. | 528 // stores NULL. This pointer is used with 'step in' implementation. |
525 Object** restarter_frame_function_pointer_; | 529 Object** restarter_frame_function_pointer_; |
526 }; | 530 }; |
527 | 531 |
528 // Storage location for registers when handling debug break calls | 532 // Storage location for registers when handling debug break calls |
529 static JSCallerSavedBuffer registers_; | 533 JSCallerSavedBuffer registers_; |
530 static ThreadLocal thread_local_; | 534 ThreadLocal thread_local_; |
531 static void ThreadInit(); | 535 void ThreadInit(); |
532 | 536 |
533 // Code to call for handling debug break on return. | 537 // Code to call for handling debug break on return. |
534 static Code* debug_break_return_; | 538 Code* debug_break_return_; |
535 | 539 |
536 // Code to call for handling debug break in debug break slots. | 540 // Code to call for handling debug break in debug break slots. |
537 static Code* debug_break_slot_; | 541 Code* debug_break_slot_; |
| 542 |
| 543 Isolate* isolate_; |
| 544 |
| 545 friend class Isolate; |
538 | 546 |
539 DISALLOW_COPY_AND_ASSIGN(Debug); | 547 DISALLOW_COPY_AND_ASSIGN(Debug); |
540 }; | 548 }; |
541 | 549 |
542 | 550 |
543 // Message delivered to the message handler callback. This is either a debugger | 551 // Message delivered to the message handler callback. This is either a debugger |
544 // event or the response to a command. | 552 // event or the response to a command. |
545 class MessageImpl: public v8::Debug::Message { | 553 class MessageImpl: public v8::Debug::Message { |
546 public: | 554 public: |
547 // Create a message object for a debug event. | 555 // Create a message object for a debug event. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 void Clear(); | 681 void Clear(); |
674 private: | 682 private: |
675 CommandMessageQueue queue_; | 683 CommandMessageQueue queue_; |
676 Mutex* lock_; | 684 Mutex* lock_; |
677 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); | 685 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); |
678 }; | 686 }; |
679 | 687 |
680 | 688 |
681 class Debugger { | 689 class Debugger { |
682 public: | 690 public: |
683 static void DebugRequest(const uint16_t* json_request, int length); | 691 ~Debugger(); |
684 | 692 |
685 static Handle<Object> MakeJSObject(Vector<const char> constructor_name, | 693 void DebugRequest(const uint16_t* json_request, int length); |
686 int argc, Object*** argv, | 694 |
687 bool* caught_exception); | 695 Handle<Object> MakeJSObject(Vector<const char> constructor_name, |
688 static Handle<Object> MakeExecutionState(bool* caught_exception); | 696 int argc, Object*** argv, |
689 static Handle<Object> MakeBreakEvent(Handle<Object> exec_state, | 697 bool* caught_exception); |
690 Handle<Object> break_points_hit, | 698 Handle<Object> MakeExecutionState(bool* caught_exception); |
691 bool* caught_exception); | 699 Handle<Object> MakeBreakEvent(Handle<Object> exec_state, |
692 static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state, | 700 Handle<Object> break_points_hit, |
693 Handle<Object> exception, | 701 bool* caught_exception); |
694 bool uncaught, | 702 Handle<Object> MakeExceptionEvent(Handle<Object> exec_state, |
695 bool* caught_exception); | 703 Handle<Object> exception, |
696 static Handle<Object> MakeNewFunctionEvent(Handle<Object> func, | 704 bool uncaught, |
697 bool* caught_exception); | 705 bool* caught_exception); |
698 static Handle<Object> MakeCompileEvent(Handle<Script> script, | 706 Handle<Object> MakeNewFunctionEvent(Handle<Object> func, |
699 bool before, | 707 bool* caught_exception); |
700 bool* caught_exception); | 708 Handle<Object> MakeCompileEvent(Handle<Script> script, |
701 static Handle<Object> MakeScriptCollectedEvent(int id, | 709 bool before, |
702 bool* caught_exception); | 710 bool* caught_exception); |
703 static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); | 711 Handle<Object> MakeScriptCollectedEvent(int id, |
704 static void OnException(Handle<Object> exception, bool uncaught); | 712 bool* caught_exception); |
705 static void OnBeforeCompile(Handle<Script> script); | 713 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); |
| 714 void OnException(Handle<Object> exception, bool uncaught); |
| 715 void OnBeforeCompile(Handle<Script> script); |
706 | 716 |
707 enum AfterCompileFlags { | 717 enum AfterCompileFlags { |
708 NO_AFTER_COMPILE_FLAGS, | 718 NO_AFTER_COMPILE_FLAGS, |
709 SEND_WHEN_DEBUGGING | 719 SEND_WHEN_DEBUGGING |
710 }; | 720 }; |
711 static void OnAfterCompile(Handle<Script> script, | 721 void OnAfterCompile(Handle<Script> script, |
712 AfterCompileFlags after_compile_flags); | 722 AfterCompileFlags after_compile_flags); |
713 static void OnNewFunction(Handle<JSFunction> fun); | 723 void OnNewFunction(Handle<JSFunction> fun); |
714 static void OnScriptCollected(int id); | 724 void OnScriptCollected(int id); |
715 static void ProcessDebugEvent(v8::DebugEvent event, | 725 void ProcessDebugEvent(v8::DebugEvent event, |
716 Handle<JSObject> event_data, | 726 Handle<JSObject> event_data, |
717 bool auto_continue); | 727 bool auto_continue); |
718 static void NotifyMessageHandler(v8::DebugEvent event, | 728 void NotifyMessageHandler(v8::DebugEvent event, |
719 Handle<JSObject> exec_state, | 729 Handle<JSObject> exec_state, |
720 Handle<JSObject> event_data, | 730 Handle<JSObject> event_data, |
721 bool auto_continue); | 731 bool auto_continue); |
722 static void SetEventListener(Handle<Object> callback, Handle<Object> data); | 732 void SetEventListener(Handle<Object> callback, Handle<Object> data); |
723 static void SetMessageHandler(v8::Debug::MessageHandler2 handler); | 733 void SetMessageHandler(v8::Debug::MessageHandler2 handler); |
724 static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, | 734 void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, |
725 int period); | 735 int period); |
726 static void SetDebugMessageDispatchHandler( | 736 void SetDebugMessageDispatchHandler( |
727 v8::Debug::DebugMessageDispatchHandler handler, | 737 v8::Debug::DebugMessageDispatchHandler handler, |
728 bool provide_locker); | 738 bool provide_locker); |
729 | 739 |
730 // Invoke the message handler function. | 740 // Invoke the message handler function. |
731 static void InvokeMessageHandler(MessageImpl message); | 741 void InvokeMessageHandler(MessageImpl message); |
732 | 742 |
733 // Add a debugger command to the command queue. | 743 // Add a debugger command to the command queue. |
734 static void ProcessCommand(Vector<const uint16_t> command, | 744 void ProcessCommand(Vector<const uint16_t> command, |
735 v8::Debug::ClientData* client_data = NULL); | 745 v8::Debug::ClientData* client_data = NULL); |
736 | 746 |
737 // Check whether there are commands in the command queue. | 747 // Check whether there are commands in the command queue. |
738 static bool HasCommands(); | 748 bool HasCommands(); |
739 | 749 |
740 // Enqueue a debugger command to the command queue for event listeners. | 750 // Enqueue a debugger command to the command queue for event listeners. |
741 static void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL); | 751 void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL); |
742 | 752 |
743 static Handle<Object> Call(Handle<JSFunction> fun, | 753 Handle<Object> Call(Handle<JSFunction> fun, |
744 Handle<Object> data, | 754 Handle<Object> data, |
745 bool* pending_exception); | 755 bool* pending_exception); |
746 | 756 |
747 // Start the debugger agent listening on the provided port. | 757 // Start the debugger agent listening on the provided port. |
748 static bool StartAgent(const char* name, int port, | 758 bool StartAgent(const char* name, int port, |
749 bool wait_for_connection = false); | 759 bool wait_for_connection = false); |
750 | 760 |
751 // Stop the debugger agent. | 761 // Stop the debugger agent. |
752 static void StopAgent(); | 762 void StopAgent(); |
753 | 763 |
754 // Blocks until the agent has started listening for connections | 764 // Blocks until the agent has started listening for connections |
755 static void WaitForAgent(); | 765 void WaitForAgent(); |
756 | 766 |
757 static void CallMessageDispatchHandler(); | 767 void CallMessageDispatchHandler(); |
758 | 768 |
759 static Handle<Context> GetDebugContext(); | 769 Handle<Context> GetDebugContext(); |
760 | 770 |
761 // Unload the debugger if possible. Only called when no debugger is currently | 771 // Unload the debugger if possible. Only called when no debugger is currently |
762 // active. | 772 // active. |
763 static void UnloadDebugger(); | 773 void UnloadDebugger(); |
764 friend void ForceUnloadDebugger(); // In test-debug.cc | 774 friend void ForceUnloadDebugger(); // In test-debug.cc |
765 | 775 |
766 inline static bool EventActive(v8::DebugEvent event) { | 776 inline bool EventActive(v8::DebugEvent event) { |
767 ScopedLock with(debugger_access_); | 777 ScopedLock with(debugger_access_); |
768 | 778 |
769 // Check whether the message handler was been cleared. | 779 // Check whether the message handler was been cleared. |
770 if (debugger_unload_pending_) { | 780 if (debugger_unload_pending_) { |
771 if (Debug::debugger_entry() == NULL) { | 781 if (isolate_->debug()->debugger_entry() == NULL) { |
772 UnloadDebugger(); | 782 UnloadDebugger(); |
773 } | 783 } |
774 } | 784 } |
775 | 785 |
776 if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) && | 786 if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) && |
777 !FLAG_debug_compile_events) { | 787 !FLAG_debug_compile_events) { |
778 return false; | 788 return false; |
779 | 789 |
780 } else if ((event == v8::ScriptCollected) && | 790 } else if ((event == v8::ScriptCollected) && |
781 !FLAG_debug_script_collected_events) { | 791 !FLAG_debug_script_collected_events) { |
782 return false; | 792 return false; |
783 } | 793 } |
784 | 794 |
785 // Currently argument event is not used. | 795 // Currently argument event is not used. |
786 return !compiling_natives_ && Debugger::IsDebuggerActive(); | 796 return !compiling_natives_ && Debugger::IsDebuggerActive(); |
787 } | 797 } |
788 | 798 |
789 static void set_compiling_natives(bool compiling_natives) { | 799 void set_compiling_natives(bool compiling_natives) { |
790 Debugger::compiling_natives_ = compiling_natives; | 800 Debugger::compiling_natives_ = compiling_natives; |
791 } | 801 } |
792 static bool compiling_natives() { return Debugger::compiling_natives_; } | 802 bool compiling_natives() const { return compiling_natives_; } |
793 static void set_loading_debugger(bool v) { is_loading_debugger_ = v; } | 803 void set_loading_debugger(bool v) { is_loading_debugger_ = v; } |
794 static bool is_loading_debugger() { return Debugger::is_loading_debugger_; } | 804 bool is_loading_debugger() const { return is_loading_debugger_; } |
795 | 805 |
796 static bool IsDebuggerActive(); | 806 bool IsDebuggerActive(); |
797 | 807 |
798 private: | 808 private: |
799 static void CallEventCallback(v8::DebugEvent event, | 809 Debugger(); |
800 Handle<Object> exec_state, | |
801 Handle<Object> event_data, | |
802 v8::Debug::ClientData* client_data); | |
803 static void CallCEventCallback(v8::DebugEvent event, | |
804 Handle<Object> exec_state, | |
805 Handle<Object> event_data, | |
806 v8::Debug::ClientData* client_data); | |
807 static void CallJSEventCallback(v8::DebugEvent event, | |
808 Handle<Object> exec_state, | |
809 Handle<Object> event_data); | |
810 static void ListenersChanged(); | |
811 | 810 |
812 static Mutex* debugger_access_; // Mutex guarding debugger variables. | 811 void CallEventCallback(v8::DebugEvent event, |
813 static Handle<Object> event_listener_; // Global handle to listener. | 812 Handle<Object> exec_state, |
814 static Handle<Object> event_listener_data_; | 813 Handle<Object> event_data, |
815 static bool compiling_natives_; // Are we compiling natives? | 814 v8::Debug::ClientData* client_data); |
816 static bool is_loading_debugger_; // Are we loading the debugger? | 815 void CallCEventCallback(v8::DebugEvent event, |
817 static bool never_unload_debugger_; // Can we unload the debugger? | 816 Handle<Object> exec_state, |
818 static v8::Debug::MessageHandler2 message_handler_; | 817 Handle<Object> event_data, |
819 static bool debugger_unload_pending_; // Was message handler cleared? | 818 v8::Debug::ClientData* client_data); |
820 static v8::Debug::HostDispatchHandler host_dispatch_handler_; | 819 void CallJSEventCallback(v8::DebugEvent event, |
821 static Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler. | 820 Handle<Object> exec_state, |
822 static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; | 821 Handle<Object> event_data); |
823 static MessageDispatchHelperThread* message_dispatch_helper_thread_; | 822 void ListenersChanged(); |
824 static int host_dispatch_micros_; | |
825 | 823 |
826 static DebuggerAgent* agent_; | 824 Mutex* debugger_access_; // Mutex guarding debugger variables. |
| 825 Handle<Object> event_listener_; // Global handle to listener. |
| 826 Handle<Object> event_listener_data_; |
| 827 bool compiling_natives_; // Are we compiling natives? |
| 828 bool is_loading_debugger_; // Are we loading the debugger? |
| 829 bool never_unload_debugger_; // Can we unload the debugger? |
| 830 v8::Debug::MessageHandler2 message_handler_; |
| 831 bool debugger_unload_pending_; // Was message handler cleared? |
| 832 v8::Debug::HostDispatchHandler host_dispatch_handler_; |
| 833 Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler. |
| 834 v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; |
| 835 MessageDispatchHelperThread* message_dispatch_helper_thread_; |
| 836 int host_dispatch_micros_; |
| 837 |
| 838 DebuggerAgent* agent_; |
827 | 839 |
828 static const int kQueueInitialSize = 4; | 840 static const int kQueueInitialSize = 4; |
829 static LockingCommandMessageQueue command_queue_; | 841 LockingCommandMessageQueue command_queue_; |
830 static Semaphore* command_received_; // Signaled for each command received. | 842 Semaphore* command_received_; // Signaled for each command received. |
| 843 LockingCommandMessageQueue event_command_queue_; |
831 | 844 |
832 static LockingCommandMessageQueue event_command_queue_; | 845 Isolate* isolate_; |
833 | 846 |
834 friend class EnterDebugger; | 847 friend class EnterDebugger; |
| 848 friend class Isolate; |
| 849 |
| 850 DISALLOW_COPY_AND_ASSIGN(Debugger); |
835 }; | 851 }; |
836 | 852 |
837 | 853 |
838 // This class is used for entering the debugger. Create an instance in the stack | 854 // This class is used for entering the debugger. Create an instance in the stack |
839 // to enter the debugger. This will set the current break state, make sure the | 855 // to enter the debugger. This will set the current break state, make sure the |
840 // debugger is loaded and switch to the debugger context. If the debugger for | 856 // debugger is loaded and switch to the debugger context. If the debugger for |
841 // some reason could not be entered FailedToEnter will return true. | 857 // some reason could not be entered FailedToEnter will return true. |
842 class EnterDebugger BASE_EMBEDDED { | 858 class EnterDebugger BASE_EMBEDDED { |
843 public: | 859 public: |
844 EnterDebugger() | 860 EnterDebugger() |
845 : prev_(Debug::debugger_entry()), | 861 : isolate_(Isolate::Current()), |
846 has_js_frames_(!it_.done()) { | 862 prev_(isolate_->debug()->debugger_entry()), |
847 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT)); | 863 has_js_frames_(!it_.done()), |
848 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK)); | 864 save_(isolate_) { |
| 865 Debug* debug = isolate_->debug(); |
| 866 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT)); |
| 867 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK)); |
849 | 868 |
850 // Link recursive debugger entry. | 869 // Link recursive debugger entry. |
851 Debug::set_debugger_entry(this); | 870 debug->set_debugger_entry(this); |
852 | 871 |
853 // Store the previous break id and frame id. | 872 // Store the previous break id and frame id. |
854 break_id_ = Debug::break_id(); | 873 break_id_ = debug->break_id(); |
855 break_frame_id_ = Debug::break_frame_id(); | 874 break_frame_id_ = debug->break_frame_id(); |
856 | 875 |
857 // Create the new break info. If there is no JavaScript frames there is no | 876 // Create the new break info. If there is no JavaScript frames there is no |
858 // break frame id. | 877 // break frame id. |
859 if (has_js_frames_) { | 878 if (has_js_frames_) { |
860 Debug::NewBreak(it_.frame()->id()); | 879 debug->NewBreak(it_.frame()->id()); |
861 } else { | 880 } else { |
862 Debug::NewBreak(StackFrame::NO_ID); | 881 debug->NewBreak(StackFrame::NO_ID); |
863 } | 882 } |
864 | 883 |
865 // Make sure that debugger is loaded and enter the debugger context. | 884 // Make sure that debugger is loaded and enter the debugger context. |
866 load_failed_ = !Debug::Load(); | 885 load_failed_ = !debug->Load(); |
867 if (!load_failed_) { | 886 if (!load_failed_) { |
868 // NOTE the member variable save which saves the previous context before | 887 // NOTE the member variable save which saves the previous context before |
869 // this change. | 888 // this change. |
870 Top::set_context(*Debug::debug_context()); | 889 isolate_->set_context(*debug->debug_context()); |
871 } | 890 } |
872 } | 891 } |
873 | 892 |
874 ~EnterDebugger() { | 893 ~EnterDebugger() { |
| 894 ASSERT(Isolate::Current() == isolate_); |
| 895 Debug* debug = isolate_->debug(); |
| 896 |
875 // Restore to the previous break state. | 897 // Restore to the previous break state. |
876 Debug::SetBreak(break_frame_id_, break_id_); | 898 debug->SetBreak(break_frame_id_, break_id_); |
877 | 899 |
878 // Check for leaving the debugger. | 900 // Check for leaving the debugger. |
879 if (prev_ == NULL) { | 901 if (prev_ == NULL) { |
880 // Clear mirror cache when leaving the debugger. Skip this if there is a | 902 // Clear mirror cache when leaving the debugger. Skip this if there is a |
881 // pending exception as clearing the mirror cache calls back into | 903 // pending exception as clearing the mirror cache calls back into |
882 // JavaScript. This can happen if the v8::Debug::Call is used in which | 904 // JavaScript. This can happen if the v8::Debug::Call is used in which |
883 // case the exception should end up in the calling code. | 905 // case the exception should end up in the calling code. |
884 if (!Top::has_pending_exception()) { | 906 if (!isolate_->has_pending_exception()) { |
885 // Try to avoid any pending debug break breaking in the clear mirror | 907 // Try to avoid any pending debug break breaking in the clear mirror |
886 // cache JavaScript code. | 908 // cache JavaScript code. |
887 if (StackGuard::IsDebugBreak()) { | 909 if (isolate_->stack_guard()->IsDebugBreak()) { |
888 Debug::set_interrupts_pending(DEBUGBREAK); | 910 debug->set_interrupts_pending(DEBUGBREAK); |
889 StackGuard::Continue(DEBUGBREAK); | 911 isolate_->stack_guard()->Continue(DEBUGBREAK); |
890 } | 912 } |
891 Debug::ClearMirrorCache(); | 913 debug->ClearMirrorCache(); |
892 } | 914 } |
893 | 915 |
894 // Request preemption and debug break when leaving the last debugger entry | 916 // Request preemption and debug break when leaving the last debugger entry |
895 // if any of these where recorded while debugging. | 917 // if any of these where recorded while debugging. |
896 if (Debug::is_interrupt_pending(PREEMPT)) { | 918 if (debug->is_interrupt_pending(PREEMPT)) { |
897 // This re-scheduling of preemption is to avoid starvation in some | 919 // This re-scheduling of preemption is to avoid starvation in some |
898 // debugging scenarios. | 920 // debugging scenarios. |
899 Debug::clear_interrupt_pending(PREEMPT); | 921 debug->clear_interrupt_pending(PREEMPT); |
900 StackGuard::Preempt(); | 922 isolate_->stack_guard()->Preempt(); |
901 } | 923 } |
902 if (Debug::is_interrupt_pending(DEBUGBREAK)) { | 924 if (debug->is_interrupt_pending(DEBUGBREAK)) { |
903 Debug::clear_interrupt_pending(DEBUGBREAK); | 925 debug->clear_interrupt_pending(DEBUGBREAK); |
904 StackGuard::DebugBreak(); | 926 isolate_->stack_guard()->DebugBreak(); |
905 } | 927 } |
906 | 928 |
907 // If there are commands in the queue when leaving the debugger request | 929 // If there are commands in the queue when leaving the debugger request |
908 // that these commands are processed. | 930 // that these commands are processed. |
909 if (Debugger::HasCommands()) { | 931 if (isolate_->debugger()->HasCommands()) { |
910 StackGuard::DebugCommand(); | 932 isolate_->stack_guard()->DebugCommand(); |
911 } | 933 } |
912 | 934 |
913 // If leaving the debugger with the debugger no longer active unload it. | 935 // If leaving the debugger with the debugger no longer active unload it. |
914 if (!Debugger::IsDebuggerActive()) { | 936 if (!isolate_->debugger()->IsDebuggerActive()) { |
915 Debugger::UnloadDebugger(); | 937 isolate_->debugger()->UnloadDebugger(); |
916 } | 938 } |
917 } | 939 } |
918 | 940 |
919 // Leaving this debugger entry. | 941 // Leaving this debugger entry. |
920 Debug::set_debugger_entry(prev_); | 942 debug->set_debugger_entry(prev_); |
921 } | 943 } |
922 | 944 |
923 // Check whether the debugger could be entered. | 945 // Check whether the debugger could be entered. |
924 inline bool FailedToEnter() { return load_failed_; } | 946 inline bool FailedToEnter() { return load_failed_; } |
925 | 947 |
926 // Check whether there are any JavaScript frames on the stack. | 948 // Check whether there are any JavaScript frames on the stack. |
927 inline bool HasJavaScriptFrames() { return has_js_frames_; } | 949 inline bool HasJavaScriptFrames() { return has_js_frames_; } |
928 | 950 |
929 // Get the active context from before entering the debugger. | 951 // Get the active context from before entering the debugger. |
930 inline Handle<Context> GetContext() { return save_.context(); } | 952 inline Handle<Context> GetContext() { return save_.context(); } |
931 | 953 |
932 private: | 954 private: |
| 955 Isolate* isolate_; |
933 EnterDebugger* prev_; // Previous debugger entry if entered recursively. | 956 EnterDebugger* prev_; // Previous debugger entry if entered recursively. |
934 JavaScriptFrameIterator it_; | 957 JavaScriptFrameIterator it_; |
935 const bool has_js_frames_; // Were there any JavaScript frames? | 958 const bool has_js_frames_; // Were there any JavaScript frames? |
936 StackFrame::Id break_frame_id_; // Previous break frame id. | 959 StackFrame::Id break_frame_id_; // Previous break frame id. |
937 int break_id_; // Previous break id. | 960 int break_id_; // Previous break id. |
938 bool load_failed_; // Did the debugger fail to load? | 961 bool load_failed_; // Did the debugger fail to load? |
939 SaveContext save_; // Saves previous context. | 962 SaveContext save_; // Saves previous context. |
940 }; | 963 }; |
941 | 964 |
942 | 965 |
943 // Stack allocated class for disabling break. | 966 // Stack allocated class for disabling break. |
944 class DisableBreak BASE_EMBEDDED { | 967 class DisableBreak BASE_EMBEDDED { |
945 public: | 968 public: |
946 explicit DisableBreak(bool disable_break) { | 969 explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) { |
947 prev_disable_break_ = Debug::disable_break(); | 970 prev_disable_break_ = isolate_->debug()->disable_break(); |
948 Debug::set_disable_break(disable_break); | 971 isolate_->debug()->set_disable_break(disable_break); |
949 } | 972 } |
950 ~DisableBreak() { | 973 ~DisableBreak() { |
951 Debug::set_disable_break(prev_disable_break_); | 974 ASSERT(Isolate::Current() == isolate_); |
| 975 isolate_->debug()->set_disable_break(prev_disable_break_); |
952 } | 976 } |
953 | 977 |
954 private: | 978 private: |
| 979 Isolate* isolate_; |
955 // The previous state of the disable break used to restore the value when this | 980 // The previous state of the disable break used to restore the value when this |
956 // object is destructed. | 981 // object is destructed. |
957 bool prev_disable_break_; | 982 bool prev_disable_break_; |
958 }; | 983 }; |
959 | 984 |
960 | 985 |
961 // Debug_Address encapsulates the Address pointers used in generating debug | 986 // Debug_Address encapsulates the Address pointers used in generating debug |
962 // code. | 987 // code. |
963 class Debug_Address { | 988 class Debug_Address { |
964 public: | 989 public: |
965 explicit Debug_Address(Debug::AddressId id) : id_(id) { } | 990 explicit Debug_Address(Debug::AddressId id) : id_(id) { } |
966 | 991 |
967 static Debug_Address AfterBreakTarget() { | 992 static Debug_Address AfterBreakTarget() { |
968 return Debug_Address(Debug::k_after_break_target_address); | 993 return Debug_Address(Debug::k_after_break_target_address); |
969 } | 994 } |
970 | 995 |
971 static Debug_Address DebugBreakReturn() { | 996 static Debug_Address DebugBreakReturn() { |
972 return Debug_Address(Debug::k_debug_break_return_address); | 997 return Debug_Address(Debug::k_debug_break_return_address); |
973 } | 998 } |
974 | 999 |
975 static Debug_Address RestarterFrameFunctionPointer() { | 1000 static Debug_Address RestarterFrameFunctionPointer() { |
976 return Debug_Address(Debug::k_restarter_frame_function_pointer); | 1001 return Debug_Address(Debug::k_restarter_frame_function_pointer); |
977 } | 1002 } |
978 | 1003 |
979 Address address() const { | 1004 Address address(Isolate* isolate) const { |
| 1005 Debug* debug = isolate->debug(); |
980 switch (id_) { | 1006 switch (id_) { |
981 case Debug::k_after_break_target_address: | 1007 case Debug::k_after_break_target_address: |
982 return reinterpret_cast<Address>(Debug::after_break_target_address()); | 1008 return reinterpret_cast<Address>(debug->after_break_target_address()); |
983 case Debug::k_debug_break_return_address: | 1009 case Debug::k_debug_break_return_address: |
984 return reinterpret_cast<Address>(Debug::debug_break_return_address()); | 1010 return reinterpret_cast<Address>(debug->debug_break_return_address()); |
985 case Debug::k_debug_break_slot_address: | 1011 case Debug::k_debug_break_slot_address: |
986 return reinterpret_cast<Address>(Debug::debug_break_slot_address()); | 1012 return reinterpret_cast<Address>(debug->debug_break_slot_address()); |
987 case Debug::k_restarter_frame_function_pointer: | 1013 case Debug::k_restarter_frame_function_pointer: |
988 return reinterpret_cast<Address>( | 1014 return reinterpret_cast<Address>( |
989 Debug::restarter_frame_function_pointer_address()); | 1015 debug->restarter_frame_function_pointer_address()); |
990 default: | 1016 default: |
991 UNREACHABLE(); | 1017 UNREACHABLE(); |
992 return NULL; | 1018 return NULL; |
993 } | 1019 } |
994 } | 1020 } |
995 private: | 1021 private: |
996 Debug::AddressId id_; | 1022 Debug::AddressId id_; |
997 }; | 1023 }; |
998 | 1024 |
999 // The optional thread that Debug Agent may use to temporary call V8 to process | 1025 // The optional thread that Debug Agent may use to temporary call V8 to process |
1000 // pending debug requests if debuggee is not running V8 at the moment. | 1026 // pending debug requests if debuggee is not running V8 at the moment. |
1001 // Techincally it does not call V8 itself, rather it asks embedding program | 1027 // Techincally it does not call V8 itself, rather it asks embedding program |
1002 // to do this via v8::Debug::HostDispatchHandler | 1028 // to do this via v8::Debug::HostDispatchHandler |
1003 class MessageDispatchHelperThread: public Thread { | 1029 class MessageDispatchHelperThread: public Thread { |
1004 public: | 1030 public: |
1005 MessageDispatchHelperThread(); | 1031 explicit MessageDispatchHelperThread(Isolate* isolate); |
1006 ~MessageDispatchHelperThread(); | 1032 ~MessageDispatchHelperThread(); |
1007 | 1033 |
1008 void Schedule(); | 1034 void Schedule(); |
1009 | 1035 |
1010 private: | 1036 private: |
1011 void Run(); | 1037 void Run(); |
1012 | 1038 |
1013 Semaphore* const sem_; | 1039 Semaphore* const sem_; |
1014 Mutex* const mutex_; | 1040 Mutex* const mutex_; |
1015 bool already_signalled_; | 1041 bool already_signalled_; |
1016 | 1042 |
1017 DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread); | 1043 DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread); |
1018 }; | 1044 }; |
1019 | 1045 |
1020 | 1046 |
1021 } } // namespace v8::internal | 1047 } } // namespace v8::internal |
1022 | 1048 |
1023 #endif // ENABLE_DEBUGGER_SUPPORT | 1049 #endif // ENABLE_DEBUGGER_SUPPORT |
1024 | 1050 |
1025 #endif // V8_DEBUG_H_ | 1051 #endif // V8_DEBUG_H_ |
OLD | NEW |