| 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 2614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2625 | 2625 |
| 2626 Debugger::Debugger(Isolate* isolate) | 2626 Debugger::Debugger(Isolate* isolate) |
| 2627 : event_listener_(Handle<Object>()), | 2627 : event_listener_(Handle<Object>()), |
| 2628 event_listener_data_(Handle<Object>()), | 2628 event_listener_data_(Handle<Object>()), |
| 2629 is_active_(false), | 2629 is_active_(false), |
| 2630 ignore_debugger_(false), | 2630 ignore_debugger_(false), |
| 2631 live_edit_enabled_(true), | 2631 live_edit_enabled_(true), |
| 2632 never_unload_debugger_(false), | 2632 never_unload_debugger_(false), |
| 2633 message_handler_(NULL), | 2633 message_handler_(NULL), |
| 2634 debugger_unload_pending_(false), | 2634 debugger_unload_pending_(false), |
| 2635 debug_message_dispatch_handler_(NULL), | |
| 2636 message_dispatch_helper_thread_(NULL), | |
| 2637 agent_(NULL), | |
| 2638 command_queue_(isolate->logger(), kQueueInitialSize), | 2635 command_queue_(isolate->logger(), kQueueInitialSize), |
| 2639 command_received_(0), | 2636 command_received_(0), |
| 2640 event_command_queue_(isolate->logger(), kQueueInitialSize), | 2637 event_command_queue_(isolate->logger(), kQueueInitialSize), |
| 2641 isolate_(isolate) { | 2638 isolate_(isolate) { |
| 2642 } | 2639 } |
| 2643 | 2640 |
| 2644 | 2641 |
| 2645 Debugger::~Debugger() {} | 2642 Debugger::~Debugger() {} |
| 2646 | 2643 |
| 2647 | 2644 |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3182 | 3179 |
| 3183 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) { | 3180 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) { |
| 3184 LockGuard<RecursiveMutex> with(&debugger_access_); | 3181 LockGuard<RecursiveMutex> with(&debugger_access_); |
| 3185 | 3182 |
| 3186 message_handler_ = handler; | 3183 message_handler_ = handler; |
| 3187 ListenersChanged(); | 3184 ListenersChanged(); |
| 3188 if (handler == NULL) { | 3185 if (handler == NULL) { |
| 3189 // 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 |
| 3190 // run again if the debugger is closed. | 3187 // run again if the debugger is closed. |
| 3191 if (isolate_->debug()->InDebugger()) { | 3188 if (isolate_->debug()->InDebugger()) { |
| 3192 ProcessCommand(Vector<const uint16_t>::empty()); | 3189 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
| 3193 } | 3190 } |
| 3194 } | 3191 } |
| 3195 } | 3192 } |
| 3196 | 3193 |
| 3197 | 3194 |
| 3198 void Debugger::ListenersChanged() { | 3195 void Debugger::ListenersChanged() { |
| 3199 LockGuard<RecursiveMutex> with(&debugger_access_); | 3196 LockGuard<RecursiveMutex> with(&debugger_access_); |
| 3200 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); | 3197 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); |
| 3201 if (is_active_) { | 3198 if (is_active_) { |
| 3202 // Disable the compilation cache when the debugger is active. | 3199 // Disable the compilation cache when the debugger is active. |
| 3203 isolate_->compilation_cache()->Disable(); | 3200 isolate_->compilation_cache()->Disable(); |
| 3204 debugger_unload_pending_ = false; | 3201 debugger_unload_pending_ = false; |
| 3205 } else { | 3202 } else { |
| 3206 isolate_->compilation_cache()->Enable(); | 3203 isolate_->compilation_cache()->Enable(); |
| 3207 // Unload the debugger if event listener and message handler cleared. | 3204 // Unload the debugger if event listener and message handler cleared. |
| 3208 // Schedule this for later, because we may be in non-V8 thread. | 3205 // Schedule this for later, because we may be in non-V8 thread. |
| 3209 debugger_unload_pending_ = true; | 3206 debugger_unload_pending_ = true; |
| 3210 } | 3207 } |
| 3211 } | 3208 } |
| 3212 | 3209 |
| 3213 | 3210 |
| 3214 void Debugger::SetDebugMessageDispatchHandler( | |
| 3215 v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) { | |
| 3216 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); | |
| 3217 debug_message_dispatch_handler_ = handler; | |
| 3218 | |
| 3219 if (provide_locker && message_dispatch_helper_thread_ == NULL) { | |
| 3220 message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_); | |
| 3221 message_dispatch_helper_thread_->Start(); | |
| 3222 } | |
| 3223 } | |
| 3224 | |
| 3225 | |
| 3226 // 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 |
| 3227 // public API. | 3212 // public API. |
| 3228 void Debugger::InvokeMessageHandler(MessageImpl message) { | 3213 void Debugger::InvokeMessageHandler(MessageImpl message) { |
| 3229 LockGuard<RecursiveMutex> with(&debugger_access_); | 3214 LockGuard<RecursiveMutex> with(&debugger_access_); |
| 3230 | 3215 |
| 3231 if (message_handler_ != NULL) { | 3216 if (message_handler_ != NULL) { |
| 3232 message_handler_(message); | 3217 message_handler_(message); |
| 3233 } | 3218 } |
| 3234 } | 3219 } |
| 3235 | 3220 |
| 3236 | 3221 |
| 3237 // 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 |
| 3238 // 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 |
| 3239 // point, the command data was managed by the API client. Called | 3224 // point, the command data was managed by the API client. Called |
| 3240 // by the API client thread. | 3225 // by the API client thread. |
| 3241 void Debugger::ProcessCommand(Vector<const uint16_t> command, | 3226 void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command, |
| 3242 v8::Debug::ClientData* client_data) { | 3227 v8::Debug::ClientData* client_data) { |
| 3243 // Need to cast away const. | 3228 // Need to cast away const. |
| 3244 CommandMessage message = CommandMessage::New( | 3229 CommandMessage message = CommandMessage::New( |
| 3245 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | 3230 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
| 3246 command.length()), | 3231 command.length()), |
| 3247 client_data); | 3232 client_data); |
| 3248 isolate_->logger()->DebugTag("Put command on command_queue."); | 3233 isolate_->logger()->DebugTag("Put command on command_queue."); |
| 3249 command_queue_.Put(message); | 3234 command_queue_.Put(message); |
| 3250 command_received_.Signal(); | 3235 command_received_.Signal(); |
| 3251 | 3236 |
| 3252 // Set the debug command break flag to have the command processed. | 3237 // Set the debug command break flag to have the command processed. |
| 3253 if (!isolate_->debug()->InDebugger()) { | 3238 if (!isolate_->debug()->InDebugger()) { |
| 3254 isolate_->stack_guard()->RequestDebugCommand(); | 3239 isolate_->stack_guard()->RequestDebugCommand(); |
| 3255 } | 3240 } |
| 3256 | |
| 3257 MessageDispatchHelperThread* dispatch_thread; | |
| 3258 { | |
| 3259 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); | |
| 3260 dispatch_thread = message_dispatch_helper_thread_; | |
| 3261 } | |
| 3262 | |
| 3263 if (dispatch_thread == NULL) { | |
| 3264 CallMessageDispatchHandler(); | |
| 3265 } else { | |
| 3266 dispatch_thread->Schedule(); | |
| 3267 } | |
| 3268 } | 3241 } |
| 3269 | 3242 |
| 3270 | 3243 |
| 3271 bool Debugger::HasCommands() { | 3244 bool Debugger::HasCommands() { |
| 3272 return !command_queue_.IsEmpty(); | 3245 return !command_queue_.IsEmpty(); |
| 3273 } | 3246 } |
| 3274 | 3247 |
| 3275 | 3248 |
| 3276 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { | 3249 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { |
| 3277 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); | 3250 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3305 return Execution::Call( | 3278 return Execution::Call( |
| 3306 isolate_, | 3279 isolate_, |
| 3307 fun, | 3280 fun, |
| 3308 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(), | 3281 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(), |
| 3309 isolate_), | 3282 isolate_), |
| 3310 ARRAY_SIZE(argv), | 3283 ARRAY_SIZE(argv), |
| 3311 argv); | 3284 argv); |
| 3312 } | 3285 } |
| 3313 | 3286 |
| 3314 | 3287 |
| 3315 static void StubMessageHandler2(const v8::Debug::Message& message) { | |
| 3316 // Simply ignore message. | |
| 3317 } | |
| 3318 | |
| 3319 | |
| 3320 bool Debugger::StartAgent(const char* name, int port, | |
| 3321 bool wait_for_connection) { | |
| 3322 if (wait_for_connection) { | |
| 3323 // Suspend V8 if it is already running or set V8 to suspend whenever | |
| 3324 // it starts. | |
| 3325 // Provide stub message handler; V8 auto-continues each suspend | |
| 3326 // when there is no message handler; we doesn't need it. | |
| 3327 // Once become suspended, V8 will stay so indefinitely long, until remote | |
| 3328 // debugger connects and issues "continue" command. | |
| 3329 Debugger::message_handler_ = StubMessageHandler2; | |
| 3330 v8::Debug::DebugBreak(reinterpret_cast<v8::Isolate*>(isolate_)); | |
| 3331 } | |
| 3332 | |
| 3333 if (agent_ == NULL) { | |
| 3334 agent_ = new DebuggerAgent(isolate_, name, port); | |
| 3335 agent_->Start(); | |
| 3336 } | |
| 3337 return true; | |
| 3338 } | |
| 3339 | |
| 3340 | |
| 3341 void Debugger::StopAgent() { | |
| 3342 if (agent_ != NULL) { | |
| 3343 agent_->Shutdown(); | |
| 3344 agent_->Join(); | |
| 3345 delete agent_; | |
| 3346 agent_ = NULL; | |
| 3347 } | |
| 3348 } | |
| 3349 | |
| 3350 | |
| 3351 void Debugger::WaitForAgent() { | |
| 3352 if (agent_ != NULL) | |
| 3353 agent_->WaitUntilListening(); | |
| 3354 } | |
| 3355 | |
| 3356 | |
| 3357 void Debugger::CallMessageDispatchHandler() { | |
| 3358 v8::Debug::DebugMessageDispatchHandler handler; | |
| 3359 { | |
| 3360 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); | |
| 3361 handler = Debugger::debug_message_dispatch_handler_; | |
| 3362 } | |
| 3363 if (handler != NULL) { | |
| 3364 handler(); | |
| 3365 } | |
| 3366 } | |
| 3367 | |
| 3368 | |
| 3369 EnterDebugger::EnterDebugger(Isolate* isolate) | 3288 EnterDebugger::EnterDebugger(Isolate* isolate) |
| 3370 : isolate_(isolate), | 3289 : isolate_(isolate), |
| 3371 prev_(isolate_->debug()->debugger_entry()), | 3290 prev_(isolate_->debug()->debugger_entry()), |
| 3372 it_(isolate_), | 3291 it_(isolate_), |
| 3373 has_js_frames_(!it_.done()), | 3292 has_js_frames_(!it_.done()), |
| 3374 save_(isolate_) { | 3293 save_(isolate_) { |
| 3375 Debug* debug = isolate_->debug(); | 3294 Debug* debug = isolate_->debug(); |
| 3376 // Link recursive debugger entry. | 3295 // Link recursive debugger entry. |
| 3377 debug->set_debugger_entry(this); | 3296 debug->set_debugger_entry(this); |
| 3378 | 3297 |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3696 queue_.Put(message); | 3615 queue_.Put(message); |
| 3697 logger_->DebugEvent("Put", message.text()); | 3616 logger_->DebugEvent("Put", message.text()); |
| 3698 } | 3617 } |
| 3699 | 3618 |
| 3700 | 3619 |
| 3701 void LockingCommandMessageQueue::Clear() { | 3620 void LockingCommandMessageQueue::Clear() { |
| 3702 LockGuard<Mutex> lock_guard(&mutex_); | 3621 LockGuard<Mutex> lock_guard(&mutex_); |
| 3703 queue_.Clear(); | 3622 queue_.Clear(); |
| 3704 } | 3623 } |
| 3705 | 3624 |
| 3706 | |
| 3707 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate) | |
| 3708 : Thread("v8:MsgDispHelpr"), | |
| 3709 isolate_(isolate), sem_(0), | |
| 3710 already_signalled_(false) { | |
| 3711 } | |
| 3712 | |
| 3713 | |
| 3714 void MessageDispatchHelperThread::Schedule() { | |
| 3715 { | |
| 3716 LockGuard<Mutex> lock_guard(&mutex_); | |
| 3717 if (already_signalled_) { | |
| 3718 return; | |
| 3719 } | |
| 3720 already_signalled_ = true; | |
| 3721 } | |
| 3722 sem_.Signal(); | |
| 3723 } | |
| 3724 | |
| 3725 | |
| 3726 void MessageDispatchHelperThread::Run() { | |
| 3727 while (true) { | |
| 3728 sem_.Wait(); | |
| 3729 { | |
| 3730 LockGuard<Mutex> lock_guard(&mutex_); | |
| 3731 already_signalled_ = false; | |
| 3732 } | |
| 3733 { | |
| 3734 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); | |
| 3735 isolate_->debugger()->CallMessageDispatchHandler(); | |
| 3736 } | |
| 3737 } | |
| 3738 } | |
| 3739 | |
| 3740 } } // namespace v8::internal | 3625 } } // namespace v8::internal |
| OLD | NEW |