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 |