| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 2594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2605 event_listener_(Handle<Object>()), | 2605 event_listener_(Handle<Object>()), |
| 2606 event_listener_data_(Handle<Object>()), | 2606 event_listener_data_(Handle<Object>()), |
| 2607 compiling_natives_(false), | 2607 compiling_natives_(false), |
| 2608 is_loading_debugger_(false), | 2608 is_loading_debugger_(false), |
| 2609 live_edit_enabled_(true), | 2609 live_edit_enabled_(true), |
| 2610 never_unload_debugger_(false), | 2610 never_unload_debugger_(false), |
| 2611 force_debugger_active_(false), | 2611 force_debugger_active_(false), |
| 2612 message_handler_(NULL), | 2612 message_handler_(NULL), |
| 2613 debugger_unload_pending_(false), | 2613 debugger_unload_pending_(false), |
| 2614 host_dispatch_handler_(NULL), | 2614 host_dispatch_handler_(NULL), |
| 2615 dispatch_handler_access_(OS::CreateMutex()), | |
| 2616 debug_message_dispatch_handler_(NULL), | 2615 debug_message_dispatch_handler_(NULL), |
| 2617 message_dispatch_helper_thread_(NULL), | 2616 message_dispatch_helper_thread_(NULL), |
| 2618 host_dispatch_micros_(100 * 1000), | 2617 host_dispatch_micros_(100 * 1000), |
| 2619 agent_(NULL), | 2618 agent_(NULL), |
| 2620 command_queue_(isolate->logger(), kQueueInitialSize), | 2619 command_queue_(isolate->logger(), kQueueInitialSize), |
| 2621 command_received_(OS::CreateSemaphore(0)), | 2620 command_received_(OS::CreateSemaphore(0)), |
| 2622 event_command_queue_(isolate->logger(), kQueueInitialSize), | 2621 event_command_queue_(isolate->logger(), kQueueInitialSize), |
| 2623 isolate_(isolate) { | 2622 isolate_(isolate) { |
| 2624 } | 2623 } |
| 2625 | 2624 |
| 2626 | 2625 |
| 2627 Debugger::~Debugger() { | 2626 Debugger::~Debugger() { |
| 2628 delete dispatch_handler_access_; | |
| 2629 dispatch_handler_access_ = 0; | |
| 2630 delete command_received_; | 2627 delete command_received_; |
| 2631 command_received_ = 0; | 2628 command_received_ = 0; |
| 2632 } | 2629 } |
| 2633 | 2630 |
| 2634 | 2631 |
| 2635 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, | 2632 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, |
| 2636 int argc, | 2633 int argc, |
| 2637 Handle<Object> argv[], | 2634 Handle<Object> argv[], |
| 2638 bool* caught_exception) { | 2635 bool* caught_exception) { |
| 2639 ASSERT(isolate_->context() == *isolate_->debug()->debug_context()); | 2636 ASSERT(isolate_->context() == *isolate_->debug()->debug_context()); |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3265 } | 3262 } |
| 3266 event_listener_data_ = Handle<Object>::cast( | 3263 event_listener_data_ = Handle<Object>::cast( |
| 3267 global_handles->Create(*data)); | 3264 global_handles->Create(*data)); |
| 3268 } | 3265 } |
| 3269 | 3266 |
| 3270 ListenersChanged(); | 3267 ListenersChanged(); |
| 3271 } | 3268 } |
| 3272 | 3269 |
| 3273 | 3270 |
| 3274 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) { | 3271 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) { |
| 3275 ScopedLock with(debugger_access_); | 3272 LockGuard<RecursiveMutex> with(debugger_access_); |
| 3276 | 3273 |
| 3277 message_handler_ = handler; | 3274 message_handler_ = handler; |
| 3278 ListenersChanged(); | 3275 ListenersChanged(); |
| 3279 if (handler == NULL) { | 3276 if (handler == NULL) { |
| 3280 // Send an empty command to the debugger if in a break to make JavaScript | 3277 // Send an empty command to the debugger if in a break to make JavaScript |
| 3281 // run again if the debugger is closed. | 3278 // run again if the debugger is closed. |
| 3282 if (isolate_->debug()->InDebugger()) { | 3279 if (isolate_->debug()->InDebugger()) { |
| 3283 ProcessCommand(Vector<const uint16_t>::empty()); | 3280 ProcessCommand(Vector<const uint16_t>::empty()); |
| 3284 } | 3281 } |
| 3285 } | 3282 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3302 | 3299 |
| 3303 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, | 3300 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, |
| 3304 int period) { | 3301 int period) { |
| 3305 host_dispatch_handler_ = handler; | 3302 host_dispatch_handler_ = handler; |
| 3306 host_dispatch_micros_ = period * 1000; | 3303 host_dispatch_micros_ = period * 1000; |
| 3307 } | 3304 } |
| 3308 | 3305 |
| 3309 | 3306 |
| 3310 void Debugger::SetDebugMessageDispatchHandler( | 3307 void Debugger::SetDebugMessageDispatchHandler( |
| 3311 v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) { | 3308 v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) { |
| 3312 ScopedLock with(dispatch_handler_access_); | 3309 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); |
| 3313 debug_message_dispatch_handler_ = handler; | 3310 debug_message_dispatch_handler_ = handler; |
| 3314 | 3311 |
| 3315 if (provide_locker && message_dispatch_helper_thread_ == NULL) { | 3312 if (provide_locker && message_dispatch_helper_thread_ == NULL) { |
| 3316 message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_); | 3313 message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_); |
| 3317 message_dispatch_helper_thread_->Start(); | 3314 message_dispatch_helper_thread_->Start(); |
| 3318 } | 3315 } |
| 3319 } | 3316 } |
| 3320 | 3317 |
| 3321 | 3318 |
| 3322 // Calls the registered debug message handler. This callback is part of the | 3319 // Calls the registered debug message handler. This callback is part of the |
| 3323 // public API. | 3320 // public API. |
| 3324 void Debugger::InvokeMessageHandler(MessageImpl message) { | 3321 void Debugger::InvokeMessageHandler(MessageImpl message) { |
| 3325 ScopedLock with(debugger_access_); | 3322 LockGuard<RecursiveMutex> with(debugger_access_); |
| 3326 | 3323 |
| 3327 if (message_handler_ != NULL) { | 3324 if (message_handler_ != NULL) { |
| 3328 message_handler_(message); | 3325 message_handler_(message); |
| 3329 } | 3326 } |
| 3330 } | 3327 } |
| 3331 | 3328 |
| 3332 | 3329 |
| 3333 // Puts a command coming from the public API on the queue. Creates | 3330 // Puts a command coming from the public API on the queue. Creates |
| 3334 // a copy of the command string managed by the debugger. Up to this | 3331 // a copy of the command string managed by the debugger. Up to this |
| 3335 // point, the command data was managed by the API client. Called | 3332 // point, the command data was managed by the API client. Called |
| 3336 // by the API client thread. | 3333 // by the API client thread. |
| 3337 void Debugger::ProcessCommand(Vector<const uint16_t> command, | 3334 void Debugger::ProcessCommand(Vector<const uint16_t> command, |
| 3338 v8::Debug::ClientData* client_data) { | 3335 v8::Debug::ClientData* client_data) { |
| 3339 // Need to cast away const. | 3336 // Need to cast away const. |
| 3340 CommandMessage message = CommandMessage::New( | 3337 CommandMessage message = CommandMessage::New( |
| 3341 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | 3338 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
| 3342 command.length()), | 3339 command.length()), |
| 3343 client_data); | 3340 client_data); |
| 3344 isolate_->logger()->DebugTag("Put command on command_queue."); | 3341 isolate_->logger()->DebugTag("Put command on command_queue."); |
| 3345 command_queue_.Put(message); | 3342 command_queue_.Put(message); |
| 3346 command_received_->Signal(); | 3343 command_received_->Signal(); |
| 3347 | 3344 |
| 3348 // Set the debug command break flag to have the command processed. | 3345 // Set the debug command break flag to have the command processed. |
| 3349 if (!isolate_->debug()->InDebugger()) { | 3346 if (!isolate_->debug()->InDebugger()) { |
| 3350 isolate_->stack_guard()->DebugCommand(); | 3347 isolate_->stack_guard()->DebugCommand(); |
| 3351 } | 3348 } |
| 3352 | 3349 |
| 3353 MessageDispatchHelperThread* dispatch_thread; | 3350 MessageDispatchHelperThread* dispatch_thread; |
| 3354 { | 3351 { |
| 3355 ScopedLock with(dispatch_handler_access_); | 3352 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); |
| 3356 dispatch_thread = message_dispatch_helper_thread_; | 3353 dispatch_thread = message_dispatch_helper_thread_; |
| 3357 } | 3354 } |
| 3358 | 3355 |
| 3359 if (dispatch_thread == NULL) { | 3356 if (dispatch_thread == NULL) { |
| 3360 CallMessageDispatchHandler(); | 3357 CallMessageDispatchHandler(); |
| 3361 } else { | 3358 } else { |
| 3362 dispatch_thread->Schedule(); | 3359 dispatch_thread->Schedule(); |
| 3363 } | 3360 } |
| 3364 } | 3361 } |
| 3365 | 3362 |
| 3366 | 3363 |
| 3367 bool Debugger::HasCommands() { | 3364 bool Debugger::HasCommands() { |
| 3368 return !command_queue_.IsEmpty(); | 3365 return !command_queue_.IsEmpty(); |
| 3369 } | 3366 } |
| 3370 | 3367 |
| 3371 | 3368 |
| 3372 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { | 3369 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { |
| 3373 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); | 3370 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); |
| 3374 event_command_queue_.Put(message); | 3371 event_command_queue_.Put(message); |
| 3375 | 3372 |
| 3376 // Set the debug command break flag to have the command processed. | 3373 // Set the debug command break flag to have the command processed. |
| 3377 if (!isolate_->debug()->InDebugger()) { | 3374 if (!isolate_->debug()->InDebugger()) { |
| 3378 isolate_->stack_guard()->DebugCommand(); | 3375 isolate_->stack_guard()->DebugCommand(); |
| 3379 } | 3376 } |
| 3380 } | 3377 } |
| 3381 | 3378 |
| 3382 | 3379 |
| 3383 bool Debugger::IsDebuggerActive() { | 3380 bool Debugger::IsDebuggerActive() { |
| 3384 ScopedLock with(debugger_access_); | 3381 LockGuard<RecursiveMutex> with(debugger_access_); |
| 3385 | 3382 |
| 3386 return message_handler_ != NULL || | 3383 return message_handler_ != NULL || |
| 3387 !event_listener_.is_null() || | 3384 !event_listener_.is_null() || |
| 3388 force_debugger_active_; | 3385 force_debugger_active_; |
| 3389 } | 3386 } |
| 3390 | 3387 |
| 3391 | 3388 |
| 3392 Handle<Object> Debugger::Call(Handle<JSFunction> fun, | 3389 Handle<Object> Debugger::Call(Handle<JSFunction> fun, |
| 3393 Handle<Object> data, | 3390 Handle<Object> data, |
| 3394 bool* pending_exception) { | 3391 bool* pending_exception) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3465 void Debugger::WaitForAgent() { | 3462 void Debugger::WaitForAgent() { |
| 3466 ASSERT(Isolate::Current() == isolate_); | 3463 ASSERT(Isolate::Current() == isolate_); |
| 3467 if (agent_ != NULL) | 3464 if (agent_ != NULL) |
| 3468 agent_->WaitUntilListening(); | 3465 agent_->WaitUntilListening(); |
| 3469 } | 3466 } |
| 3470 | 3467 |
| 3471 | 3468 |
| 3472 void Debugger::CallMessageDispatchHandler() { | 3469 void Debugger::CallMessageDispatchHandler() { |
| 3473 v8::Debug::DebugMessageDispatchHandler handler; | 3470 v8::Debug::DebugMessageDispatchHandler handler; |
| 3474 { | 3471 { |
| 3475 ScopedLock with(dispatch_handler_access_); | 3472 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); |
| 3476 handler = Debugger::debug_message_dispatch_handler_; | 3473 handler = Debugger::debug_message_dispatch_handler_; |
| 3477 } | 3474 } |
| 3478 if (handler != NULL) { | 3475 if (handler != NULL) { |
| 3479 handler(); | 3476 handler(); |
| 3480 } | 3477 } |
| 3481 } | 3478 } |
| 3482 | 3479 |
| 3483 | 3480 |
| 3484 EnterDebugger::EnterDebugger() | 3481 EnterDebugger::EnterDebugger() |
| 3485 : isolate_(Isolate::Current()), | 3482 : isolate_(Isolate::Current()), |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3786 CommandMessage* array_to_free = messages_; | 3783 CommandMessage* array_to_free = messages_; |
| 3787 *this = new_queue; | 3784 *this = new_queue; |
| 3788 new_queue.messages_ = array_to_free; | 3785 new_queue.messages_ = array_to_free; |
| 3789 // Make the new_queue empty so that it doesn't call Dispose on any messages. | 3786 // Make the new_queue empty so that it doesn't call Dispose on any messages. |
| 3790 new_queue.start_ = new_queue.end_; | 3787 new_queue.start_ = new_queue.end_; |
| 3791 // Automatic destructor called on new_queue, freeing array_to_free. | 3788 // Automatic destructor called on new_queue, freeing array_to_free. |
| 3792 } | 3789 } |
| 3793 | 3790 |
| 3794 | 3791 |
| 3795 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size) | 3792 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size) |
| 3796 : logger_(logger), queue_(size) { | 3793 : logger_(logger), queue_(size) {} |
| 3797 lock_ = OS::CreateMutex(); | |
| 3798 } | |
| 3799 | |
| 3800 | |
| 3801 LockingCommandMessageQueue::~LockingCommandMessageQueue() { | |
| 3802 delete lock_; | |
| 3803 } | |
| 3804 | 3794 |
| 3805 | 3795 |
| 3806 bool LockingCommandMessageQueue::IsEmpty() const { | 3796 bool LockingCommandMessageQueue::IsEmpty() const { |
| 3807 ScopedLock sl(lock_); | 3797 LockGuard<Mutex> lock_guard(&mutex_); |
| 3808 return queue_.IsEmpty(); | 3798 return queue_.IsEmpty(); |
| 3809 } | 3799 } |
| 3810 | 3800 |
| 3811 | 3801 |
| 3812 CommandMessage LockingCommandMessageQueue::Get() { | 3802 CommandMessage LockingCommandMessageQueue::Get() { |
| 3813 ScopedLock sl(lock_); | 3803 LockGuard<Mutex> lock_guard(&mutex_); |
| 3814 CommandMessage result = queue_.Get(); | 3804 CommandMessage result = queue_.Get(); |
| 3815 logger_->DebugEvent("Get", result.text()); | 3805 logger_->DebugEvent("Get", result.text()); |
| 3816 return result; | 3806 return result; |
| 3817 } | 3807 } |
| 3818 | 3808 |
| 3819 | 3809 |
| 3820 void LockingCommandMessageQueue::Put(const CommandMessage& message) { | 3810 void LockingCommandMessageQueue::Put(const CommandMessage& message) { |
| 3821 ScopedLock sl(lock_); | 3811 LockGuard<Mutex> lock_guard(&mutex_); |
| 3822 queue_.Put(message); | 3812 queue_.Put(message); |
| 3823 logger_->DebugEvent("Put", message.text()); | 3813 logger_->DebugEvent("Put", message.text()); |
| 3824 } | 3814 } |
| 3825 | 3815 |
| 3826 | 3816 |
| 3827 void LockingCommandMessageQueue::Clear() { | 3817 void LockingCommandMessageQueue::Clear() { |
| 3828 ScopedLock sl(lock_); | 3818 LockGuard<Mutex> lock_guard(&mutex_); |
| 3829 queue_.Clear(); | 3819 queue_.Clear(); |
| 3830 } | 3820 } |
| 3831 | 3821 |
| 3832 | 3822 |
| 3833 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate) | 3823 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate) |
| 3834 : Thread("v8:MsgDispHelpr"), | 3824 : Thread("v8:MsgDispHelpr"), |
| 3835 isolate_(isolate), sem_(OS::CreateSemaphore(0)), | 3825 isolate_(isolate), sem_(OS::CreateSemaphore(0)), |
| 3836 mutex_(OS::CreateMutex()), already_signalled_(false) { | 3826 already_signalled_(false) { |
| 3837 } | 3827 } |
| 3838 | 3828 |
| 3839 | 3829 |
| 3840 MessageDispatchHelperThread::~MessageDispatchHelperThread() { | 3830 MessageDispatchHelperThread::~MessageDispatchHelperThread() { |
| 3841 delete mutex_; | |
| 3842 delete sem_; | 3831 delete sem_; |
| 3843 } | 3832 } |
| 3844 | 3833 |
| 3845 | 3834 |
| 3846 void MessageDispatchHelperThread::Schedule() { | 3835 void MessageDispatchHelperThread::Schedule() { |
| 3847 { | 3836 { |
| 3848 ScopedLock lock(mutex_); | 3837 LockGuard<Mutex> lock_guard(&mutex_); |
| 3849 if (already_signalled_) { | 3838 if (already_signalled_) { |
| 3850 return; | 3839 return; |
| 3851 } | 3840 } |
| 3852 already_signalled_ = true; | 3841 already_signalled_ = true; |
| 3853 } | 3842 } |
| 3854 sem_->Signal(); | 3843 sem_->Signal(); |
| 3855 } | 3844 } |
| 3856 | 3845 |
| 3857 | 3846 |
| 3858 void MessageDispatchHelperThread::Run() { | 3847 void MessageDispatchHelperThread::Run() { |
| 3859 while (true) { | 3848 while (true) { |
| 3860 sem_->Wait(); | 3849 sem_->Wait(); |
| 3861 { | 3850 { |
| 3862 ScopedLock lock(mutex_); | 3851 LockGuard<Mutex> lock_guard(&mutex_); |
| 3863 already_signalled_ = false; | 3852 already_signalled_ = false; |
| 3864 } | 3853 } |
| 3865 { | 3854 { |
| 3866 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); | 3855 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); |
| 3867 isolate_->debugger()->CallMessageDispatchHandler(); | 3856 isolate_->debugger()->CallMessageDispatchHandler(); |
| 3868 } | 3857 } |
| 3869 } | 3858 } |
| 3870 } | 3859 } |
| 3871 | 3860 |
| 3872 #endif // ENABLE_DEBUGGER_SUPPORT | 3861 #endif // ENABLE_DEBUGGER_SUPPORT |
| 3873 | 3862 |
| 3874 } } // namespace v8::internal | 3863 } } // namespace v8::internal |
| OLD | NEW |