OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "api.h" | 7 #include "api.h" |
8 #include "arguments.h" | 8 #include "arguments.h" |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 thread_local_.break_id_ = 0; | 558 thread_local_.break_id_ = 0; |
559 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 559 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
560 thread_local_.last_step_action_ = StepNone; | 560 thread_local_.last_step_action_ = StepNone; |
561 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 561 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
562 thread_local_.step_count_ = 0; | 562 thread_local_.step_count_ = 0; |
563 thread_local_.last_fp_ = 0; | 563 thread_local_.last_fp_ = 0; |
564 thread_local_.queued_step_count_ = 0; | 564 thread_local_.queued_step_count_ = 0; |
565 thread_local_.step_into_fp_ = 0; | 565 thread_local_.step_into_fp_ = 0; |
566 thread_local_.step_out_fp_ = 0; | 566 thread_local_.step_out_fp_ = 0; |
567 // TODO(isolates): frames_are_dropped_? | 567 // TODO(isolates): frames_are_dropped_? |
568 thread_local_.debugger_entry_ = NULL; | 568 thread_local_.current_debug_scope_ = NULL; |
569 thread_local_.restarter_frame_function_pointer_ = NULL; | 569 thread_local_.restarter_frame_function_pointer_ = NULL; |
570 thread_local_.promise_on_stack_ = NULL; | 570 thread_local_.promise_on_stack_ = NULL; |
571 } | 571 } |
572 | 572 |
573 | 573 |
574 char* Debug::ArchiveDebug(char* storage) { | 574 char* Debug::ArchiveDebug(char* storage) { |
575 char* to = storage; | 575 char* to = storage; |
576 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 576 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
577 ThreadInit(); | 577 ThreadInit(); |
578 return storage + ArchiveSpacePerThread(); | 578 return storage + ArchiveSpacePerThread(); |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 ASSERT(args.length() == 0); | 887 ASSERT(args.length() == 0); |
888 | 888 |
889 if (live_edit_enabled()) { | 889 if (live_edit_enabled()) { |
890 thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; | 890 thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; |
891 } | 891 } |
892 | 892 |
893 // Just continue if breaks are disabled or debugger cannot be loaded. | 893 // Just continue if breaks are disabled or debugger cannot be loaded. |
894 if (break_disabled_) return; | 894 if (break_disabled_) return; |
895 | 895 |
896 // Enter the debugger. | 896 // Enter the debugger. |
897 EnterDebugger debugger(isolate_); | 897 DebugScope debug_scope(this); |
898 if (debugger.FailedToEnter()) return; | 898 if (debug_scope.failed()) return; |
899 | 899 |
900 // Postpone interrupt during breakpoint processing. | 900 // Postpone interrupt during breakpoint processing. |
901 PostponeInterruptsScope postpone(isolate_); | 901 PostponeInterruptsScope postpone(isolate_); |
902 | 902 |
903 // Get the debug info (create it if it does not exist). | 903 // Get the debug info (create it if it does not exist). |
904 Handle<SharedFunctionInfo> shared = | 904 Handle<SharedFunctionInfo> shared = |
905 Handle<SharedFunctionInfo>(frame->function()->shared()); | 905 Handle<SharedFunctionInfo>(frame->function()->shared()); |
906 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 906 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
907 | 907 |
908 // Find the break point where execution has stopped. | 908 // Find the break point where execution has stopped. |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 } | 1341 } |
1342 | 1342 |
1343 | 1343 |
1344 void Debug::PrepareStep(StepAction step_action, | 1344 void Debug::PrepareStep(StepAction step_action, |
1345 int step_count, | 1345 int step_count, |
1346 StackFrame::Id frame_id) { | 1346 StackFrame::Id frame_id) { |
1347 HandleScope scope(isolate_); | 1347 HandleScope scope(isolate_); |
1348 | 1348 |
1349 PrepareForBreakPoints(); | 1349 PrepareForBreakPoints(); |
1350 | 1350 |
1351 ASSERT(is_entered()); | 1351 ASSERT(in_debug_scope()); |
1352 | 1352 |
1353 // Remember this step action and count. | 1353 // Remember this step action and count. |
1354 thread_local_.last_step_action_ = step_action; | 1354 thread_local_.last_step_action_ = step_action; |
1355 if (step_action == StepOut) { | 1355 if (step_action == StepOut) { |
1356 // For step out target frame will be found on the stack so there is no need | 1356 // For step out target frame will be found on the stack so there is no need |
1357 // to set step counter for it. It's expected to always be 0 for StepOut. | 1357 // to set step counter for it. It's expected to always be 0 for StepOut. |
1358 thread_local_.step_count_ = 0; | 1358 thread_local_.step_count_ = 0; |
1359 } else { | 1359 } else { |
1360 thread_local_.step_count_ = step_count; | 1360 thread_local_.step_count_ = step_count; |
1361 } | 1361 } |
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2451 | 2451 |
2452 | 2452 |
2453 bool Debug::IsDebugGlobal(GlobalObject* global) { | 2453 bool Debug::IsDebugGlobal(GlobalObject* global) { |
2454 return is_loaded() && global == debug_context()->global_object(); | 2454 return is_loaded() && global == debug_context()->global_object(); |
2455 } | 2455 } |
2456 | 2456 |
2457 | 2457 |
2458 void Debug::ClearMirrorCache() { | 2458 void Debug::ClearMirrorCache() { |
2459 PostponeInterruptsScope postpone(isolate_); | 2459 PostponeInterruptsScope postpone(isolate_); |
2460 HandleScope scope(isolate_); | 2460 HandleScope scope(isolate_); |
2461 ASSERT(isolate_->context() == *Debug::debug_context()); | 2461 AssertDebugContext(); |
2462 | 2462 |
2463 // Clear the mirror cache. | 2463 // Clear the mirror cache. |
2464 Handle<Object> fun = Object::GetProperty( | 2464 Handle<Object> fun = Object::GetProperty( |
2465 isolate_, | 2465 isolate_, |
2466 isolate_->global_object(), | 2466 isolate_->global_object(), |
2467 "ClearMirrorCache").ToHandleChecked(); | 2467 "ClearMirrorCache").ToHandleChecked(); |
2468 ASSERT(fun->IsJSFunction()); | 2468 ASSERT(fun->IsJSFunction()); |
2469 Execution::TryCall(Handle<JSFunction>::cast(fun), | 2469 Execution::TryCall(Handle<JSFunction>::cast(fun), |
2470 Handle<JSObject>(Debug::debug_context()->global_object()), | 2470 Handle<JSObject>(Debug::debug_context()->global_object()), |
2471 0, | 2471 0, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2507 // Generate events for collected scripts. | 2507 // Generate events for collected scripts. |
2508 if (script_cache_ != NULL) { | 2508 if (script_cache_ != NULL) { |
2509 script_cache_->ProcessCollectedScripts(); | 2509 script_cache_->ProcessCollectedScripts(); |
2510 } | 2510 } |
2511 } | 2511 } |
2512 | 2512 |
2513 | 2513 |
2514 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, | 2514 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, |
2515 int argc, | 2515 int argc, |
2516 Handle<Object> argv[]) { | 2516 Handle<Object> argv[]) { |
2517 ASSERT(isolate_->context() == *debug_context()); | 2517 AssertDebugContext(); |
2518 // Create the execution state object. | 2518 // Create the execution state object. |
2519 Handle<Object> constructor = Object::GetProperty( | 2519 Handle<Object> constructor = Object::GetProperty( |
2520 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked(); | 2520 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked(); |
2521 ASSERT(constructor->IsJSFunction()); | 2521 ASSERT(constructor->IsJSFunction()); |
2522 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); | 2522 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); |
2523 return Execution::TryCall(Handle<JSFunction>::cast(constructor), | 2523 return Execution::TryCall(Handle<JSFunction>::cast(constructor), |
2524 Handle<JSObject>(debug_context()->global_object()), | 2524 Handle<JSObject>(debug_context()->global_object()), |
2525 argc, | 2525 argc, |
2526 argv); | 2526 argv); |
2527 } | 2527 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2574 Handle<Object> exec_state; | 2574 Handle<Object> exec_state; |
2575 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2575 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
2576 // Create the script collected event object. | 2576 // Create the script collected event object. |
2577 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | 2577 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); |
2578 Handle<Object> argv[] = { exec_state, id_object }; | 2578 Handle<Object> argv[] = { exec_state, id_object }; |
2579 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); | 2579 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); |
2580 } | 2580 } |
2581 | 2581 |
2582 | 2582 |
2583 void Debug::OnException(Handle<Object> exception, bool uncaught) { | 2583 void Debug::OnException(Handle<Object> exception, bool uncaught) { |
2584 if (is_entered() || ignore_events()) return; | 2584 if (in_debug_scope() || ignore_events()) return; |
2585 | 2585 |
2586 HandleScope scope(isolate_); | 2586 HandleScope scope(isolate_); |
2587 Handle<Object> promise = GetPromiseForUncaughtException(); | 2587 Handle<Object> promise = GetPromiseForUncaughtException(); |
2588 uncaught |= !promise->IsUndefined(); | 2588 uncaught |= !promise->IsUndefined(); |
2589 | 2589 |
2590 // Bail out if exception breaks are not active | 2590 // Bail out if exception breaks are not active |
2591 if (uncaught) { | 2591 if (uncaught) { |
2592 // Uncaught exceptions are reported by either flags. | 2592 // Uncaught exceptions are reported by either flags. |
2593 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; | 2593 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
2594 } else { | 2594 } else { |
2595 // Caught exceptions are reported is activated. | 2595 // Caught exceptions are reported is activated. |
2596 if (!break_on_exception_) return; | 2596 if (!break_on_exception_) return; |
2597 } | 2597 } |
2598 | 2598 |
2599 // Enter the debugger. | 2599 DebugScope debug_scope(this); |
2600 EnterDebugger debugger(isolate_); | 2600 if (debug_scope.failed()) return; |
2601 if (debugger.FailedToEnter()) return; | |
2602 | 2601 |
2603 // Clear all current stepping setup. | 2602 // Clear all current stepping setup. |
2604 ClearStepping(); | 2603 ClearStepping(); |
2605 | 2604 |
2606 // Create the event data object. | 2605 // Create the event data object. |
2607 Handle<Object> event_data; | 2606 Handle<Object> event_data; |
2608 // Bail out and don't call debugger if exception. | 2607 // Bail out and don't call debugger if exception. |
2609 if (!MakeExceptionEvent( | 2608 if (!MakeExceptionEvent( |
2610 exception, uncaught, promise).ToHandle(&event_data)) { | 2609 exception, uncaught, promise).ToHandle(&event_data)) { |
2611 return; | 2610 return; |
2612 } | 2611 } |
2613 | 2612 |
2614 // Process debug event. | 2613 // Process debug event. |
2615 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 2614 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
2616 // Return to continue execution from where the exception was thrown. | 2615 // Return to continue execution from where the exception was thrown. |
2617 } | 2616 } |
2618 | 2617 |
2619 | 2618 |
2620 void Debug::OnDebugBreak(Handle<Object> break_points_hit, | 2619 void Debug::OnDebugBreak(Handle<Object> break_points_hit, |
2621 bool auto_continue) { | 2620 bool auto_continue) { |
2622 // Debugger has already been entered by caller. | 2621 // The caller provided for DebugScope. |
2623 ASSERT(isolate_->context() == *debug_context()); | 2622 AssertDebugContext(); |
2624 // Bail out if there is no listener for this event | 2623 // Bail out if there is no listener for this event |
2625 if (ignore_events()) return; | 2624 if (ignore_events()) return; |
2626 | 2625 |
2627 HandleScope scope(isolate_); | 2626 HandleScope scope(isolate_); |
2628 // Create the event data object. | 2627 // Create the event data object. |
2629 Handle<Object> event_data; | 2628 Handle<Object> event_data; |
2630 // Bail out and don't call debugger if exception. | 2629 // Bail out and don't call debugger if exception. |
2631 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 2630 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
2632 | 2631 |
2633 // Process debug event. | 2632 // Process debug event. |
2634 ProcessDebugEvent(v8::Break, | 2633 ProcessDebugEvent(v8::Break, |
2635 Handle<JSObject>::cast(event_data), | 2634 Handle<JSObject>::cast(event_data), |
2636 auto_continue); | 2635 auto_continue); |
2637 } | 2636 } |
2638 | 2637 |
2639 | 2638 |
2640 void Debug::OnBeforeCompile(Handle<Script> script) { | 2639 void Debug::OnBeforeCompile(Handle<Script> script) { |
2641 if (is_entered() || ignore_events()) return; | 2640 if (in_debug_scope() || ignore_events()) return; |
2642 | 2641 |
2643 HandleScope scope(isolate_); | 2642 HandleScope scope(isolate_); |
2644 // Enter the debugger. | 2643 DebugScope debug_scope(this); |
2645 EnterDebugger debugger(isolate_); | 2644 if (debug_scope.failed()) return; |
2646 if (debugger.FailedToEnter()) return; | |
2647 | 2645 |
2648 // Create the event data object. | 2646 // Create the event data object. |
2649 Handle<Object> event_data; | 2647 Handle<Object> event_data; |
2650 // Bail out and don't call debugger if exception. | 2648 // Bail out and don't call debugger if exception. |
2651 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; | 2649 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; |
2652 | 2650 |
2653 // Process debug event. | 2651 // Process debug event. |
2654 ProcessDebugEvent(v8::BeforeCompile, | 2652 ProcessDebugEvent(v8::BeforeCompile, |
2655 Handle<JSObject>::cast(event_data), | 2653 Handle<JSObject>::cast(event_data), |
2656 true); | 2654 true); |
2657 } | 2655 } |
2658 | 2656 |
2659 | 2657 |
2660 // Handle debugger actions when a new script is compiled. | 2658 // Handle debugger actions when a new script is compiled. |
2661 void Debug::OnAfterCompile(Handle<Script> script, | 2659 void Debug::OnAfterCompile(Handle<Script> script, |
2662 AfterCompileFlags after_compile_flags) { | 2660 AfterCompileFlags after_compile_flags) { |
2663 // Add the newly compiled script to the script cache. | 2661 // Add the newly compiled script to the script cache. |
2664 if (script_cache_ != NULL) script_cache_->Add(script); | 2662 if (script_cache_ != NULL) script_cache_->Add(script); |
2665 | 2663 |
2666 // No more to do if not debugging. | 2664 // No more to do if not debugging. |
2667 if (is_entered() || ignore_events()) return; | 2665 if (in_debug_scope() || ignore_events()) return; |
2668 | 2666 |
2669 HandleScope scope(isolate_); | 2667 HandleScope scope(isolate_); |
2670 // Store whether in debugger before entering debugger. | 2668 // Store whether in debugger before entering debugger. |
2671 bool in_debugger = is_entered(); | 2669 bool was_in_scope = in_debug_scope(); |
2672 | 2670 |
2673 // Enter the debugger. | 2671 DebugScope debug_scope(this); |
2674 EnterDebugger debugger(isolate_); | 2672 if (debug_scope.failed()) return; |
2675 if (debugger.FailedToEnter()) return; | |
2676 | 2673 |
2677 // If debugging there might be script break points registered for this | 2674 // If debugging there might be script break points registered for this |
2678 // script. Make sure that these break points are set. | 2675 // script. Make sure that these break points are set. |
2679 | 2676 |
2680 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js). | 2677 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js). |
2681 Handle<String> update_script_break_points_string = | 2678 Handle<String> update_script_break_points_string = |
2682 isolate_->factory()->InternalizeOneByteString( | 2679 isolate_->factory()->InternalizeOneByteString( |
2683 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints")); | 2680 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints")); |
2684 Handle<GlobalObject> debug_global(debug_context()->global_object()); | 2681 Handle<GlobalObject> debug_global(debug_context()->global_object()); |
2685 Handle<Object> update_script_break_points = | 2682 Handle<Object> update_script_break_points = |
(...skipping 10 matching lines...) Expand all Loading... |
2696 | 2693 |
2697 // Call UpdateScriptBreakPoints expect no exceptions. | 2694 // Call UpdateScriptBreakPoints expect no exceptions. |
2698 Handle<Object> argv[] = { wrapper }; | 2695 Handle<Object> argv[] = { wrapper }; |
2699 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), | 2696 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), |
2700 isolate_->js_builtins_object(), | 2697 isolate_->js_builtins_object(), |
2701 ARRAY_SIZE(argv), | 2698 ARRAY_SIZE(argv), |
2702 argv).is_null()) { | 2699 argv).is_null()) { |
2703 return; | 2700 return; |
2704 } | 2701 } |
2705 // Bail out based on state or if there is no listener for this event | 2702 // Bail out based on state or if there is no listener for this event |
2706 if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return; | 2703 if (was_in_scope && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return; |
2707 | 2704 |
2708 // Create the compile state object. | 2705 // Create the compile state object. |
2709 Handle<Object> event_data; | 2706 Handle<Object> event_data; |
2710 // Bail out and don't call debugger if exception. | 2707 // Bail out and don't call debugger if exception. |
2711 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; | 2708 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; |
2712 | 2709 |
2713 // Process debug event. | 2710 // Process debug event. |
2714 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2711 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
2715 } | 2712 } |
2716 | 2713 |
2717 | 2714 |
2718 void Debug::OnScriptCollected(int id) { | 2715 void Debug::OnScriptCollected(int id) { |
2719 if (is_entered() || ignore_events()) return; | 2716 if (in_debug_scope() || ignore_events()) return; |
2720 | 2717 |
2721 HandleScope scope(isolate_); | 2718 HandleScope scope(isolate_); |
2722 // Enter the debugger. | 2719 DebugScope debug_scope(this); |
2723 EnterDebugger debugger(isolate_); | 2720 if (debug_scope.failed()) return; |
2724 if (debugger.FailedToEnter()) return; | |
2725 | 2721 |
2726 // Create the script collected state object. | 2722 // Create the script collected state object. |
2727 Handle<Object> event_data; | 2723 Handle<Object> event_data; |
2728 // Bail out and don't call debugger if exception. | 2724 // Bail out and don't call debugger if exception. |
2729 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; | 2725 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; |
2730 | 2726 |
2731 // Process debug event. | 2727 // Process debug event. |
2732 ProcessDebugEvent(v8::ScriptCollected, | 2728 ProcessDebugEvent(v8::ScriptCollected, |
2733 Handle<JSObject>::cast(event_data), | 2729 Handle<JSObject>::cast(event_data), |
2734 true); | 2730 true); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2799 event_listener_data_ }; | 2795 event_listener_data_ }; |
2800 Execution::TryCall(Handle<JSFunction>::cast(event_listener_), | 2796 Execution::TryCall(Handle<JSFunction>::cast(event_listener_), |
2801 isolate_->global_object(), | 2797 isolate_->global_object(), |
2802 ARRAY_SIZE(argv), | 2798 ARRAY_SIZE(argv), |
2803 argv); | 2799 argv); |
2804 } | 2800 } |
2805 } | 2801 } |
2806 | 2802 |
2807 | 2803 |
2808 Handle<Context> Debug::GetDebugContext() { | 2804 Handle<Context> Debug::GetDebugContext() { |
2809 EnterDebugger debugger(isolate_); | 2805 DebugScope debug_scope(this); |
2810 // The global handle may be destroyed soon after. Return it reboxed. | 2806 // The global handle may be destroyed soon after. Return it reboxed. |
2811 return handle(*debug_context(), isolate_); | 2807 return handle(*debug_context(), isolate_); |
2812 } | 2808 } |
2813 | 2809 |
2814 | 2810 |
2815 void Debug::NotifyMessageHandler(v8::DebugEvent event, | 2811 void Debug::NotifyMessageHandler(v8::DebugEvent event, |
2816 Handle<JSObject> exec_state, | 2812 Handle<JSObject> exec_state, |
2817 Handle<JSObject> event_data, | 2813 Handle<JSObject> event_data, |
2818 bool auto_continue) { | 2814 bool auto_continue) { |
2819 ASSERT(is_active_); | 2815 ASSERT(is_active_); |
(...skipping 18 matching lines...) Expand all Loading... |
2838 break; | 2834 break; |
2839 case v8::NewFunction: | 2835 case v8::NewFunction: |
2840 break; | 2836 break; |
2841 default: | 2837 default: |
2842 UNREACHABLE(); | 2838 UNREACHABLE(); |
2843 } | 2839 } |
2844 | 2840 |
2845 // The debug command interrupt flag might have been set when the command was | 2841 // The debug command interrupt flag might have been set when the command was |
2846 // added. It should be enough to clear the flag only once while we are in the | 2842 // added. It should be enough to clear the flag only once while we are in the |
2847 // debugger. | 2843 // debugger. |
2848 ASSERT(is_entered()); | 2844 ASSERT(in_debug_scope()); |
2849 isolate_->stack_guard()->ClearDebugCommand(); | 2845 isolate_->stack_guard()->ClearDebugCommand(); |
2850 | 2846 |
2851 // Notify the debugger that a debug event has occurred unless auto continue is | 2847 // Notify the debugger that a debug event has occurred unless auto continue is |
2852 // active in which case no event is send. | 2848 // active in which case no event is send. |
2853 if (sendEventMessage) { | 2849 if (sendEventMessage) { |
2854 MessageImpl message = MessageImpl::NewEvent( | 2850 MessageImpl message = MessageImpl::NewEvent( |
2855 event, | 2851 event, |
2856 auto_continue, | 2852 auto_continue, |
2857 Handle<JSObject>::cast(exec_state), | 2853 Handle<JSObject>::cast(exec_state), |
2858 Handle<JSObject>::cast(event_data)); | 2854 Handle<JSObject>::cast(event_data)); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2960 event_listener_data_ = global_handles->Create(*data); | 2956 event_listener_data_ = global_handles->Create(*data); |
2961 } | 2957 } |
2962 | 2958 |
2963 UpdateState(); | 2959 UpdateState(); |
2964 } | 2960 } |
2965 | 2961 |
2966 | 2962 |
2967 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { | 2963 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { |
2968 message_handler_ = handler; | 2964 message_handler_ = handler; |
2969 UpdateState(); | 2965 UpdateState(); |
2970 if (handler == NULL && is_entered()) { | 2966 if (handler == NULL && in_debug_scope()) { |
2971 // Send an empty command to the debugger if in a break to make JavaScript | 2967 // Send an empty command to the debugger if in a break to make JavaScript |
2972 // run again if the debugger is closed. | 2968 // run again if the debugger is closed. |
2973 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | 2969 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
2974 } | 2970 } |
2975 } | 2971 } |
2976 | 2972 |
2977 | 2973 |
2978 | 2974 |
2979 void Debug::UpdateState() { | 2975 void Debug::UpdateState() { |
2980 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); | 2976 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); |
2981 if (is_active_ || is_entered()) { | 2977 if (is_active_ || in_debug_scope()) { |
2982 // Note that the debug context could have already been loaded to | 2978 // Note that the debug context could have already been loaded to |
2983 // bootstrap test cases. | 2979 // bootstrap test cases. |
2984 isolate_->compilation_cache()->Disable(); | 2980 isolate_->compilation_cache()->Disable(); |
2985 is_active_ = Load(); | 2981 is_active_ = Load(); |
2986 } else if (is_loaded() && !is_active_) { | 2982 } else if (is_loaded()) { |
2987 isolate_->compilation_cache()->Enable(); | 2983 isolate_->compilation_cache()->Enable(); |
2988 Unload(); | 2984 Unload(); |
2989 } | 2985 } |
2990 } | 2986 } |
2991 | 2987 |
2992 | 2988 |
2993 // Calls the registered debug message handler. This callback is part of the | 2989 // Calls the registered debug message handler. This callback is part of the |
2994 // public API. | 2990 // public API. |
2995 void Debug::InvokeMessageHandler(MessageImpl message) { | 2991 void Debug::InvokeMessageHandler(MessageImpl message) { |
2996 if (message_handler_ != NULL) message_handler_(message); | 2992 if (message_handler_ != NULL) message_handler_(message); |
2997 } | 2993 } |
2998 | 2994 |
2999 | 2995 |
3000 // Puts a command coming from the public API on the queue. Creates | 2996 // Puts a command coming from the public API on the queue. Creates |
3001 // a copy of the command string managed by the debugger. Up to this | 2997 // a copy of the command string managed by the debugger. Up to this |
3002 // point, the command data was managed by the API client. Called | 2998 // point, the command data was managed by the API client. Called |
3003 // by the API client thread. | 2999 // by the API client thread. |
3004 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, | 3000 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, |
3005 v8::Debug::ClientData* client_data) { | 3001 v8::Debug::ClientData* client_data) { |
3006 // Need to cast away const. | 3002 // Need to cast away const. |
3007 CommandMessage message = CommandMessage::New( | 3003 CommandMessage message = CommandMessage::New( |
3008 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | 3004 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
3009 command.length()), | 3005 command.length()), |
3010 client_data); | 3006 client_data); |
3011 isolate_->logger()->DebugTag("Put command on command_queue."); | 3007 isolate_->logger()->DebugTag("Put command on command_queue."); |
3012 command_queue_.Put(message); | 3008 command_queue_.Put(message); |
3013 command_received_.Signal(); | 3009 command_received_.Signal(); |
3014 | 3010 |
3015 // Set the debug command break flag to have the command processed. | 3011 // Set the debug command break flag to have the command processed. |
3016 if (!is_entered()) isolate_->stack_guard()->RequestDebugCommand(); | 3012 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand(); |
3017 } | 3013 } |
3018 | 3014 |
3019 | 3015 |
3020 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { | 3016 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { |
3021 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); | 3017 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); |
3022 event_command_queue_.Put(message); | 3018 event_command_queue_.Put(message); |
3023 | 3019 |
3024 // Set the debug command break flag to have the command processed. | 3020 // Set the debug command break flag to have the command processed. |
3025 if (!is_entered()) isolate_->stack_guard()->RequestDebugCommand(); | 3021 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand(); |
3026 } | 3022 } |
3027 | 3023 |
3028 | 3024 |
3029 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) { | 3025 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) { |
3030 // Enter the debugger. | 3026 DebugScope debug_scope(this); |
3031 EnterDebugger debugger(isolate_); | 3027 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); |
3032 if (debugger.FailedToEnter()) { | |
3033 return isolate_->factory()->undefined_value(); | |
3034 } | |
3035 | 3028 |
3036 // Create the execution state. | 3029 // Create the execution state. |
3037 Handle<Object> exec_state; | 3030 Handle<Object> exec_state; |
3038 if (!MakeExecutionState().ToHandle(&exec_state)) { | 3031 if (!MakeExecutionState().ToHandle(&exec_state)) { |
3039 return isolate_->factory()->undefined_value(); | 3032 return isolate_->factory()->undefined_value(); |
3040 } | 3033 } |
3041 | 3034 |
3042 Handle<Object> argv[] = { exec_state, data }; | 3035 Handle<Object> argv[] = { exec_state, data }; |
3043 return Execution::Call( | 3036 return Execution::Call( |
3044 isolate_, | 3037 isolate_, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3082 } | 3075 } |
3083 | 3076 |
3084 | 3077 |
3085 void Debug::ProcessDebugMessages(bool debug_command_only) { | 3078 void Debug::ProcessDebugMessages(bool debug_command_only) { |
3086 isolate_->stack_guard()->ClearDebugCommand(); | 3079 isolate_->stack_guard()->ClearDebugCommand(); |
3087 | 3080 |
3088 StackLimitCheck check(isolate_); | 3081 StackLimitCheck check(isolate_); |
3089 if (check.HasOverflowed()) return; | 3082 if (check.HasOverflowed()) return; |
3090 | 3083 |
3091 HandleScope scope(isolate_); | 3084 HandleScope scope(isolate_); |
3092 // Enter the debugger. Just continue if we fail to enter the debugger. | 3085 DebugScope debug_scope(this); |
3093 EnterDebugger debugger(isolate_); | 3086 if (debug_scope.failed()) return; |
3094 if (debugger.FailedToEnter()) return; | |
3095 | 3087 |
3096 // Notify the debug event listeners. Indicate auto continue if the break was | 3088 // Notify the debug event listeners. Indicate auto continue if the break was |
3097 // a debug command break. | 3089 // a debug command break. |
3098 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); | 3090 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); |
3099 } | 3091 } |
3100 | 3092 |
3101 | 3093 |
3102 EnterDebugger::EnterDebugger(Isolate* isolate) | 3094 DebugScope::DebugScope(Debug* debug) : debug_(debug), |
3103 : isolate_(isolate), | 3095 prev_(debug->debugger_entry()), |
3104 prev_(isolate_->debug()->debugger_entry()), | 3096 save_(debug_->isolate_) { |
3105 save_(isolate_) { | |
3106 Debug* debug = isolate_->debug(); | |
3107 | |
3108 // Link recursive debugger entry. | 3097 // Link recursive debugger entry. |
3109 debug->thread_local_.debugger_entry_ = this; | 3098 debug_->thread_local_.current_debug_scope_ = this; |
3110 | 3099 |
3111 // Store the previous break id and frame id. | 3100 // Store the previous break id and frame id. |
3112 break_id_ = debug->break_id(); | 3101 break_id_ = debug_->break_id(); |
3113 break_frame_id_ = debug->break_frame_id(); | 3102 break_frame_id_ = debug_->break_frame_id(); |
3114 | 3103 |
3115 // Create the new break info. If there is no JavaScript frames there is no | 3104 // Create the new break info. If there is no JavaScript frames there is no |
3116 // break frame id. | 3105 // break frame id. |
3117 JavaScriptFrameIterator it(isolate_); | 3106 JavaScriptFrameIterator it(isolate()); |
3118 bool has_js_frames = !it.done(); | 3107 bool has_js_frames = !it.done(); |
3119 debug->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() | 3108 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() |
3120 : StackFrame::NO_ID; | 3109 : StackFrame::NO_ID; |
3121 debug->SetNextBreakId(); | 3110 debug_->SetNextBreakId(); |
3122 | 3111 |
3123 debug->UpdateState(); | 3112 debug_->UpdateState(); |
3124 // Make sure that debugger is loaded and enter the debugger context. | 3113 // Make sure that debugger is loaded and enter the debugger context. |
3125 // The previous context is kept in save_. | 3114 // The previous context is kept in save_. |
3126 load_failed_ = !debug->is_loaded(); | 3115 failed_ = !debug_->is_loaded(); |
3127 if (!load_failed_) isolate_->set_context(*debug->debug_context()); | 3116 if (!failed_) isolate()->set_context(*debug->debug_context()); |
3128 } | 3117 } |
3129 | 3118 |
3130 | 3119 |
3131 EnterDebugger::~EnterDebugger() { | |
3132 Debug* debug = isolate_->debug(); | |
3133 | 3120 |
3134 // Restore to the previous break state. | 3121 DebugScope::~DebugScope() { |
3135 debug->thread_local_.break_frame_id_ = break_frame_id_; | 3122 if (!failed_ && prev_ == NULL) { |
3136 debug->thread_local_.break_id_ = break_id_; | |
3137 | |
3138 // Check for leaving the debugger. | |
3139 if (!load_failed_ && prev_ == NULL) { | |
3140 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3123 // Clear mirror cache when leaving the debugger. Skip this if there is a |
3141 // pending exception as clearing the mirror cache calls back into | 3124 // pending exception as clearing the mirror cache calls back into |
3142 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3125 // JavaScript. This can happen if the v8::Debug::Call is used in which |
3143 // case the exception should end up in the calling code. | 3126 // case the exception should end up in the calling code. |
3144 if (!isolate_->has_pending_exception()) debug->ClearMirrorCache(); | 3127 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); |
3145 | 3128 |
3146 // If there are commands in the queue when leaving the debugger request | 3129 // If there are commands in the queue when leaving the debugger request |
3147 // that these commands are processed. | 3130 // that these commands are processed. |
3148 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); | 3131 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand(); |
3149 } | 3132 } |
3150 | 3133 |
3151 // Leaving this debugger entry. | 3134 // Leaving this debugger entry. |
3152 debug->thread_local_.debugger_entry_ = prev_; | 3135 debug_->thread_local_.current_debug_scope_ = prev_; |
3153 | 3136 |
3154 debug->UpdateState(); | 3137 // Restore to the previous break state. |
| 3138 debug_->thread_local_.break_frame_id_ = break_frame_id_; |
| 3139 debug_->thread_local_.break_id_ = break_id_; |
| 3140 |
| 3141 debug_->UpdateState(); |
3155 } | 3142 } |
3156 | 3143 |
3157 | 3144 |
3158 MessageImpl MessageImpl::NewEvent(DebugEvent event, | 3145 MessageImpl MessageImpl::NewEvent(DebugEvent event, |
3159 bool running, | 3146 bool running, |
3160 Handle<JSObject> exec_state, | 3147 Handle<JSObject> exec_state, |
3161 Handle<JSObject> event_data) { | 3148 Handle<JSObject> event_data) { |
3162 MessageImpl message(true, event, running, | 3149 MessageImpl message(true, event, running, |
3163 exec_state, event_data, Handle<String>(), NULL); | 3150 exec_state, event_data, Handle<String>(), NULL); |
3164 return message; | 3151 return message; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3401 logger_->DebugEvent("Put", message.text()); | 3388 logger_->DebugEvent("Put", message.text()); |
3402 } | 3389 } |
3403 | 3390 |
3404 | 3391 |
3405 void LockingCommandMessageQueue::Clear() { | 3392 void LockingCommandMessageQueue::Clear() { |
3406 LockGuard<Mutex> lock_guard(&mutex_); | 3393 LockGuard<Mutex> lock_guard(&mutex_); |
3407 queue_.Clear(); | 3394 queue_.Clear(); |
3408 } | 3395 } |
3409 | 3396 |
3410 } } // namespace v8::internal | 3397 } } // namespace v8::internal |
OLD | NEW |