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 27 matching lines...) Expand all Loading... |
38 break_on_exception_(false), | 38 break_on_exception_(false), |
39 break_on_uncaught_exception_(false), | 39 break_on_uncaught_exception_(false), |
40 promise_catch_handlers_(0), | 40 promise_catch_handlers_(0), |
41 promise_getters_(0), | 41 promise_getters_(0), |
42 isolate_(isolate) { | 42 isolate_(isolate) { |
43 memset(registers_, 0, sizeof(JSCallerSavedBuffer)); | 43 memset(registers_, 0, sizeof(JSCallerSavedBuffer)); |
44 ThreadInit(); | 44 ThreadInit(); |
45 } | 45 } |
46 | 46 |
47 | 47 |
| 48 Debug::~Debug() { |
| 49 } |
| 50 |
| 51 |
48 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { | 52 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { |
49 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | 53 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); |
50 // Isolate::context() may have been NULL when "script collected" event | 54 // Isolate::context() may have been NULL when "script collected" event |
51 // occured. | 55 // occured. |
52 if (context.is_null()) return v8::Local<v8::Context>(); | 56 if (context.is_null()) return v8::Local<v8::Context>(); |
53 Handle<Context> native_context(context->native_context()); | 57 Handle<Context> native_context(context->native_context()); |
54 return v8::Utils::ToLocal(native_context); | 58 return v8::Utils::ToLocal(native_context); |
55 } | 59 } |
56 | 60 |
57 | 61 |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 DebugInfoListNode::~DebugInfoListNode() { | 687 DebugInfoListNode::~DebugInfoListNode() { |
684 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); | 688 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); |
685 } | 689 } |
686 | 690 |
687 | 691 |
688 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { | 692 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { |
689 Factory* factory = isolate->factory(); | 693 Factory* factory = isolate->factory(); |
690 HandleScope scope(isolate); | 694 HandleScope scope(isolate); |
691 | 695 |
692 // Bail out if the index is invalid. | 696 // Bail out if the index is invalid. |
693 if (index == -1) return false; | 697 if (index == -1) { |
| 698 return false; |
| 699 } |
694 | 700 |
695 // Find source and name for the requested script. | 701 // Find source and name for the requested script. |
696 Handle<String> source_code = | 702 Handle<String> source_code = |
697 isolate->bootstrapper()->NativesSourceLookup(index); | 703 isolate->bootstrapper()->NativesSourceLookup(index); |
698 Vector<const char> name = Natives::GetScriptName(index); | 704 Vector<const char> name = Natives::GetScriptName(index); |
699 Handle<String> script_name = | 705 Handle<String> script_name = |
700 factory->NewStringFromAscii(name).ToHandleChecked(); | 706 factory->NewStringFromAscii(name).ToHandleChecked(); |
701 Handle<Context> context = isolate->native_context(); | 707 Handle<Context> context = isolate->native_context(); |
702 | 708 |
703 // Compile the script. | 709 // Compile the script. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 Handle<Script> script(Script::cast(function->shared()->script())); | 755 Handle<Script> script(Script::cast(function->shared()->script())); |
750 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); | 756 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); |
751 return true; | 757 return true; |
752 } | 758 } |
753 | 759 |
754 | 760 |
755 bool Debug::Load() { | 761 bool Debug::Load() { |
756 // Return if debugger is already loaded. | 762 // Return if debugger is already loaded. |
757 if (IsLoaded()) return true; | 763 if (IsLoaded()) return true; |
758 | 764 |
| 765 Debugger* debugger = isolate_->debugger(); |
| 766 |
759 // Bail out if we're already in the process of compiling the native | 767 // Bail out if we're already in the process of compiling the native |
760 // JavaScript source code for the debugger. | 768 // JavaScript source code for the debugger. |
761 if (isolate_->debugger()->ignore_debugger()) return false; | 769 if (debugger->ignore_debugger()) return false; |
762 Debugger::IgnoreScope during_create(isolate_->debugger()); | |
763 | 770 |
| 771 Debugger::IgnoreScope during_load(debugger); |
764 // Disable breakpoints and interrupts while compiling and running the | 772 // Disable breakpoints and interrupts while compiling and running the |
765 // debugger scripts including the context creation code. | 773 // debugger scripts including the context creation code. |
766 DisableBreak disable(isolate_, true); | 774 DisableBreak disable(isolate_, true); |
767 PostponeInterruptsScope postpone(isolate_); | 775 PostponeInterruptsScope postpone(isolate_); |
768 | 776 |
769 // Create the debugger context. | 777 // Create the debugger context. |
770 HandleScope scope(isolate_); | 778 HandleScope scope(isolate_); |
771 ExtensionConfiguration no_extensions; | 779 ExtensionConfiguration no_extensions; |
772 Handle<Context> context = | 780 Handle<Context> context = |
773 isolate_->bootstrapper()->CreateEnvironment( | 781 isolate_->bootstrapper()->CreateEnvironment( |
774 Handle<Object>::null(), | 782 Handle<Object>::null(), |
775 v8::Handle<ObjectTemplate>(), | 783 v8::Handle<ObjectTemplate>(), |
776 &no_extensions); | 784 &no_extensions); |
777 | 785 |
778 // Fail if no context could be created. | 786 // Fail if no context could be created. |
779 if (context.is_null()) return false; | 787 if (context.is_null()) return false; |
780 | 788 |
781 // Use the debugger context. | 789 // Use the debugger context. |
782 SaveContext save(isolate_); | 790 SaveContext save(isolate_); |
783 isolate_->set_context(*context); | 791 isolate_->set_context(*context); |
784 | 792 |
785 // Expose the builtins object in the debugger context. | 793 // Expose the builtins object in the debugger context. |
786 Handle<String> key = isolate_->factory()->InternalizeOneByteString( | 794 Handle<String> key = isolate_->factory()->InternalizeOneByteString( |
787 STATIC_ASCII_VECTOR("builtins")); | 795 STATIC_ASCII_VECTOR("builtins")); |
788 Handle<GlobalObject> global = | 796 Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object()); |
789 Handle<GlobalObject>(context->global_object(), isolate_); | |
790 Handle<JSBuiltinsObject> builtin = | |
791 Handle<JSBuiltinsObject>(global->builtins(), isolate_); | |
792 RETURN_ON_EXCEPTION_VALUE( | 797 RETURN_ON_EXCEPTION_VALUE( |
793 isolate_, | 798 isolate_, |
794 JSReceiver::SetProperty(global, key, builtin, NONE, SLOPPY), | 799 JSReceiver::SetProperty(global, |
| 800 key, |
| 801 Handle<Object>(global->builtins(), isolate_), |
| 802 NONE, |
| 803 SLOPPY), |
795 false); | 804 false); |
796 | 805 |
797 // Compile the JavaScript for the debugger in the debugger context. | 806 // Compile the JavaScript for the debugger in the debugger context. |
798 bool caught_exception = | 807 bool caught_exception = |
799 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) || | 808 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) || |
800 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug")); | 809 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug")); |
801 | 810 |
802 if (FLAG_enable_liveedit) { | 811 if (FLAG_enable_liveedit) { |
803 caught_exception = caught_exception || | 812 caught_exception = caught_exception || |
804 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit")); | 813 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit")); |
805 } | 814 } |
| 815 |
| 816 // Make sure we mark the debugger as not loading before we might |
| 817 // return. |
| 818 |
806 // Check for caught exceptions. | 819 // Check for caught exceptions. |
807 if (caught_exception) return false; | 820 if (caught_exception) return false; |
808 | 821 |
| 822 // Debugger loaded, create debugger context global handle. |
809 debug_context_ = Handle<Context>::cast( | 823 debug_context_ = Handle<Context>::cast( |
810 isolate_->global_handles()->Create(*context)); | 824 isolate_->global_handles()->Create(*context)); |
| 825 |
811 return true; | 826 return true; |
812 } | 827 } |
813 | 828 |
814 | 829 |
815 void Debug::Unload() { | 830 void Debug::Unload() { |
816 // Return debugger is not loaded. | 831 // Return debugger is not loaded. |
817 if (!IsLoaded()) return; | 832 if (!IsLoaded()) { |
| 833 return; |
| 834 } |
818 | 835 |
819 // Clear the script cache. | 836 // Clear the script cache. |
820 DestroyScriptCache(); | 837 DestroyScriptCache(); |
821 | 838 |
822 // Clear debugger context global handle. | 839 // Clear debugger context global handle. |
823 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 840 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); |
824 debug_context_ = Handle<Context>(); | 841 debug_context_ = Handle<Context>(); |
825 } | 842 } |
826 | 843 |
827 | 844 |
828 Object* Debug::Break(Arguments args) { | 845 Object* Debug::Break(Arguments args) { |
829 Heap* heap = isolate_->heap(); | 846 Heap* heap = isolate_->heap(); |
830 HandleScope scope(isolate_); | 847 HandleScope scope(isolate_); |
831 ASSERT(args.length() == 0); | 848 ASSERT(args.length() == 0); |
832 | 849 |
833 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED; | 850 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED; |
834 | 851 |
835 // Get the top-most JavaScript frame. | 852 // Get the top-most JavaScript frame. |
836 JavaScriptFrameIterator it(isolate_); | 853 JavaScriptFrameIterator it(isolate_); |
837 JavaScriptFrame* frame = it.frame(); | 854 JavaScriptFrame* frame = it.frame(); |
838 | 855 |
839 // Just continue if breaks are disabled or debugger cannot be loaded. | 856 // Just continue if breaks are disabled or debugger cannot be loaded. |
840 if (disable_break()) { | 857 if (disable_break() || !Load()) { |
841 SetAfterBreakTarget(frame); | 858 SetAfterBreakTarget(frame); |
842 return heap->undefined_value(); | 859 return heap->undefined_value(); |
843 } | 860 } |
844 | 861 |
845 // Enter the debugger. | 862 // Enter the debugger. |
846 EnterDebugger debugger(isolate_); | 863 EnterDebugger debugger(isolate_); |
847 if (debugger.FailedToEnter()) { | 864 if (debugger.FailedToEnter()) { |
848 return heap->undefined_value(); | 865 return heap->undefined_value(); |
849 } | 866 } |
850 | 867 |
(...skipping 1754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2605 } | 2622 } |
2606 } | 2623 } |
2607 | 2624 |
2608 | 2625 |
2609 Debugger::Debugger(Isolate* isolate) | 2626 Debugger::Debugger(Isolate* isolate) |
2610 : event_listener_(Handle<Object>()), | 2627 : event_listener_(Handle<Object>()), |
2611 event_listener_data_(Handle<Object>()), | 2628 event_listener_data_(Handle<Object>()), |
2612 is_active_(false), | 2629 is_active_(false), |
2613 ignore_debugger_(false), | 2630 ignore_debugger_(false), |
2614 live_edit_enabled_(true), | 2631 live_edit_enabled_(true), |
| 2632 never_unload_debugger_(false), |
2615 message_handler_(NULL), | 2633 message_handler_(NULL), |
| 2634 debugger_unload_pending_(false), |
2616 command_queue_(isolate->logger(), kQueueInitialSize), | 2635 command_queue_(isolate->logger(), kQueueInitialSize), |
2617 command_received_(0), | 2636 command_received_(0), |
2618 event_command_queue_(isolate->logger(), kQueueInitialSize), | 2637 event_command_queue_(isolate->logger(), kQueueInitialSize), |
2619 isolate_(isolate) { | 2638 isolate_(isolate) { |
2620 } | 2639 } |
2621 | 2640 |
2622 | 2641 |
2623 Debugger::~Debugger() {} | 2642 Debugger::~Debugger() {} |
2624 | 2643 |
2625 | 2644 |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2962 event_listener_data_ }; | 2981 event_listener_data_ }; |
2963 Execution::TryCall(fun, | 2982 Execution::TryCall(fun, |
2964 isolate_->global_object(), | 2983 isolate_->global_object(), |
2965 ARRAY_SIZE(argv), | 2984 ARRAY_SIZE(argv), |
2966 argv); | 2985 argv); |
2967 // Silently ignore exceptions from debug event listeners. | 2986 // Silently ignore exceptions from debug event listeners. |
2968 } | 2987 } |
2969 | 2988 |
2970 | 2989 |
2971 Handle<Context> Debugger::GetDebugContext() { | 2990 Handle<Context> Debugger::GetDebugContext() { |
| 2991 never_unload_debugger_ = true; |
2972 EnterDebugger debugger(isolate_); | 2992 EnterDebugger debugger(isolate_); |
2973 return isolate_->debug()->debug_context(); | 2993 return isolate_->debug()->debug_context(); |
2974 } | 2994 } |
2975 | 2995 |
2976 | 2996 |
| 2997 void Debugger::UnloadDebugger() { |
| 2998 Debug* debug = isolate_->debug(); |
| 2999 |
| 3000 // Make sure that there are no breakpoints left. |
| 3001 debug->ClearAllBreakPoints(); |
| 3002 |
| 3003 // Unload the debugger if feasible. |
| 3004 if (!never_unload_debugger_) { |
| 3005 debug->Unload(); |
| 3006 } |
| 3007 |
| 3008 // Clear the flag indicating that the debugger should be unloaded. |
| 3009 debugger_unload_pending_ = false; |
| 3010 } |
| 3011 |
| 3012 |
2977 void Debugger::NotifyMessageHandler(v8::DebugEvent event, | 3013 void Debugger::NotifyMessageHandler(v8::DebugEvent event, |
2978 Handle<JSObject> exec_state, | 3014 Handle<JSObject> exec_state, |
2979 Handle<JSObject> event_data, | 3015 Handle<JSObject> event_data, |
2980 bool auto_continue) { | 3016 bool auto_continue) { |
2981 ASSERT(is_active_); | |
2982 HandleScope scope(isolate_); | 3017 HandleScope scope(isolate_); |
| 3018 |
| 3019 if (!isolate_->debug()->Load()) return; |
| 3020 |
2983 // Process the individual events. | 3021 // Process the individual events. |
2984 bool sendEventMessage = false; | 3022 bool sendEventMessage = false; |
2985 switch (event) { | 3023 switch (event) { |
2986 case v8::Break: | 3024 case v8::Break: |
2987 case v8::BreakForCommand: | 3025 case v8::BreakForCommand: |
2988 sendEventMessage = !auto_continue; | 3026 sendEventMessage = !auto_continue; |
2989 break; | 3027 break; |
2990 case v8::Exception: | 3028 case v8::Exception: |
2991 sendEventMessage = true; | 3029 sendEventMessage = true; |
2992 break; | 3030 break; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3100 | 3138 |
3101 // Return from debug event processing if either the VM is put into the | 3139 // Return from debug event processing if either the VM is put into the |
3102 // running state (through a continue command) or auto continue is active | 3140 // running state (through a continue command) or auto continue is active |
3103 // and there are no more commands queued. | 3141 // and there are no more commands queued. |
3104 } while (!running || HasCommands()); | 3142 } while (!running || HasCommands()); |
3105 } | 3143 } |
3106 | 3144 |
3107 | 3145 |
3108 void Debugger::SetEventListener(Handle<Object> callback, | 3146 void Debugger::SetEventListener(Handle<Object> callback, |
3109 Handle<Object> data) { | 3147 Handle<Object> data) { |
| 3148 HandleScope scope(isolate_); |
3110 GlobalHandles* global_handles = isolate_->global_handles(); | 3149 GlobalHandles* global_handles = isolate_->global_handles(); |
3111 | 3150 |
3112 // Remove existing entry. | 3151 // Clear the global handles for the event listener and the event listener data |
3113 GlobalHandles::Destroy(event_listener_.location()); | 3152 // object. |
3114 event_listener_ = Handle<Object>(); | 3153 if (!event_listener_.is_null()) { |
3115 GlobalHandles::Destroy(event_listener_data_.location()); | 3154 GlobalHandles::Destroy( |
3116 event_listener_data_ = Handle<Object>(); | 3155 reinterpret_cast<Object**>(event_listener_.location())); |
3117 | 3156 event_listener_ = Handle<Object>(); |
3118 // Set new entry. | 3157 } |
3119 if (!callback->IsUndefined() && !callback->IsNull()) { | 3158 if (!event_listener_data_.is_null()) { |
3120 event_listener_ = global_handles->Create(*callback); | 3159 GlobalHandles::Destroy( |
3121 if (data.is_null()) data = isolate_->factory()->undefined_value(); | 3160 reinterpret_cast<Object**>(event_listener_data_.location())); |
3122 event_listener_data_ = global_handles->Create(*data); | 3161 event_listener_data_ = Handle<Object>(); |
3123 } | 3162 } |
3124 | 3163 |
3125 UpdateState(); | 3164 // If there is a new debug event listener register it together with its data |
| 3165 // object. |
| 3166 if (!callback->IsUndefined() && !callback->IsNull()) { |
| 3167 event_listener_ = Handle<Object>::cast( |
| 3168 global_handles->Create(*callback)); |
| 3169 if (data.is_null()) { |
| 3170 data = isolate_->factory()->undefined_value(); |
| 3171 } |
| 3172 event_listener_data_ = Handle<Object>::cast( |
| 3173 global_handles->Create(*data)); |
| 3174 } |
| 3175 |
| 3176 ListenersChanged(); |
3126 } | 3177 } |
3127 | 3178 |
3128 | 3179 |
3129 void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) { | 3180 void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) { |
| 3181 LockGuard<RecursiveMutex> with(&debugger_access_); |
| 3182 |
3130 message_handler_ = handler; | 3183 message_handler_ = handler; |
3131 UpdateState(); | 3184 ListenersChanged(); |
3132 if (handler == NULL && isolate_->debug()->InDebugger()) { | 3185 if (handler == NULL) { |
3133 // Send an empty command to the debugger if in a break to make JavaScript | 3186 // Send an empty command to the debugger if in a break to make JavaScript |
3134 // run again if the debugger is closed. | 3187 // run again if the debugger is closed. |
3135 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | 3188 if (isolate_->debug()->InDebugger()) { |
| 3189 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
| 3190 } |
3136 } | 3191 } |
3137 } | 3192 } |
3138 | 3193 |
3139 | 3194 |
3140 void Debugger::UpdateState() { | 3195 void Debugger::ListenersChanged() { |
3141 bool activate = message_handler_ != NULL || | 3196 LockGuard<RecursiveMutex> with(&debugger_access_); |
3142 !event_listener_.is_null() || | 3197 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); |
3143 isolate_->debug()->InDebugger(); | 3198 if (is_active_) { |
3144 if (!is_active_ && activate) { | 3199 // Disable the compilation cache when the debugger is active. |
3145 // Note that the debug context could have already been loaded to | |
3146 // bootstrap test cases. | |
3147 isolate_->compilation_cache()->Disable(); | 3200 isolate_->compilation_cache()->Disable(); |
3148 activate = isolate_->debug()->Load(); | 3201 debugger_unload_pending_ = false; |
3149 } else if (is_active_ && !activate) { | 3202 } else { |
3150 isolate_->compilation_cache()->Enable(); | 3203 isolate_->compilation_cache()->Enable(); |
3151 isolate_->debug()->ClearAllBreakPoints(); | 3204 // Unload the debugger if event listener and message handler cleared. |
3152 isolate_->debug()->Unload(); | 3205 // Schedule this for later, because we may be in non-V8 thread. |
| 3206 debugger_unload_pending_ = true; |
3153 } | 3207 } |
3154 is_active_ = activate; | |
3155 // At this point the debug context is loaded iff the debugger is active. | |
3156 ASSERT(isolate_->debug()->IsLoaded() == is_active_); | |
3157 } | 3208 } |
3158 | 3209 |
3159 | 3210 |
3160 // Calls the registered debug message handler. This callback is part of the | 3211 // Calls the registered debug message handler. This callback is part of the |
3161 // public API. | 3212 // public API. |
3162 void Debugger::InvokeMessageHandler(MessageImpl message) { | 3213 void Debugger::InvokeMessageHandler(MessageImpl message) { |
3163 if (message_handler_ != NULL) message_handler_(message); | 3214 LockGuard<RecursiveMutex> with(&debugger_access_); |
| 3215 |
| 3216 if (message_handler_ != NULL) { |
| 3217 message_handler_(message); |
| 3218 } |
3164 } | 3219 } |
3165 | 3220 |
3166 | 3221 |
3167 // Puts a command coming from the public API on the queue. Creates | 3222 // Puts a command coming from the public API on the queue. Creates |
3168 // a copy of the command string managed by the debugger. Up to this | 3223 // a copy of the command string managed by the debugger. Up to this |
3169 // point, the command data was managed by the API client. Called | 3224 // point, the command data was managed by the API client. Called |
3170 // by the API client thread. | 3225 // by the API client thread. |
3171 void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command, | 3226 void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command, |
3172 v8::Debug::ClientData* client_data) { | 3227 v8::Debug::ClientData* client_data) { |
3173 // Need to cast away const. | 3228 // Need to cast away const. |
(...skipping 23 matching lines...) Expand all Loading... |
3197 | 3252 |
3198 // Set the debug command break flag to have the command processed. | 3253 // Set the debug command break flag to have the command processed. |
3199 if (!isolate_->debug()->InDebugger()) { | 3254 if (!isolate_->debug()->InDebugger()) { |
3200 isolate_->stack_guard()->RequestDebugCommand(); | 3255 isolate_->stack_guard()->RequestDebugCommand(); |
3201 } | 3256 } |
3202 } | 3257 } |
3203 | 3258 |
3204 | 3259 |
3205 MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun, | 3260 MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun, |
3206 Handle<Object> data) { | 3261 Handle<Object> data) { |
| 3262 // When calling functions in the debugger prevent it from beeing unloaded. |
| 3263 Debugger::never_unload_debugger_ = true; |
| 3264 |
3207 // Enter the debugger. | 3265 // Enter the debugger. |
3208 EnterDebugger debugger(isolate_); | 3266 EnterDebugger debugger(isolate_); |
3209 if (debugger.FailedToEnter()) { | 3267 if (debugger.FailedToEnter()) { |
3210 return isolate_->factory()->undefined_value(); | 3268 return isolate_->factory()->undefined_value(); |
3211 } | 3269 } |
3212 | 3270 |
3213 // Create the execution state. | 3271 // Create the execution state. |
3214 Handle<Object> exec_state; | 3272 Handle<Object> exec_state; |
3215 if (!MakeExecutionState().ToHandle(&exec_state)) { | 3273 if (!MakeExecutionState().ToHandle(&exec_state)) { |
3216 return isolate_->factory()->undefined_value(); | 3274 return isolate_->factory()->undefined_value(); |
3217 } | 3275 } |
3218 | 3276 |
3219 Handle<Object> argv[] = { exec_state, data }; | 3277 Handle<Object> argv[] = { exec_state, data }; |
3220 return Execution::Call( | 3278 return Execution::Call( |
3221 isolate_, | 3279 isolate_, |
3222 fun, | 3280 fun, |
3223 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(), | 3281 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(), |
3224 isolate_), | 3282 isolate_), |
3225 ARRAY_SIZE(argv), | 3283 ARRAY_SIZE(argv), |
3226 argv); | 3284 argv); |
3227 } | 3285 } |
3228 | 3286 |
3229 | 3287 |
3230 EnterDebugger::EnterDebugger(Isolate* isolate) | 3288 EnterDebugger::EnterDebugger(Isolate* isolate) |
3231 : isolate_(isolate), | 3289 : isolate_(isolate), |
3232 prev_(isolate_->debug()->debugger_entry()), | 3290 prev_(isolate_->debug()->debugger_entry()), |
| 3291 it_(isolate_), |
| 3292 has_js_frames_(!it_.done()), |
3233 save_(isolate_) { | 3293 save_(isolate_) { |
3234 Debug* debug = isolate_->debug(); | 3294 Debug* debug = isolate_->debug(); |
3235 | |
3236 // Link recursive debugger entry. | 3295 // Link recursive debugger entry. |
3237 debug->set_debugger_entry(this); | 3296 debug->set_debugger_entry(this); |
3238 | 3297 |
3239 // Store the previous break id and frame id. | 3298 // Store the previous break id and frame id. |
3240 break_id_ = debug->break_id(); | 3299 break_id_ = debug->break_id(); |
3241 break_frame_id_ = debug->break_frame_id(); | 3300 break_frame_id_ = debug->break_frame_id(); |
3242 | 3301 |
3243 // Create the new break info. If there is no JavaScript frames there is no | 3302 // Create the new break info. If there is no JavaScript frames there is no |
3244 // break frame id. | 3303 // break frame id. |
3245 JavaScriptFrameIterator it(isolate_); | 3304 if (has_js_frames_) { |
3246 has_js_frames_ = !it.done(); | 3305 debug->NewBreak(it_.frame()->id()); |
3247 debug->NewBreak(has_js_frames_ ? it.frame()->id() : StackFrame::NO_ID); | 3306 } else { |
| 3307 debug->NewBreak(StackFrame::NO_ID); |
| 3308 } |
3248 | 3309 |
3249 isolate_->debugger()->UpdateState(); | |
3250 // Make sure that debugger is loaded and enter the debugger context. | 3310 // Make sure that debugger is loaded and enter the debugger context. |
3251 // The previous context is kept in save_. | 3311 load_failed_ = !debug->Load(); |
3252 load_failed_ = !debug->IsLoaded(); | 3312 if (!load_failed_) { |
3253 if (!load_failed_) isolate_->set_context(*debug->debug_context()); | 3313 // NOTE the member variable save which saves the previous context before |
| 3314 // this change. |
| 3315 isolate_->set_context(*debug->debug_context()); |
| 3316 } |
3254 } | 3317 } |
3255 | 3318 |
3256 | 3319 |
3257 EnterDebugger::~EnterDebugger() { | 3320 EnterDebugger::~EnterDebugger() { |
3258 Debug* debug = isolate_->debug(); | 3321 Debug* debug = isolate_->debug(); |
3259 | 3322 |
3260 // Leaving this debugger entry. | |
3261 debug->set_debugger_entry(prev_); | |
3262 | |
3263 // Restore to the previous break state. | 3323 // Restore to the previous break state. |
3264 debug->SetBreak(break_frame_id_, break_id_); | 3324 debug->SetBreak(break_frame_id_, break_id_); |
3265 | 3325 |
3266 // Check for leaving the debugger. | 3326 // Check for leaving the debugger. |
3267 if (!load_failed_ && prev_ == NULL) { | 3327 if (!load_failed_ && prev_ == NULL) { |
3268 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3328 // Clear mirror cache when leaving the debugger. Skip this if there is a |
3269 // pending exception as clearing the mirror cache calls back into | 3329 // pending exception as clearing the mirror cache calls back into |
3270 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3330 // JavaScript. This can happen if the v8::Debug::Call is used in which |
3271 // case the exception should end up in the calling code. | 3331 // case the exception should end up in the calling code. |
3272 if (!isolate_->has_pending_exception()) { | 3332 if (!isolate_->has_pending_exception()) { |
(...skipping 11 matching lines...) Expand all Loading... |
3284 if (debug->has_pending_interrupt()) { | 3344 if (debug->has_pending_interrupt()) { |
3285 debug->set_has_pending_interrupt(false); | 3345 debug->set_has_pending_interrupt(false); |
3286 isolate_->stack_guard()->RequestDebugBreak(); | 3346 isolate_->stack_guard()->RequestDebugBreak(); |
3287 } | 3347 } |
3288 | 3348 |
3289 // If there are commands in the queue when leaving the debugger request | 3349 // If there are commands in the queue when leaving the debugger request |
3290 // that these commands are processed. | 3350 // that these commands are processed. |
3291 if (isolate_->debugger()->HasCommands()) { | 3351 if (isolate_->debugger()->HasCommands()) { |
3292 isolate_->stack_guard()->RequestDebugCommand(); | 3352 isolate_->stack_guard()->RequestDebugCommand(); |
3293 } | 3353 } |
| 3354 |
| 3355 // If leaving the debugger with the debugger no longer active unload it. |
| 3356 if (!isolate_->debugger()->is_active()) { |
| 3357 isolate_->debugger()->UnloadDebugger(); |
| 3358 } |
3294 } | 3359 } |
3295 | 3360 |
3296 isolate_->debugger()->UpdateState(); | 3361 // Leaving this debugger entry. |
| 3362 debug->set_debugger_entry(prev_); |
3297 } | 3363 } |
3298 | 3364 |
3299 | 3365 |
3300 MessageImpl MessageImpl::NewEvent(DebugEvent event, | 3366 MessageImpl MessageImpl::NewEvent(DebugEvent event, |
3301 bool running, | 3367 bool running, |
3302 Handle<JSObject> exec_state, | 3368 Handle<JSObject> exec_state, |
3303 Handle<JSObject> event_data) { | 3369 Handle<JSObject> event_data) { |
3304 MessageImpl message(true, event, running, | 3370 MessageImpl message(true, event, running, |
3305 exec_state, event_data, Handle<String>(), NULL); | 3371 exec_state, event_data, Handle<String>(), NULL); |
3306 return message; | 3372 return message; |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3550 logger_->DebugEvent("Put", message.text()); | 3616 logger_->DebugEvent("Put", message.text()); |
3551 } | 3617 } |
3552 | 3618 |
3553 | 3619 |
3554 void LockingCommandMessageQueue::Clear() { | 3620 void LockingCommandMessageQueue::Clear() { |
3555 LockGuard<Mutex> lock_guard(&mutex_); | 3621 LockGuard<Mutex> lock_guard(&mutex_); |
3556 queue_.Clear(); | 3622 queue_.Clear(); |
3557 } | 3623 } |
3558 | 3624 |
3559 } } // namespace v8::internal | 3625 } } // namespace v8::internal |
OLD | NEW |