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