| 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 13 matching lines...) Expand all Loading... |
| 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_V8_DEBUG_H_ | 28 #ifndef V8_V8_DEBUG_H_ |
| 29 #define V8_V8_DEBUG_H_ | 29 #define V8_V8_DEBUG_H_ |
| 30 | 30 |
| 31 #include "../include/v8-debug.h" | 31 #include "../include/v8-debug.h" |
| 32 #include "assembler.h" | 32 #include "assembler.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "debug-agent.h" |
| 34 #include "execution.h" | 35 #include "execution.h" |
| 35 #include "factory.h" | 36 #include "factory.h" |
| 36 #include "platform.h" | 37 #include "platform.h" |
| 37 #include "string-stream.h" | 38 #include "string-stream.h" |
| 39 #include "v8threads.h" |
| 38 | 40 |
| 39 | 41 |
| 40 namespace v8 { namespace internal { | 42 namespace v8 { namespace internal { |
| 41 | 43 |
| 44 |
| 45 // Forward declarations. |
| 46 class EnterDebugger; |
| 47 |
| 48 |
| 42 // Step actions. NOTE: These values are in macros.py as well. | 49 // Step actions. NOTE: These values are in macros.py as well. |
| 43 enum StepAction { | 50 enum StepAction { |
| 44 StepNone = -1, // Stepping not prepared. | 51 StepNone = -1, // Stepping not prepared. |
| 45 StepOut = 0, // Step out of the current function. | 52 StepOut = 0, // Step out of the current function. |
| 46 StepNext = 1, // Step to the next statement in the current function. | 53 StepNext = 1, // Step to the next statement in the current function. |
| 47 StepIn = 2, // Step into new functions invoked or the next statement | 54 StepIn = 2, // Step into new functions invoked or the next statement |
| 48 // in the current function. | 55 // in the current function. |
| 49 StepMin = 3, // Perform a minimum step in the current function. | 56 StepMin = 3, // Perform a minimum step in the current function. |
| 50 StepInMin = 4 // Step into new functions invoked or perform a minimum step | 57 StepInMin = 4 // Step into new functions invoked or perform a minimum step |
| 51 // in the current function. | 58 // in the current function. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 // This class controls the debug info for all functions which currently have | 165 // This class controls the debug info for all functions which currently have |
| 159 // active breakpoints in them. This debug info is held in the heap root object | 166 // active breakpoints in them. This debug info is held in the heap root object |
| 160 // debug_info which is a FixedArray. Each entry in this list is of class | 167 // debug_info which is a FixedArray. Each entry in this list is of class |
| 161 // DebugInfo. | 168 // DebugInfo. |
| 162 class Debug { | 169 class Debug { |
| 163 public: | 170 public: |
| 164 static void Setup(bool create_heap_objects); | 171 static void Setup(bool create_heap_objects); |
| 165 static bool Load(); | 172 static bool Load(); |
| 166 static void Unload(); | 173 static void Unload(); |
| 167 static bool IsLoaded() { return !debug_context_.is_null(); } | 174 static bool IsLoaded() { return !debug_context_.is_null(); } |
| 168 static bool InDebugger() { return Top::is_break(); } | 175 static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } |
| 176 static void PreemptionWhileInDebugger(); |
| 169 static void Iterate(ObjectVisitor* v); | 177 static void Iterate(ObjectVisitor* v); |
| 170 | 178 |
| 171 static Object* Break(Arguments args); | 179 static Object* Break(Arguments args); |
| 172 static void SetBreakPoint(Handle<SharedFunctionInfo> shared, | 180 static void SetBreakPoint(Handle<SharedFunctionInfo> shared, |
| 173 int source_position, | 181 int source_position, |
| 174 Handle<Object> break_point_object); | 182 Handle<Object> break_point_object); |
| 175 static void ClearBreakPoint(Handle<Object> break_point_object); | 183 static void ClearBreakPoint(Handle<Object> break_point_object); |
| 176 static void ClearAllBreakPoints(); | 184 static void ClearAllBreakPoints(); |
| 177 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared); | 185 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared); |
| 178 static void FloodHandlerWithOneShot(); | 186 static void FloodHandlerWithOneShot(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 203 | 211 |
| 204 // Getter for the debug_context. | 212 // Getter for the debug_context. |
| 205 inline static Handle<Context> debug_context() { return debug_context_; } | 213 inline static Handle<Context> debug_context() { return debug_context_; } |
| 206 | 214 |
| 207 // Check whether a global object is the debug global object. | 215 // Check whether a global object is the debug global object. |
| 208 static bool IsDebugGlobal(GlobalObject* global); | 216 static bool IsDebugGlobal(GlobalObject* global); |
| 209 | 217 |
| 210 // Fast check to see if any break points are active. | 218 // Fast check to see if any break points are active. |
| 211 inline static bool has_break_points() { return has_break_points_; } | 219 inline static bool has_break_points() { return has_break_points_; } |
| 212 | 220 |
| 221 static void NewBreak(StackFrame::Id break_frame_id); |
| 222 static void SetBreak(StackFrame::Id break_frame_id, int break_id); |
| 223 static StackFrame::Id break_frame_id() { |
| 224 return thread_local_.break_frame_id_; |
| 225 } |
| 226 static int break_id() { return thread_local_.break_id_; } |
| 227 |
| 228 |
| 229 |
| 230 |
| 213 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } | 231 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } |
| 214 static void HandleStepIn(Handle<JSFunction> function, | 232 static void HandleStepIn(Handle<JSFunction> function, |
| 215 Address fp, | 233 Address fp, |
| 216 bool is_constructor); | 234 bool is_constructor); |
| 217 static Address step_in_fp() { return thread_local_.step_into_fp_; } | 235 static Address step_in_fp() { return thread_local_.step_into_fp_; } |
| 218 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } | 236 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } |
| 219 | 237 |
| 238 static EnterDebugger* debugger_entry() { |
| 239 return thread_local_.debugger_entry_; |
| 240 } |
| 241 static void set_debugger_entry(EnterDebugger* entry) { |
| 242 thread_local_.debugger_entry_ = entry; |
| 243 } |
| 244 |
| 245 static bool preemption_pending() { |
| 246 return thread_local_.preemption_pending_; |
| 247 } |
| 248 static void set_preemption_pending(bool preemption_pending) { |
| 249 thread_local_.preemption_pending_ = preemption_pending; |
| 250 } |
| 251 |
| 220 // Getter and setter for the disable break state. | 252 // Getter and setter for the disable break state. |
| 221 static bool disable_break() { return disable_break_; } | 253 static bool disable_break() { return disable_break_; } |
| 222 static void set_disable_break(bool disable_break) { | 254 static void set_disable_break(bool disable_break) { |
| 223 disable_break_ = disable_break; | 255 disable_break_ = disable_break; |
| 224 } | 256 } |
| 225 | 257 |
| 226 // Getters for the current exception break state. | 258 // Getters for the current exception break state. |
| 227 static bool break_on_exception() { return break_on_exception_; } | 259 static bool break_on_exception() { return break_on_exception_; } |
| 228 static bool break_on_uncaught_exception() { | 260 static bool break_on_uncaught_exception() { |
| 229 return break_on_uncaught_exception_; | 261 return break_on_uncaught_exception_; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 static Handle<Context> debug_context_; | 337 static Handle<Context> debug_context_; |
| 306 | 338 |
| 307 // Boolean state indicating whether any break points are set. | 339 // Boolean state indicating whether any break points are set. |
| 308 static bool has_break_points_; | 340 static bool has_break_points_; |
| 309 static DebugInfoListNode* debug_info_list_; | 341 static DebugInfoListNode* debug_info_list_; |
| 310 | 342 |
| 311 static bool disable_break_; | 343 static bool disable_break_; |
| 312 static bool break_on_exception_; | 344 static bool break_on_exception_; |
| 313 static bool break_on_uncaught_exception_; | 345 static bool break_on_uncaught_exception_; |
| 314 | 346 |
| 315 // Per-thread: | 347 // Per-thread data. |
| 316 class ThreadLocal { | 348 class ThreadLocal { |
| 317 public: | 349 public: |
| 350 // Counter for generating next break id. |
| 351 int break_count_; |
| 352 |
| 353 // Current break id. |
| 354 int break_id_; |
| 355 |
| 356 // Frame id for the frame of the current break. |
| 357 StackFrame::Id break_frame_id_; |
| 358 |
| 318 // Step action for last step performed. | 359 // Step action for last step performed. |
| 319 StepAction last_step_action_; | 360 StepAction last_step_action_; |
| 320 | 361 |
| 321 // Source statement position from last step next action. | 362 // Source statement position from last step next action. |
| 322 int last_statement_position_; | 363 int last_statement_position_; |
| 323 | 364 |
| 324 // Number of steps left to perform before debug event. | 365 // Number of steps left to perform before debug event. |
| 325 int step_count_; | 366 int step_count_; |
| 326 | 367 |
| 327 // Frame pointer from last step next action. | 368 // Frame pointer from last step next action. |
| 328 Address last_fp_; | 369 Address last_fp_; |
| 329 | 370 |
| 330 // Frame pointer for frame from which step in was performed. | 371 // Frame pointer for frame from which step in was performed. |
| 331 Address step_into_fp_; | 372 Address step_into_fp_; |
| 332 | 373 |
| 333 // Storage location for jump when exiting debug break calls. | 374 // Storage location for jump when exiting debug break calls. |
| 334 Address after_break_target_; | 375 Address after_break_target_; |
| 376 |
| 377 // Top debugger entry. |
| 378 EnterDebugger* debugger_entry_; |
| 379 |
| 380 // Preemption happened while debugging. |
| 381 bool preemption_pending_; |
| 335 }; | 382 }; |
| 336 | 383 |
| 337 // Storage location for registers when handling debug break calls | 384 // Storage location for registers when handling debug break calls |
| 338 static JSCallerSavedBuffer registers_; | 385 static JSCallerSavedBuffer registers_; |
| 339 static ThreadLocal thread_local_; | 386 static ThreadLocal thread_local_; |
| 340 static void ThreadInit(); | 387 static void ThreadInit(); |
| 341 | 388 |
| 342 // Code object for debug break return entry code. | 389 // Code object for debug break return entry code. |
| 343 static Code* debug_break_return_entry_; | 390 static Code* debug_break_return_entry_; |
| 344 | 391 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler, | 431 static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler, |
| 385 void* data); | 432 void* data); |
| 386 static void SendMessage(Vector<uint16_t> message); | 433 static void SendMessage(Vector<uint16_t> message); |
| 387 static void ProcessCommand(Vector<const uint16_t> command); | 434 static void ProcessCommand(Vector<const uint16_t> command); |
| 388 static void ProcessHostDispatch(void* dispatch); | 435 static void ProcessHostDispatch(void* dispatch); |
| 389 static void UpdateActiveDebugger(); | 436 static void UpdateActiveDebugger(); |
| 390 static Handle<Object> Call(Handle<JSFunction> fun, | 437 static Handle<Object> Call(Handle<JSFunction> fun, |
| 391 Handle<Object> data, | 438 Handle<Object> data, |
| 392 bool* pending_exception); | 439 bool* pending_exception); |
| 393 | 440 |
| 441 // Start the debugger agent listening on the provided port. |
| 442 static bool StartAgent(int port); |
| 443 |
| 394 inline static bool EventActive(v8::DebugEvent event) { | 444 inline static bool EventActive(v8::DebugEvent event) { |
| 395 // Currently argument event is not used. | 445 // Currently argument event is not used. |
| 396 return !Debugger::compiling_natives_ && Debugger::debugger_active_; | 446 return !Debugger::compiling_natives_ && Debugger::debugger_active_; |
| 397 } | 447 } |
| 398 | 448 |
| 399 static void set_debugger_active(bool debugger_active) { | 449 static void set_debugger_active(bool debugger_active) { |
| 400 Debugger::debugger_active_ = debugger_active; | 450 Debugger::debugger_active_ = debugger_active; |
| 401 } | 451 } |
| 402 static bool debugger_active() { return Debugger::debugger_active_; } | 452 static bool debugger_active() { return Debugger::debugger_active_; } |
| 403 static void set_compiling_natives(bool compiling_natives) { | 453 static void set_compiling_natives(bool compiling_natives) { |
| 404 Debugger::compiling_natives_ = compiling_natives; | 454 Debugger::compiling_natives_ = compiling_natives; |
| 405 } | 455 } |
| 406 static bool compiling_natives() { return Debugger::compiling_natives_; } | 456 static bool compiling_natives() { return Debugger::compiling_natives_; } |
| 407 static void set_loading_debugger(bool v) { is_loading_debugger_ = v; } | 457 static void set_loading_debugger(bool v) { is_loading_debugger_ = v; } |
| 408 static bool is_loading_debugger() { return Debugger::is_loading_debugger_; } | 458 static bool is_loading_debugger() { return Debugger::is_loading_debugger_; } |
| 409 | 459 |
| 410 private: | 460 private: |
| 411 static Handle<Object> event_listener_; // Global handle to listener | 461 static Handle<Object> event_listener_; // Global handle to listener |
| 412 static Handle<Object> event_listener_data_; | 462 static Handle<Object> event_listener_data_; |
| 413 static bool debugger_active_; // Are there any active debugger? | 463 static bool debugger_active_; // Are there any active debugger? |
| 414 static bool compiling_natives_; // Are we compiling natives? | 464 static bool compiling_natives_; // Are we compiling natives? |
| 415 static bool is_loading_debugger_; // Are we loading the debugger? | 465 static bool is_loading_debugger_; // Are we loading the debugger? |
| 416 static DebugMessageThread* message_thread_; | 466 static DebugMessageThread* message_thread_; |
| 417 static v8::DebugMessageHandler message_handler_; | 467 static v8::DebugMessageHandler message_handler_; |
| 418 static void* message_handler_data_; | 468 static void* message_handler_data_; |
| 419 static v8::DebugHostDispatchHandler host_dispatch_handler_; | 469 static v8::DebugHostDispatchHandler host_dispatch_handler_; |
| 420 static void* host_dispatch_handler_data_; | 470 static void* host_dispatch_handler_data_; |
| 421 | 471 |
| 472 static DebuggerAgent* agent_; |
| 473 |
| 422 friend class DebugMessageThread; | 474 friend class DebugMessageThread; |
| 423 }; | 475 }; |
| 424 | 476 |
| 425 | 477 |
| 426 // A Queue of Vector<uint16_t> objects. A thread-safe version is | 478 // A Queue of Vector<uint16_t> objects. A thread-safe version is |
| 427 // LockingMessageQueue, based on this class. | 479 // LockingMessageQueue, based on this class. |
| 428 class MessageQueue BASE_EMBEDDED { | 480 class MessageQueue BASE_EMBEDDED { |
| 429 public: | 481 public: |
| 430 explicit MessageQueue(int size); | 482 explicit MessageQueue(int size); |
| 431 ~MessageQueue(); | 483 ~MessageQueue(); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 DISALLOW_COPY_AND_ASSIGN(DebugMessageThread); | 558 DISALLOW_COPY_AND_ASSIGN(DebugMessageThread); |
| 507 }; | 559 }; |
| 508 | 560 |
| 509 | 561 |
| 510 // This class is used for entering the debugger. Create an instance in the stack | 562 // This class is used for entering the debugger. Create an instance in the stack |
| 511 // to enter the debugger. This will set the current break state, make sure the | 563 // to enter the debugger. This will set the current break state, make sure the |
| 512 // debugger is loaded and switch to the debugger context. If the debugger for | 564 // debugger is loaded and switch to the debugger context. If the debugger for |
| 513 // some reason could not be entered FailedToEnter will return true. | 565 // some reason could not be entered FailedToEnter will return true. |
| 514 class EnterDebugger BASE_EMBEDDED { | 566 class EnterDebugger BASE_EMBEDDED { |
| 515 public: | 567 public: |
| 516 EnterDebugger() : has_js_frames_(!it_.done()) { | 568 EnterDebugger() |
| 569 : prev_(Debug::debugger_entry()), |
| 570 has_js_frames_(!it_.done()) { |
| 571 ASSERT(!Debug::preemption_pending()); |
| 572 |
| 573 // Link recursive debugger entry. |
| 574 Debug::set_debugger_entry(this); |
| 575 |
| 576 // If a preemption is pending when first entering the debugger clear it as |
| 577 // we don't want preemption happening while executing JavaScript in the |
| 578 // debugger. When recursively entering the debugger the preemption flag |
| 579 // cannot be set as this is disabled while in the debugger (see |
| 580 // RuntimePreempt). |
| 581 if (prev_ == NULL && StackGuard::IsPreempted()) { |
| 582 StackGuard::Continue(PREEMPT); |
| 583 } |
| 584 ASSERT(!StackGuard::IsPreempted()); |
| 585 |
| 517 // Store the previous break id and frame id. | 586 // Store the previous break id and frame id. |
| 518 break_id_ = Top::break_id(); | 587 break_id_ = Debug::break_id(); |
| 519 break_frame_id_ = Top::break_frame_id(); | 588 break_frame_id_ = Debug::break_frame_id(); |
| 520 | 589 |
| 521 // Create the new break info. If there is no JavaScript frames there is no | 590 // Create the new break info. If there is no JavaScript frames there is no |
| 522 // break frame id. | 591 // break frame id. |
| 523 if (has_js_frames_) { | 592 if (has_js_frames_) { |
| 524 Top::new_break(it_.frame()->id()); | 593 Debug::NewBreak(it_.frame()->id()); |
| 525 } else { | 594 } else { |
| 526 Top::new_break(StackFrame::NO_ID); | 595 Debug::NewBreak(StackFrame::NO_ID); |
| 527 } | 596 } |
| 528 | 597 |
| 529 // Make sure that debugger is loaded and enter the debugger context. | 598 // Make sure that debugger is loaded and enter the debugger context. |
| 530 load_failed_ = !Debug::Load(); | 599 load_failed_ = !Debug::Load(); |
| 531 if (!load_failed_) { | 600 if (!load_failed_) { |
| 532 // NOTE the member variable save which saves the previous context before | 601 // NOTE the member variable save which saves the previous context before |
| 533 // this change. | 602 // this change. |
| 534 Top::set_context(*Debug::debug_context()); | 603 Top::set_context(*Debug::debug_context()); |
| 535 } | 604 } |
| 536 } | 605 } |
| 537 | 606 |
| 538 ~EnterDebugger() { | 607 ~EnterDebugger() { |
| 539 // Restore to the previous break state. | 608 // Restore to the previous break state. |
| 540 Top::set_break(break_frame_id_, break_id_); | 609 Debug::SetBreak(break_frame_id_, break_id_); |
| 610 |
| 611 // Request preemption when leaving the last debugger entry and a preemption |
| 612 // had been recorded while debugging. This is to avoid starvation in some |
| 613 // debugging scenarios. |
| 614 if (prev_ == NULL && Debug::preemption_pending()) { |
| 615 StackGuard::Preempt(); |
| 616 Debug::set_preemption_pending(false); |
| 617 } |
| 618 |
| 619 // Leaving this debugger entry. |
| 620 Debug::set_debugger_entry(prev_); |
| 541 } | 621 } |
| 542 | 622 |
| 543 // Check whether the debugger could be entered. | 623 // Check whether the debugger could be entered. |
| 544 inline bool FailedToEnter() { return load_failed_; } | 624 inline bool FailedToEnter() { return load_failed_; } |
| 545 | 625 |
| 546 // Check whether there are any JavaScript frames on the stack. | 626 // Check whether there are any JavaScript frames on the stack. |
| 547 inline bool HasJavaScriptFrames() { return has_js_frames_; } | 627 inline bool HasJavaScriptFrames() { return has_js_frames_; } |
| 548 | 628 |
| 549 private: | 629 private: |
| 630 EnterDebugger* prev_; // Previous debugger entry if entered recursively. |
| 550 JavaScriptFrameIterator it_; | 631 JavaScriptFrameIterator it_; |
| 551 const bool has_js_frames_; // Were there any JavaScript frames? | 632 const bool has_js_frames_; // Were there any JavaScript frames? |
| 552 StackFrame::Id break_frame_id_; // Previous break frame id. | 633 StackFrame::Id break_frame_id_; // Previous break frame id. |
| 553 int break_id_; // Previous break id. | 634 int break_id_; // Previous break id. |
| 554 bool load_failed_; // Did the debugger fail to load? | 635 bool load_failed_; // Did the debugger fail to load? |
| 555 SaveContext save_; // Saves previous context. | 636 SaveContext save_; // Saves previous context. |
| 556 }; | 637 }; |
| 557 | 638 |
| 558 | 639 |
| 559 // Stack allocated class for disabling break. | 640 // Stack allocated class for disabling break. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 } | 693 } |
| 613 private: | 694 private: |
| 614 Debug::AddressId id_; | 695 Debug::AddressId id_; |
| 615 int reg_; | 696 int reg_; |
| 616 }; | 697 }; |
| 617 | 698 |
| 618 | 699 |
| 619 } } // namespace v8::internal | 700 } } // namespace v8::internal |
| 620 | 701 |
| 621 #endif // V8_V8_DEBUG_H_ | 702 #endif // V8_V8_DEBUG_H_ |
| OLD | NEW |