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