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