| 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 return isolate_->debug()->debug_context(); |
| 2994 } | 2974 } |
| 2995 | 2975 |
| 2996 | 2976 |
| 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, | 2977 void Debugger::NotifyMessageHandler(v8::DebugEvent event, |
| 3014 Handle<JSObject> exec_state, | 2978 Handle<JSObject> exec_state, |
| 3015 Handle<JSObject> event_data, | 2979 Handle<JSObject> event_data, |
| 3016 bool auto_continue) { | 2980 bool auto_continue) { |
| 2981 ASSERT(is_active_); |
| 3017 HandleScope scope(isolate_); | 2982 HandleScope scope(isolate_); |
| 3018 | |
| 3019 if (!isolate_->debug()->Load()) return; | |
| 3020 | |
| 3021 // Process the individual events. | 2983 // Process the individual events. |
| 3022 bool sendEventMessage = false; | 2984 bool sendEventMessage = false; |
| 3023 switch (event) { | 2985 switch (event) { |
| 3024 case v8::Break: | 2986 case v8::Break: |
| 3025 case v8::BreakForCommand: | 2987 case v8::BreakForCommand: |
| 3026 sendEventMessage = !auto_continue; | 2988 sendEventMessage = !auto_continue; |
| 3027 break; | 2989 break; |
| 3028 case v8::Exception: | 2990 case v8::Exception: |
| 3029 sendEventMessage = true; | 2991 sendEventMessage = true; |
| 3030 break; | 2992 break; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3138 | 3100 |
| 3139 // Return from debug event processing if either the VM is put into the | 3101 // 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 | 3102 // running state (through a continue command) or auto continue is active |
| 3141 // and there are no more commands queued. | 3103 // and there are no more commands queued. |
| 3142 } while (!running || HasCommands()); | 3104 } while (!running || HasCommands()); |
| 3143 } | 3105 } |
| 3144 | 3106 |
| 3145 | 3107 |
| 3146 void Debugger::SetEventListener(Handle<Object> callback, | 3108 void Debugger::SetEventListener(Handle<Object> callback, |
| 3147 Handle<Object> data) { | 3109 Handle<Object> data) { |
| 3148 HandleScope scope(isolate_); | |
| 3149 GlobalHandles* global_handles = isolate_->global_handles(); | 3110 GlobalHandles* global_handles = isolate_->global_handles(); |
| 3150 | 3111 |
| 3151 // Clear the global handles for the event listener and the event listener data | 3112 // Remove existing entry. |
| 3152 // object. | 3113 GlobalHandles::Destroy(event_listener_.location()); |
| 3153 if (!event_listener_.is_null()) { | 3114 event_listener_ = Handle<Object>(); |
| 3154 GlobalHandles::Destroy( | 3115 GlobalHandles::Destroy(event_listener_data_.location()); |
| 3155 reinterpret_cast<Object**>(event_listener_.location())); | 3116 event_listener_data_ = Handle<Object>(); |
| 3156 event_listener_ = Handle<Object>(); | 3117 |
| 3157 } | 3118 // Set new entry. |
| 3158 if (!event_listener_data_.is_null()) { | 3119 if (!callback->IsUndefined() && !callback->IsNull()) { |
| 3159 GlobalHandles::Destroy( | 3120 event_listener_ = global_handles->Create(*callback); |
| 3160 reinterpret_cast<Object**>(event_listener_data_.location())); | 3121 if (data.is_null()) data = isolate_->factory()->undefined_value(); |
| 3161 event_listener_data_ = Handle<Object>(); | 3122 event_listener_data_ = global_handles->Create(*data); |
| 3162 } | 3123 } |
| 3163 | 3124 |
| 3164 // If there is a new debug event listener register it together with its data | 3125 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 } | 3126 } |
| 3178 | 3127 |
| 3179 | 3128 |
| 3180 void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) { | 3129 void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) { |
| 3181 LockGuard<RecursiveMutex> with(&debugger_access_); | |
| 3182 | |
| 3183 message_handler_ = handler; | 3130 message_handler_ = handler; |
| 3184 ListenersChanged(); | 3131 UpdateState(); |
| 3185 if (handler == NULL) { | 3132 if (handler == NULL && isolate_->debug()->InDebugger()) { |
| 3186 // Send an empty command to the debugger if in a break to make JavaScript | 3133 // Send an empty command to the debugger if in a break to make JavaScript |
| 3187 // run again if the debugger is closed. | 3134 // run again if the debugger is closed. |
| 3188 if (isolate_->debug()->InDebugger()) { | 3135 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
| 3189 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | |
| 3190 } | |
| 3191 } | 3136 } |
| 3192 } | 3137 } |
| 3193 | 3138 |
| 3194 | 3139 |
| 3195 void Debugger::ListenersChanged() { | 3140 void Debugger::UpdateState() { |
| 3196 LockGuard<RecursiveMutex> with(&debugger_access_); | 3141 bool activate = message_handler_ != NULL || |
| 3197 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); | 3142 !event_listener_.is_null() || |
| 3198 if (is_active_) { | 3143 isolate_->debug()->InDebugger(); |
| 3199 // Disable the compilation cache when the debugger is active. | 3144 if (!is_active_ && activate) { |
| 3145 // Note that the debug context could have already been loaded to |
| 3146 // bootstrap test cases. |
| 3200 isolate_->compilation_cache()->Disable(); | 3147 isolate_->compilation_cache()->Disable(); |
| 3201 debugger_unload_pending_ = false; | 3148 activate = isolate_->debug()->Load(); |
| 3202 } else { | 3149 } else if (is_active_ && !activate) { |
| 3203 isolate_->compilation_cache()->Enable(); | 3150 isolate_->compilation_cache()->Enable(); |
| 3204 // Unload the debugger if event listener and message handler cleared. | 3151 isolate_->debug()->ClearAllBreakPoints(); |
| 3205 // Schedule this for later, because we may be in non-V8 thread. | 3152 isolate_->debug()->Unload(); |
| 3206 debugger_unload_pending_ = true; | |
| 3207 } | 3153 } |
| 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_); |
| 3208 } | 3157 } |
| 3209 | 3158 |
| 3210 | 3159 |
| 3211 // Calls the registered debug message handler. This callback is part of the | 3160 // Calls the registered debug message handler. This callback is part of the |
| 3212 // public API. | 3161 // public API. |
| 3213 void Debugger::InvokeMessageHandler(MessageImpl message) { | 3162 void Debugger::InvokeMessageHandler(MessageImpl message) { |
| 3214 LockGuard<RecursiveMutex> with(&debugger_access_); | 3163 if (message_handler_ != NULL) message_handler_(message); |
| 3215 | |
| 3216 if (message_handler_ != NULL) { | |
| 3217 message_handler_(message); | |
| 3218 } | |
| 3219 } | 3164 } |
| 3220 | 3165 |
| 3221 | 3166 |
| 3222 // Puts a command coming from the public API on the queue. Creates | 3167 // 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 | 3168 // 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 | 3169 // point, the command data was managed by the API client. Called |
| 3225 // by the API client thread. | 3170 // by the API client thread. |
| 3226 void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command, | 3171 void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command, |
| 3227 v8::Debug::ClientData* client_data) { | 3172 v8::Debug::ClientData* client_data) { |
| 3228 // Need to cast away const. | 3173 // Need to cast away const. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3252 | 3197 |
| 3253 // Set the debug command break flag to have the command processed. | 3198 // Set the debug command break flag to have the command processed. |
| 3254 if (!isolate_->debug()->InDebugger()) { | 3199 if (!isolate_->debug()->InDebugger()) { |
| 3255 isolate_->stack_guard()->RequestDebugCommand(); | 3200 isolate_->stack_guard()->RequestDebugCommand(); |
| 3256 } | 3201 } |
| 3257 } | 3202 } |
| 3258 | 3203 |
| 3259 | 3204 |
| 3260 MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun, | 3205 MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun, |
| 3261 Handle<Object> data) { | 3206 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. | 3207 // Enter the debugger. |
| 3266 EnterDebugger debugger(isolate_); | 3208 EnterDebugger debugger(isolate_); |
| 3267 if (debugger.FailedToEnter()) { | 3209 if (debugger.FailedToEnter()) { |
| 3268 return isolate_->factory()->undefined_value(); | 3210 return isolate_->factory()->undefined_value(); |
| 3269 } | 3211 } |
| 3270 | 3212 |
| 3271 // Create the execution state. | 3213 // Create the execution state. |
| 3272 Handle<Object> exec_state; | 3214 Handle<Object> exec_state; |
| 3273 if (!MakeExecutionState().ToHandle(&exec_state)) { | 3215 if (!MakeExecutionState().ToHandle(&exec_state)) { |
| 3274 return isolate_->factory()->undefined_value(); | 3216 return isolate_->factory()->undefined_value(); |
| 3275 } | 3217 } |
| 3276 | 3218 |
| 3277 Handle<Object> argv[] = { exec_state, data }; | 3219 Handle<Object> argv[] = { exec_state, data }; |
| 3278 return Execution::Call( | 3220 return Execution::Call( |
| 3279 isolate_, | 3221 isolate_, |
| 3280 fun, | 3222 fun, |
| 3281 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(), | 3223 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(), |
| 3282 isolate_), | 3224 isolate_), |
| 3283 ARRAY_SIZE(argv), | 3225 ARRAY_SIZE(argv), |
| 3284 argv); | 3226 argv); |
| 3285 } | 3227 } |
| 3286 | 3228 |
| 3287 | 3229 |
| 3288 EnterDebugger::EnterDebugger(Isolate* isolate) | 3230 EnterDebugger::EnterDebugger(Isolate* isolate) |
| 3289 : isolate_(isolate), | 3231 : isolate_(isolate), |
| 3290 prev_(isolate_->debug()->debugger_entry()), | 3232 prev_(isolate_->debug()->debugger_entry()), |
| 3291 it_(isolate_), | |
| 3292 has_js_frames_(!it_.done()), | |
| 3293 save_(isolate_) { | 3233 save_(isolate_) { |
| 3294 Debug* debug = isolate_->debug(); | 3234 Debug* debug = isolate_->debug(); |
| 3235 |
| 3295 // Link recursive debugger entry. | 3236 // Link recursive debugger entry. |
| 3296 debug->set_debugger_entry(this); | 3237 debug->set_debugger_entry(this); |
| 3297 | 3238 |
| 3298 // Store the previous break id and frame id. | 3239 // Store the previous break id and frame id. |
| 3299 break_id_ = debug->break_id(); | 3240 break_id_ = debug->break_id(); |
| 3300 break_frame_id_ = debug->break_frame_id(); | 3241 break_frame_id_ = debug->break_frame_id(); |
| 3301 | 3242 |
| 3302 // Create the new break info. If there is no JavaScript frames there is no | 3243 // Create the new break info. If there is no JavaScript frames there is no |
| 3303 // break frame id. | 3244 // break frame id. |
| 3304 if (has_js_frames_) { | 3245 JavaScriptFrameIterator it(isolate_); |
| 3305 debug->NewBreak(it_.frame()->id()); | 3246 has_js_frames_ = !it.done(); |
| 3306 } else { | 3247 debug->NewBreak(has_js_frames_ ? it.frame()->id() : StackFrame::NO_ID); |
| 3307 debug->NewBreak(StackFrame::NO_ID); | |
| 3308 } | |
| 3309 | 3248 |
| 3249 isolate_->debugger()->UpdateState(); |
| 3310 // Make sure that debugger is loaded and enter the debugger context. | 3250 // Make sure that debugger is loaded and enter the debugger context. |
| 3311 load_failed_ = !debug->Load(); | 3251 // The previous context is kept in save_. |
| 3312 if (!load_failed_) { | 3252 load_failed_ = !debug->IsLoaded(); |
| 3313 // NOTE the member variable save which saves the previous context before | 3253 if (!load_failed_) isolate_->set_context(*debug->debug_context()); |
| 3314 // this change. | |
| 3315 isolate_->set_context(*debug->debug_context()); | |
| 3316 } | |
| 3317 } | 3254 } |
| 3318 | 3255 |
| 3319 | 3256 |
| 3320 EnterDebugger::~EnterDebugger() { | 3257 EnterDebugger::~EnterDebugger() { |
| 3321 Debug* debug = isolate_->debug(); | 3258 Debug* debug = isolate_->debug(); |
| 3322 | 3259 |
| 3260 // Leaving this debugger entry. |
| 3261 debug->set_debugger_entry(prev_); |
| 3262 |
| 3323 // Restore to the previous break state. | 3263 // Restore to the previous break state. |
| 3324 debug->SetBreak(break_frame_id_, break_id_); | 3264 debug->SetBreak(break_frame_id_, break_id_); |
| 3325 | 3265 |
| 3326 // Check for leaving the debugger. | 3266 // Check for leaving the debugger. |
| 3327 if (!load_failed_ && prev_ == NULL) { | 3267 if (!load_failed_ && prev_ == NULL) { |
| 3328 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3268 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 3329 // pending exception as clearing the mirror cache calls back into | 3269 // pending exception as clearing the mirror cache calls back into |
| 3330 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3270 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 3331 // case the exception should end up in the calling code. | 3271 // case the exception should end up in the calling code. |
| 3332 if (!isolate_->has_pending_exception()) { | 3272 if (!isolate_->has_pending_exception()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3344 if (debug->has_pending_interrupt()) { | 3284 if (debug->has_pending_interrupt()) { |
| 3345 debug->set_has_pending_interrupt(false); | 3285 debug->set_has_pending_interrupt(false); |
| 3346 isolate_->stack_guard()->RequestDebugBreak(); | 3286 isolate_->stack_guard()->RequestDebugBreak(); |
| 3347 } | 3287 } |
| 3348 | 3288 |
| 3349 // If there are commands in the queue when leaving the debugger request | 3289 // If there are commands in the queue when leaving the debugger request |
| 3350 // that these commands are processed. | 3290 // that these commands are processed. |
| 3351 if (isolate_->debugger()->HasCommands()) { | 3291 if (isolate_->debugger()->HasCommands()) { |
| 3352 isolate_->stack_guard()->RequestDebugCommand(); | 3292 isolate_->stack_guard()->RequestDebugCommand(); |
| 3353 } | 3293 } |
| 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 } | 3294 } |
| 3360 | 3295 |
| 3361 // Leaving this debugger entry. | 3296 isolate_->debugger()->UpdateState(); |
| 3362 debug->set_debugger_entry(prev_); | |
| 3363 } | 3297 } |
| 3364 | 3298 |
| 3365 | 3299 |
| 3366 MessageImpl MessageImpl::NewEvent(DebugEvent event, | 3300 MessageImpl MessageImpl::NewEvent(DebugEvent event, |
| 3367 bool running, | 3301 bool running, |
| 3368 Handle<JSObject> exec_state, | 3302 Handle<JSObject> exec_state, |
| 3369 Handle<JSObject> event_data) { | 3303 Handle<JSObject> event_data) { |
| 3370 MessageImpl message(true, event, running, | 3304 MessageImpl message(true, event, running, |
| 3371 exec_state, event_data, Handle<String>(), NULL); | 3305 exec_state, event_data, Handle<String>(), NULL); |
| 3372 return message; | 3306 return message; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3616 logger_->DebugEvent("Put", message.text()); | 3550 logger_->DebugEvent("Put", message.text()); |
| 3617 } | 3551 } |
| 3618 | 3552 |
| 3619 | 3553 |
| 3620 void LockingCommandMessageQueue::Clear() { | 3554 void LockingCommandMessageQueue::Clear() { |
| 3621 LockGuard<Mutex> lock_guard(&mutex_); | 3555 LockGuard<Mutex> lock_guard(&mutex_); |
| 3622 queue_.Clear(); | 3556 queue_.Clear(); |
| 3623 } | 3557 } |
| 3624 | 3558 |
| 3625 } } // namespace v8::internal | 3559 } } // namespace v8::internal |
| OLD | NEW |