OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 1406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 Mutex* Debugger::debugger_access_ = OS::CreateMutex(); | 1417 Mutex* Debugger::debugger_access_ = OS::CreateMutex(); |
1418 Handle<Object> Debugger::event_listener_ = Handle<Object>(); | 1418 Handle<Object> Debugger::event_listener_ = Handle<Object>(); |
1419 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); | 1419 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); |
1420 bool Debugger::compiling_natives_ = false; | 1420 bool Debugger::compiling_natives_ = false; |
1421 bool Debugger::is_loading_debugger_ = false; | 1421 bool Debugger::is_loading_debugger_ = false; |
1422 bool Debugger::never_unload_debugger_ = false; | 1422 bool Debugger::never_unload_debugger_ = false; |
1423 DebugMessageThread* Debugger::message_thread_ = NULL; | 1423 DebugMessageThread* Debugger::message_thread_ = NULL; |
1424 v8::Debug::MessageHandler Debugger::message_handler_ = NULL; | 1424 v8::Debug::MessageHandler Debugger::message_handler_ = NULL; |
1425 bool Debugger::message_handler_cleared_ = false; | 1425 bool Debugger::message_handler_cleared_ = false; |
1426 v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL; | 1426 v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL; |
| 1427 int Debugger::host_dispatch_micros_ = 100 * 1000; |
1427 DebuggerAgent* Debugger::agent_ = NULL; | 1428 DebuggerAgent* Debugger::agent_ = NULL; |
1428 LockingMessageQueue Debugger::command_queue_(kQueueInitialSize); | 1429 LockingMessageQueue Debugger::command_queue_(kQueueInitialSize); |
1429 LockingMessageQueue Debugger::message_queue_(kQueueInitialSize); | 1430 LockingMessageQueue Debugger::message_queue_(kQueueInitialSize); |
1430 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); | 1431 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); |
1431 Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0); | 1432 Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0); |
1432 | 1433 |
1433 | 1434 |
1434 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, | 1435 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, |
1435 int argc, Object*** argv, | 1436 int argc, Object*** argv, |
1436 bool* caught_exception) { | 1437 bool* caught_exception) { |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 bool success = SendEventMessage(event_data); | 1821 bool success = SendEventMessage(event_data); |
1821 if (!success) { | 1822 if (!success) { |
1822 // If failed to notify debugger just continue running. | 1823 // If failed to notify debugger just continue running. |
1823 return; | 1824 return; |
1824 } | 1825 } |
1825 } | 1826 } |
1826 | 1827 |
1827 // Process requests from the debugger. | 1828 // Process requests from the debugger. |
1828 while (true) { | 1829 while (true) { |
1829 // Wait for new command in the queue. | 1830 // Wait for new command in the queue. |
1830 command_received_->Wait(); | 1831 if (Debugger::host_dispatch_handler_) { |
| 1832 // In case there is a host dispatch - do periodic dispatches. |
| 1833 if (!command_received_->Wait(host_dispatch_micros_)) { |
| 1834 // Timout expired, do the dispatch. |
| 1835 Debugger::host_dispatch_handler_(); |
| 1836 continue; |
| 1837 } |
| 1838 } else { |
| 1839 // In case there is no host dispatch - just wait. |
| 1840 command_received_->Wait(); |
| 1841 } |
1831 | 1842 |
1832 // The debug command interrupt flag might have been set when the command was | 1843 // The debug command interrupt flag might have been set when the command was |
1833 // added. | 1844 // added. |
1834 StackGuard::Continue(DEBUGCOMMAND); | 1845 StackGuard::Continue(DEBUGCOMMAND); |
1835 | 1846 |
1836 // Get the command from the queue. | 1847 // Get the command from the queue. |
1837 Message command = command_queue_.Get(); | 1848 Message command = command_queue_.Get(); |
1838 Logger::DebugTag("Got request from command queue, in interactive loop."); | 1849 Logger::DebugTag("Got request from command queue, in interactive loop."); |
1839 if (!Debugger::IsDebuggerActive()) { | 1850 if (!Debugger::IsDebuggerActive()) { |
1840 // Delete command text and user data. | 1851 // Delete command text and user data. |
1841 command.Dispose(); | 1852 command.Dispose(); |
1842 return; | 1853 return; |
1843 } | 1854 } |
1844 | 1855 |
1845 // Check if the command is a host dispatch. | |
1846 if (command.IsHostDispatch()) { | |
1847 if (Debugger::host_dispatch_handler_) { | |
1848 Debugger::host_dispatch_handler_(command.client_data()); | |
1849 // Delete the dispatch. | |
1850 command.Dispose(); | |
1851 } | |
1852 if (auto_continue && !HasCommands()) { | |
1853 return; | |
1854 } | |
1855 continue; | |
1856 } | |
1857 | |
1858 // Invoke JavaScript to process the debug request. | 1856 // Invoke JavaScript to process the debug request. |
1859 v8::Local<v8::String> fun_name; | 1857 v8::Local<v8::String> fun_name; |
1860 v8::Local<v8::Function> fun; | 1858 v8::Local<v8::Function> fun; |
1861 v8::Local<v8::Value> request; | 1859 v8::Local<v8::Value> request; |
1862 v8::TryCatch try_catch; | 1860 v8::TryCatch try_catch; |
1863 fun_name = v8::String::New("processDebugRequest"); | 1861 fun_name = v8::String::New("processDebugRequest"); |
1864 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); | 1862 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); |
1865 | 1863 |
1866 request = v8::String::New(command.text().start(), | 1864 request = v8::String::New(command.text().start(), |
1867 command.text().length()); | 1865 command.text().length()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1964 | 1962 |
1965 // Send an empty command to the debugger if in a break to make JavaScript | 1963 // Send an empty command to the debugger if in a break to make JavaScript |
1966 // run again if the debugger is closed. | 1964 // run again if the debugger is closed. |
1967 if (Debug::InDebugger()) { | 1965 if (Debug::InDebugger()) { |
1968 ProcessCommand(Vector<const uint16_t>::empty()); | 1966 ProcessCommand(Vector<const uint16_t>::empty()); |
1969 } | 1967 } |
1970 } | 1968 } |
1971 } | 1969 } |
1972 | 1970 |
1973 | 1971 |
1974 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler) { | 1972 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, |
| 1973 int period) { |
1975 host_dispatch_handler_ = handler; | 1974 host_dispatch_handler_ = handler; |
| 1975 host_dispatch_micros_ = period * 1000; |
1976 } | 1976 } |
1977 | 1977 |
1978 | 1978 |
1979 // Calls the registered debug message handler. This callback is part of the | 1979 // Calls the registered debug message handler. This callback is part of the |
1980 // public API. Messages are kept internally as Vector<uint16_t> strings, which | 1980 // public API. Messages are kept internally as Vector<uint16_t> strings, which |
1981 // are allocated in various places and deallocated by the calling function | 1981 // are allocated in various places and deallocated by the calling function |
1982 // sometime after this call. | 1982 // sometime after this call. |
1983 void Debugger::InvokeMessageHandler(Message message) { | 1983 void Debugger::InvokeMessageHandler(Message message) { |
1984 ScopedLock with(debugger_access_); | 1984 ScopedLock with(debugger_access_); |
1985 | 1985 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2060 StackGuard::DebugCommand(); | 2060 StackGuard::DebugCommand(); |
2061 } | 2061 } |
2062 } | 2062 } |
2063 | 2063 |
2064 | 2064 |
2065 bool Debugger::HasCommands() { | 2065 bool Debugger::HasCommands() { |
2066 return !command_queue_.IsEmpty(); | 2066 return !command_queue_.IsEmpty(); |
2067 } | 2067 } |
2068 | 2068 |
2069 | 2069 |
2070 void Debugger::ProcessHostDispatch(v8::Debug::ClientData* dispatch) { | |
2071 // Puts a host dispatch comming from the public API on the queue. | |
2072 Logger::DebugTag("Put dispatch on command_queue."); | |
2073 command_queue_.Put(Message::NewHostDispatch(dispatch)); | |
2074 command_received_->Signal(); | |
2075 | |
2076 // Set the debug command break flag to have the host dispatch processed. | |
2077 if (!Debug::InDebugger()) { | |
2078 StackGuard::DebugCommand(); | |
2079 } | |
2080 } | |
2081 | |
2082 | |
2083 bool Debugger::IsDebuggerActive() { | 2070 bool Debugger::IsDebuggerActive() { |
2084 ScopedLock with(debugger_access_); | 2071 ScopedLock with(debugger_access_); |
2085 | 2072 |
2086 return message_handler_ != NULL || !event_listener_.is_null(); | 2073 return message_handler_ != NULL || !event_listener_.is_null(); |
2087 } | 2074 } |
2088 | 2075 |
2089 | 2076 |
2090 Handle<Object> Debugger::Call(Handle<JSFunction> fun, | 2077 Handle<Object> Debugger::Call(Handle<JSFunction> fun, |
2091 Handle<Object> data, | 2078 Handle<Object> data, |
2092 bool* pending_exception) { | 2079 bool* pending_exception) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2161 | 2148 |
2162 | 2149 |
2163 void DebugMessageThread::Stop() { | 2150 void DebugMessageThread::Stop() { |
2164 keep_running_ = false; | 2151 keep_running_ = false; |
2165 Debugger::SendMessage(Message::NewEmptyMessage()); | 2152 Debugger::SendMessage(Message::NewEmptyMessage()); |
2166 Join(); | 2153 Join(); |
2167 } | 2154 } |
2168 | 2155 |
2169 | 2156 |
2170 Message::Message() : text_(Vector<uint16_t>::empty()), | 2157 Message::Message() : text_(Vector<uint16_t>::empty()), |
2171 client_data_(NULL), | 2158 client_data_(NULL) { |
2172 is_host_dispatch_(false) { | |
2173 } | 2159 } |
2174 | 2160 |
2175 | 2161 |
2176 Message::Message(const Vector<uint16_t>& text, | 2162 Message::Message(const Vector<uint16_t>& text, |
2177 v8::Debug::ClientData* data, | 2163 v8::Debug::ClientData* data) |
2178 bool is_host_dispatch) | |
2179 : text_(text), | 2164 : text_(text), |
2180 client_data_(data), | 2165 client_data_(data) { |
2181 is_host_dispatch_(is_host_dispatch) { | |
2182 } | 2166 } |
2183 | 2167 |
2184 | 2168 |
2185 Message::~Message() { | 2169 Message::~Message() { |
2186 } | 2170 } |
2187 | 2171 |
2188 | 2172 |
2189 void Message::Dispose() { | 2173 void Message::Dispose() { |
2190 text_.Dispose(); | 2174 text_.Dispose(); |
2191 delete client_data_; | 2175 delete client_data_; |
2192 client_data_ = NULL; | 2176 client_data_ = NULL; |
2193 } | 2177 } |
2194 | 2178 |
2195 | 2179 |
2196 bool Message::IsHostDispatch() const { | |
2197 return is_host_dispatch_; | |
2198 } | |
2199 | |
2200 | |
2201 Message Message::NewCommand(const Vector<uint16_t>& command, | 2180 Message Message::NewCommand(const Vector<uint16_t>& command, |
2202 v8::Debug::ClientData* data) { | 2181 v8::Debug::ClientData* data) { |
2203 return Message(command.Clone(), data, false); | 2182 return Message(command.Clone(), data); |
2204 } | 2183 } |
2205 | 2184 |
2206 | 2185 |
2207 Message Message::NewHostDispatch(v8::Debug::ClientData* dispatch) { | |
2208 return Message(Vector<uint16_t>::empty(), dispatch, true); | |
2209 } | |
2210 | |
2211 | |
2212 Message Message::NewOutput(v8::Handle<v8::String> output, | 2186 Message Message::NewOutput(v8::Handle<v8::String> output, |
2213 v8::Debug::ClientData* data) { | 2187 v8::Debug::ClientData* data) { |
2214 Vector<uint16_t> text; | 2188 Vector<uint16_t> text; |
2215 if (!output.IsEmpty()) { | 2189 if (!output.IsEmpty()) { |
2216 // Do not include trailing '\0'. | 2190 // Do not include trailing '\0'. |
2217 text = Vector<uint16_t>::New(output->Length()); | 2191 text = Vector<uint16_t>::New(output->Length()); |
2218 output->Write(text.start(), 0, output->Length()); | 2192 output->Write(text.start(), 0, output->Length()); |
2219 } | 2193 } |
2220 return Message(text, data, false); | 2194 return Message(text, data); |
2221 } | 2195 } |
2222 | 2196 |
2223 | 2197 |
2224 Message Message::NewEmptyMessage() { | 2198 Message Message::NewEmptyMessage() { |
2225 return Message(); | 2199 return Message(); |
2226 } | 2200 } |
2227 | 2201 |
2228 | 2202 |
2229 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) { | 2203 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) { |
2230 messages_ = NewArray<Message>(size); | 2204 messages_ = NewArray<Message>(size); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2303 | 2277 |
2304 | 2278 |
2305 void LockingMessageQueue::Clear() { | 2279 void LockingMessageQueue::Clear() { |
2306 ScopedLock sl(lock_); | 2280 ScopedLock sl(lock_); |
2307 queue_.Clear(); | 2281 queue_.Clear(); |
2308 } | 2282 } |
2309 | 2283 |
2310 #endif // ENABLE_DEBUGGER_SUPPORT | 2284 #endif // ENABLE_DEBUGGER_SUPPORT |
2311 | 2285 |
2312 } } // namespace v8::internal | 2286 } } // namespace v8::internal |
OLD | NEW |