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 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1373 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); | 1373 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); |
1374 bool Debugger::debugger_active_ = false; | 1374 bool Debugger::debugger_active_ = false; |
1375 bool Debugger::compiling_natives_ = false; | 1375 bool Debugger::compiling_natives_ = false; |
1376 bool Debugger::is_loading_debugger_ = false; | 1376 bool Debugger::is_loading_debugger_ = false; |
1377 DebugMessageThread* Debugger::message_thread_ = NULL; | 1377 DebugMessageThread* Debugger::message_thread_ = NULL; |
1378 v8::DebugMessageHandler Debugger::message_handler_ = NULL; | 1378 v8::DebugMessageHandler Debugger::message_handler_ = NULL; |
1379 void* Debugger::message_handler_data_ = NULL; | 1379 void* Debugger::message_handler_data_ = NULL; |
1380 v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL; | 1380 v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL; |
1381 void* Debugger::host_dispatch_handler_data_ = NULL; | 1381 void* Debugger::host_dispatch_handler_data_ = NULL; |
1382 DebuggerAgent* Debugger::agent_ = NULL; | 1382 DebuggerAgent* Debugger::agent_ = NULL; |
| 1383 LockingMessageQueue Debugger::command_queue_(kQueueInitialSize); |
| 1384 LockingMessageQueue Debugger::message_queue_(kQueueInitialSize); |
| 1385 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); |
| 1386 Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0); |
1383 | 1387 |
1384 | 1388 |
1385 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, | 1389 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, |
1386 int argc, Object*** argv, | 1390 int argc, Object*** argv, |
1387 bool* caught_exception) { | 1391 bool* caught_exception) { |
1388 ASSERT(Top::context() == *Debug::debug_context()); | 1392 ASSERT(Top::context() == *Debug::debug_context()); |
1389 | 1393 |
1390 // Create the execution state object. | 1394 // Create the execution state object. |
1391 Handle<String> constructor_str = Factory::LookupSymbol(constructor_name); | 1395 Handle<String> constructor_str = Factory::LookupSymbol(constructor_name); |
1392 Handle<Object> constructor(Top::global()->GetProperty(*constructor_str)); | 1396 Handle<Object> constructor(Top::global()->GetProperty(*constructor_str)); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1659 Handle<Object> event_data, | 1663 Handle<Object> event_data, |
1660 bool auto_continue) { | 1664 bool auto_continue) { |
1661 HandleScope scope; | 1665 HandleScope scope; |
1662 | 1666 |
1663 // Create the execution state. | 1667 // Create the execution state. |
1664 bool caught_exception = false; | 1668 bool caught_exception = false; |
1665 Handle<Object> exec_state = MakeExecutionState(&caught_exception); | 1669 Handle<Object> exec_state = MakeExecutionState(&caught_exception); |
1666 if (caught_exception) { | 1670 if (caught_exception) { |
1667 return; | 1671 return; |
1668 } | 1672 } |
1669 // First notify the builtin debugger. | 1673 // First notify the message handler if any. |
1670 if (message_thread_ != NULL) { | 1674 if (message_handler_ != NULL) { |
1671 message_thread_->DebugEvent(event, exec_state, event_data, auto_continue); | 1675 NotifyMessageHandler(event, exec_state, event_data, auto_continue); |
1672 } | 1676 } |
1673 // Notify registered debug event listener. This can be either a C or a | 1677 // Notify registered debug event listener. This can be either a C or a |
1674 // JavaScript function. | 1678 // JavaScript function. |
1675 if (!event_listener_.is_null()) { | 1679 if (!event_listener_.is_null()) { |
1676 if (event_listener_->IsProxy()) { | 1680 if (event_listener_->IsProxy()) { |
1677 // C debug event listener. | 1681 // C debug event listener. |
1678 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); | 1682 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); |
1679 v8::DebugEventCallback callback = | 1683 v8::DebugEventCallback callback = |
1680 FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy()); | 1684 FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy()); |
1681 callback(event, | 1685 callback(event, |
(...skipping 17 matching lines...) Expand all Loading... |
1699 // Silently ignore exceptions from debug event listeners. | 1703 // Silently ignore exceptions from debug event listeners. |
1700 } | 1704 } |
1701 } | 1705 } |
1702 } | 1706 } |
1703 | 1707 |
1704 // Clear the mirror cache. | 1708 // Clear the mirror cache. |
1705 Debug::ClearMirrorCache(); | 1709 Debug::ClearMirrorCache(); |
1706 } | 1710 } |
1707 | 1711 |
1708 | 1712 |
1709 void Debugger::SetEventListener(Handle<Object> callback, | 1713 void Debugger::NotifyMessageHandler(v8::DebugEvent event, |
1710 Handle<Object> data) { | |
1711 HandleScope scope; | |
1712 | |
1713 // Clear the global handles for the event listener and the event listener data | |
1714 // object. | |
1715 if (!event_listener_.is_null()) { | |
1716 GlobalHandles::Destroy( | |
1717 reinterpret_cast<Object**>(event_listener_.location())); | |
1718 event_listener_ = Handle<Object>(); | |
1719 } | |
1720 if (!event_listener_data_.is_null()) { | |
1721 GlobalHandles::Destroy( | |
1722 reinterpret_cast<Object**>(event_listener_data_.location())); | |
1723 event_listener_data_ = Handle<Object>(); | |
1724 } | |
1725 | |
1726 // If there is a new debug event listener register it together with its data | |
1727 // object. | |
1728 if (!callback->IsUndefined() && !callback->IsNull()) { | |
1729 event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback)); | |
1730 if (data.is_null()) { | |
1731 data = Factory::undefined_value(); | |
1732 } | |
1733 event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data)); | |
1734 } | |
1735 | |
1736 UpdateActiveDebugger(); | |
1737 } | |
1738 | |
1739 | |
1740 void Debugger::TearDown() { | |
1741 if (message_thread_ != NULL) { | |
1742 message_thread_->Stop(); | |
1743 delete message_thread_; | |
1744 message_thread_ = NULL; | |
1745 } | |
1746 } | |
1747 | |
1748 | |
1749 void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data) { | |
1750 message_handler_ = handler; | |
1751 message_handler_data_ = data; | |
1752 if (!message_thread_) { | |
1753 message_thread_ = new DebugMessageThread(); | |
1754 message_thread_->Start(); | |
1755 } | |
1756 UpdateActiveDebugger(); | |
1757 } | |
1758 | |
1759 | |
1760 void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler, | |
1761 void* data) { | |
1762 host_dispatch_handler_ = handler; | |
1763 host_dispatch_handler_data_ = data; | |
1764 } | |
1765 | |
1766 | |
1767 // Posts an output message from the debugger to the debug_message_handler | |
1768 // callback. This callback is part of the public API. Messages are | |
1769 // kept internally as Vector<uint16_t> strings, which are allocated in various | |
1770 // places and deallocated by the calling function sometime after this call. | |
1771 void Debugger::SendMessage(Vector< uint16_t> message) { | |
1772 if (message_handler_ != NULL) { | |
1773 message_handler_(message.start(), message.length(), message_handler_data_); | |
1774 } | |
1775 } | |
1776 | |
1777 | |
1778 void Debugger::ProcessCommand(Vector<const uint16_t> command) { | |
1779 if (message_thread_ != NULL) { | |
1780 message_thread_->ProcessCommand( | |
1781 Vector<uint16_t>(const_cast<uint16_t *>(command.start()), | |
1782 command.length())); | |
1783 } | |
1784 } | |
1785 | |
1786 | |
1787 bool Debugger::HasCommands() { | |
1788 if (message_thread_ != NULL) { | |
1789 return message_thread_->HasCommands(); | |
1790 } else { | |
1791 return false; | |
1792 } | |
1793 } | |
1794 | |
1795 | |
1796 void Debugger::ProcessHostDispatch(void* dispatch) { | |
1797 if (message_thread_ != NULL) { | |
1798 message_thread_->ProcessHostDispatch(dispatch); | |
1799 } | |
1800 } | |
1801 | |
1802 | |
1803 void Debugger::UpdateActiveDebugger() { | |
1804 set_debugger_active((message_thread_ != NULL && | |
1805 message_handler_ != NULL) || | |
1806 !event_listener_.is_null()); | |
1807 if (!debugger_active() && message_thread_) { | |
1808 message_thread_->OnDebuggerInactive(); | |
1809 } | |
1810 if (!debugger_active()) { | |
1811 Debug::Unload(); | |
1812 } | |
1813 } | |
1814 | |
1815 | |
1816 Handle<Object> Debugger::Call(Handle<JSFunction> fun, | |
1817 Handle<Object> data, | |
1818 bool* pending_exception) { | |
1819 // Enter the debugger. | |
1820 EnterDebugger debugger; | |
1821 if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) { | |
1822 return Factory::undefined_value(); | |
1823 } | |
1824 | |
1825 // Create the execution state. | |
1826 bool caught_exception = false; | |
1827 Handle<Object> exec_state = MakeExecutionState(&caught_exception); | |
1828 if (caught_exception) { | |
1829 return Factory::undefined_value(); | |
1830 } | |
1831 | |
1832 static const int kArgc = 2; | |
1833 Object** argv[kArgc] = { exec_state.location(), data.location() }; | |
1834 Handle<Object> result = Execution::Call(fun, Factory::undefined_value(), | |
1835 kArgc, argv, pending_exception); | |
1836 return result; | |
1837 } | |
1838 | |
1839 | |
1840 bool Debugger::StartAgent(const char* name, int port) { | |
1841 if (Socket::Setup()) { | |
1842 agent_ = new DebuggerAgent(name, port); | |
1843 agent_->Start(); | |
1844 return true; | |
1845 } | |
1846 | |
1847 return false; | |
1848 } | |
1849 | |
1850 | |
1851 void Debugger::StopAgent() { | |
1852 if (agent_ != NULL) { | |
1853 agent_->Shutdown(); | |
1854 agent_->Join(); | |
1855 delete agent_; | |
1856 agent_ = NULL; | |
1857 } | |
1858 } | |
1859 | |
1860 | |
1861 DebugMessageThread::DebugMessageThread() | |
1862 : host_running_(true), | |
1863 command_queue_(kQueueInitialSize), | |
1864 message_queue_(kQueueInitialSize), | |
1865 keep_running_(true) { | |
1866 command_received_ = OS::CreateSemaphore(0); | |
1867 message_received_ = OS::CreateSemaphore(0); | |
1868 } | |
1869 | |
1870 // Should only be done after the thread is done running. | |
1871 DebugMessageThread::~DebugMessageThread() { | |
1872 delete command_received_; | |
1873 delete message_received_; | |
1874 } | |
1875 | |
1876 void DebugMessageThread::Stop() { | |
1877 keep_running_ = false; | |
1878 SendMessage(Vector<uint16_t>(NULL, 0)); | |
1879 Join(); | |
1880 } | |
1881 | |
1882 // Puts an event coming from V8 on the queue. Creates | |
1883 // a copy of the JSON formatted event string managed by the V8. | |
1884 // Called by the V8 thread. | |
1885 // The new copy of the event string is destroyed in Run(). | |
1886 void DebugMessageThread::SendMessage(Vector<uint16_t> message) { | |
1887 Vector<uint16_t> message_copy = message.Clone(); | |
1888 Logger::DebugTag("Put message on event message_queue."); | |
1889 message_queue_.Put(message_copy); | |
1890 message_received_->Signal(); | |
1891 } | |
1892 | |
1893 | |
1894 bool DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) { | |
1895 v8::HandleScope scope; | |
1896 // Call toJSONProtocol on the debug event object. | |
1897 v8::Local<v8::Object> api_event_data = | |
1898 v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)); | |
1899 v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol"); | |
1900 v8::Local<v8::Function> fun = | |
1901 v8::Function::Cast(*api_event_data->Get(fun_name)); | |
1902 v8::TryCatch try_catch; | |
1903 v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL); | |
1904 v8::Local<v8::String> json_event_string; | |
1905 if (!try_catch.HasCaught()) { | |
1906 if (!json_event->IsUndefined()) { | |
1907 json_event_string = json_event->ToString(); | |
1908 if (FLAG_trace_debug_json) { | |
1909 PrintLn(json_event_string); | |
1910 } | |
1911 v8::String::Value val(json_event_string); | |
1912 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val), | |
1913 json_event_string->Length()); | |
1914 SendMessage(str); | |
1915 } else { | |
1916 SendMessage(Vector<uint16_t>::empty()); | |
1917 } | |
1918 } else { | |
1919 PrintLn(try_catch.Exception()); | |
1920 return false; | |
1921 } | |
1922 return true; | |
1923 } | |
1924 | |
1925 | |
1926 void DebugMessageThread::Run() { | |
1927 // Sends debug events to an installed debugger message callback. | |
1928 while (keep_running_) { | |
1929 // Wait and Get are paired so that semaphore count equals queue length. | |
1930 message_received_->Wait(); | |
1931 Logger::DebugTag("Get message from event message_queue."); | |
1932 Vector<uint16_t> message = message_queue_.Get(); | |
1933 if (message.length() > 0) { | |
1934 Debugger::SendMessage(message); | |
1935 } | |
1936 } | |
1937 } | |
1938 | |
1939 | |
1940 // This method is called by the V8 thread whenever a debug event occurs in | |
1941 // the VM. | |
1942 void DebugMessageThread::DebugEvent(v8::DebugEvent event, | |
1943 Handle<Object> exec_state, | 1714 Handle<Object> exec_state, |
1944 Handle<Object> event_data, | 1715 Handle<Object> event_data, |
1945 bool auto_continue) { | 1716 bool auto_continue) { |
1946 HandleScope scope; | 1717 HandleScope scope; |
1947 | 1718 |
1948 if (!Debug::Load()) return; | 1719 if (!Debug::Load()) return; |
1949 | 1720 |
1950 // Process the individual events. | 1721 // Process the individual events. |
1951 bool interactive = false; | 1722 bool interactive = false; |
1952 switch (event) { | 1723 switch (event) { |
(...skipping 27 matching lines...) Expand all Loading... |
1980 v8::Local<v8::Object> cmd_processor = | 1751 v8::Local<v8::Object> cmd_processor = |
1981 v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL)); | 1752 v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL)); |
1982 if (try_catch.HasCaught()) { | 1753 if (try_catch.HasCaught()) { |
1983 PrintLn(try_catch.Exception()); | 1754 PrintLn(try_catch.Exception()); |
1984 return; | 1755 return; |
1985 } | 1756 } |
1986 | 1757 |
1987 // Notify the debugger that a debug event has occurred unless auto continue is | 1758 // Notify the debugger that a debug event has occurred unless auto continue is |
1988 // active in which case no event is send. | 1759 // active in which case no event is send. |
1989 if (!auto_continue) { | 1760 if (!auto_continue) { |
1990 bool success = SetEventJSONFromEvent(event_data); | 1761 bool success = SendEventMessage(event_data); |
1991 if (!success) { | 1762 if (!success) { |
1992 // If failed to notify debugger just continue running. | 1763 // If failed to notify debugger just continue running. |
1993 return; | 1764 return; |
1994 } | 1765 } |
1995 } | 1766 } |
1996 | 1767 |
1997 // Process requests from the debugger. | 1768 // Process requests from the debugger. |
1998 host_running_ = false; | |
1999 while (true) { | 1769 while (true) { |
2000 // Wait for new command in the queue. | 1770 // Wait for new command in the queue. |
2001 command_received_->Wait(); | 1771 command_received_->Wait(); |
2002 | 1772 |
2003 // The debug command interrupt flag might have been set when the command was | 1773 // The debug command interrupt flag might have been set when the command was |
2004 // added. | 1774 // added. |
2005 StackGuard::Continue(DEBUGCOMMAND); | 1775 StackGuard::Continue(DEBUGCOMMAND); |
2006 | 1776 |
2007 // Get the command from the queue. | 1777 // Get the command from the queue. |
2008 Vector<uint16_t> command = command_queue_.Get(); | 1778 Vector<uint16_t> command = command_queue_.Get(); |
2009 Logger::DebugTag("Got request from command queue, in interactive loop."); | 1779 Logger::DebugTag("Got request from command queue, in interactive loop."); |
2010 ASSERT(!host_running_); | |
2011 if (!Debugger::debugger_active()) { | 1780 if (!Debugger::debugger_active()) { |
2012 host_running_ = true; | |
2013 return; | 1781 return; |
2014 } | 1782 } |
2015 | 1783 |
2016 // Check if the command is a host dispatch. | 1784 // Check if the command is a host dispatch. |
2017 if (command[0] == 0) { | 1785 if (command[0] == 0) { |
2018 if (Debugger::host_dispatch_handler_) { | 1786 if (Debugger::host_dispatch_handler_) { |
2019 int32_t dispatch = (command[1] << 16) | command[2]; | 1787 int32_t dispatch = (command[1] << 16) | command[2]; |
2020 Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch), | 1788 Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch), |
2021 Debugger::host_dispatch_handler_data_); | 1789 Debugger::host_dispatch_handler_data_); |
2022 } | 1790 } |
2023 continue; | 1791 continue; |
2024 } | 1792 } |
2025 | 1793 |
2026 // Invoke the JavaScript to process the debug request. | 1794 // Invoke JavaScript to process the debug request. |
2027 v8::Local<v8::String> fun_name; | 1795 v8::Local<v8::String> fun_name; |
2028 v8::Local<v8::Function> fun; | 1796 v8::Local<v8::Function> fun; |
2029 v8::Local<v8::Value> request; | 1797 v8::Local<v8::Value> request; |
2030 v8::TryCatch try_catch; | 1798 v8::TryCatch try_catch; |
2031 fun_name = v8::String::New("processDebugRequest"); | 1799 fun_name = v8::String::New("processDebugRequest"); |
2032 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); | 1800 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); |
2033 request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()), | 1801 request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()), |
2034 command.length()); | 1802 command.length()); |
2035 static const int kArgc = 1; | 1803 static const int kArgc = 1; |
2036 v8::Handle<Value> argv[kArgc] = { request }; | 1804 v8::Handle<Value> argv[kArgc] = { request }; |
(...skipping 28 matching lines...) Expand all Loading... |
2065 } else { | 1833 } else { |
2066 // In case of failure the result text is the exception text. | 1834 // In case of failure the result text is the exception text. |
2067 response = try_catch.Exception()->ToString(); | 1835 response = try_catch.Exception()->ToString(); |
2068 } | 1836 } |
2069 | 1837 |
2070 // Convert text result to C string. | 1838 // Convert text result to C string. |
2071 v8::String::Value val(response); | 1839 v8::String::Value val(response); |
2072 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val), | 1840 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val), |
2073 response->Length()); | 1841 response->Length()); |
2074 | 1842 |
2075 // Set host_running_ correctly for nested debugger evaluations. | |
2076 host_running_ = running; | |
2077 | |
2078 // Return the result. | 1843 // Return the result. |
2079 SendMessage(str); | 1844 SendMessage(str); |
2080 | 1845 |
2081 // Return from debug event processing if either the VM is put into the | 1846 // Return from debug event processing if either the VM is put into the |
2082 // runnning state (through a continue command) or auto continue is active | 1847 // runnning state (through a continue command) or auto continue is active |
2083 // and there are no more commands queued. | 1848 // and there are no more commands queued. |
2084 if (running || (auto_continue && !HasCommands())) { | 1849 if (running || (auto_continue && !HasCommands())) { |
2085 return; | 1850 return; |
2086 } | 1851 } |
2087 } | 1852 } |
2088 } | 1853 } |
2089 | 1854 |
2090 | 1855 |
| 1856 void Debugger::SetEventListener(Handle<Object> callback, |
| 1857 Handle<Object> data) { |
| 1858 HandleScope scope; |
| 1859 |
| 1860 // Clear the global handles for the event listener and the event listener data |
| 1861 // object. |
| 1862 if (!event_listener_.is_null()) { |
| 1863 GlobalHandles::Destroy( |
| 1864 reinterpret_cast<Object**>(event_listener_.location())); |
| 1865 event_listener_ = Handle<Object>(); |
| 1866 } |
| 1867 if (!event_listener_data_.is_null()) { |
| 1868 GlobalHandles::Destroy( |
| 1869 reinterpret_cast<Object**>(event_listener_data_.location())); |
| 1870 event_listener_data_ = Handle<Object>(); |
| 1871 } |
| 1872 |
| 1873 // If there is a new debug event listener register it together with its data |
| 1874 // object. |
| 1875 if (!callback->IsUndefined() && !callback->IsNull()) { |
| 1876 event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback)); |
| 1877 if (data.is_null()) { |
| 1878 data = Factory::undefined_value(); |
| 1879 } |
| 1880 event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data)); |
| 1881 } |
| 1882 |
| 1883 UpdateActiveDebugger(); |
| 1884 } |
| 1885 |
| 1886 |
| 1887 void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data, |
| 1888 bool message_handler_thread) { |
| 1889 message_handler_ = handler; |
| 1890 message_handler_data_ = data; |
| 1891 if (!message_thread_ && message_handler_thread) { |
| 1892 message_thread_ = new DebugMessageThread(); |
| 1893 message_thread_->Start(); |
| 1894 } |
| 1895 UpdateActiveDebugger(); |
| 1896 } |
| 1897 |
| 1898 |
| 1899 void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler, |
| 1900 void* data) { |
| 1901 host_dispatch_handler_ = handler; |
| 1902 host_dispatch_handler_data_ = data; |
| 1903 } |
| 1904 |
| 1905 |
| 1906 // Calls the registered debug message handler. This callback is part of the |
| 1907 // public API. Messages are kept internally as Vector<uint16_t> strings, which |
| 1908 // are allocated in various places and deallocated by the calling function |
| 1909 // sometime after this call. |
| 1910 void Debugger::InvokeMessageHandler(Vector<uint16_t> message) { |
| 1911 if (message_handler_ != NULL) { |
| 1912 message_handler_(message.start(), message.length(), message_handler_data_); |
| 1913 } |
| 1914 } |
| 1915 |
| 1916 |
| 1917 void Debugger::SendMessage(Vector<uint16_t> message) { |
| 1918 if (message_thread_ == NULL) { |
| 1919 // If there is no message thread just invoke the message handler from the |
| 1920 // V8 thread. |
| 1921 InvokeMessageHandler(message); |
| 1922 } else { |
| 1923 // Put a copy of the message coming from V8 on the queue. The new copy of |
| 1924 // the event string is destroyed by the message thread. |
| 1925 Vector<uint16_t> message_copy = message.Clone(); |
| 1926 Logger::DebugTag("Put message on event message_queue."); |
| 1927 message_queue_.Put(message_copy); |
| 1928 message_received_->Signal(); |
| 1929 } |
| 1930 } |
| 1931 |
| 1932 |
| 1933 bool Debugger::SendEventMessage(Handle<Object> event_data) { |
| 1934 v8::HandleScope scope; |
| 1935 // Call toJSONProtocol on the debug event object. |
| 1936 v8::Local<v8::Object> api_event_data = |
| 1937 v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)); |
| 1938 v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol"); |
| 1939 v8::Local<v8::Function> fun = |
| 1940 v8::Function::Cast(*api_event_data->Get(fun_name)); |
| 1941 v8::TryCatch try_catch; |
| 1942 v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL); |
| 1943 v8::Local<v8::String> json_event_string; |
| 1944 if (!try_catch.HasCaught()) { |
| 1945 if (!json_event->IsUndefined()) { |
| 1946 json_event_string = json_event->ToString(); |
| 1947 if (FLAG_trace_debug_json) { |
| 1948 PrintLn(json_event_string); |
| 1949 } |
| 1950 v8::String::Value val(json_event_string); |
| 1951 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val), |
| 1952 json_event_string->Length()); |
| 1953 SendMessage(str); |
| 1954 } else { |
| 1955 SendMessage(Vector<uint16_t>::empty()); |
| 1956 } |
| 1957 } else { |
| 1958 PrintLn(try_catch.Exception()); |
| 1959 return false; |
| 1960 } |
| 1961 return true; |
| 1962 } |
| 1963 |
| 1964 |
2091 // Puts a command coming from the public API on the queue. Creates | 1965 // Puts a command coming from the public API on the queue. Creates |
2092 // a copy of the command string managed by the debugger. Up to this | 1966 // a copy of the command string managed by the debugger. Up to this |
2093 // point, the command data was managed by the API client. Called | 1967 // point, the command data was managed by the API client. Called |
2094 // by the API client thread. This is where the API client hands off | 1968 // by the API client thread. This is where the API client hands off |
2095 // processing of the command to the DebugMessageThread thread. | 1969 // processing of the command to the DebugMessageThread thread. |
2096 // The new copy of the command is destroyed in HandleCommand(). | 1970 // The new copy of the command is destroyed in HandleCommand(). |
2097 void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) { | 1971 void Debugger::ProcessCommand(Vector<const uint16_t> command) { |
2098 Vector<uint16_t> command_copy = command.Clone(); | 1972 // Make a copy of the command. Need to cast away const for Clone to work. |
| 1973 Vector<uint16_t> command_copy = |
| 1974 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
| 1975 command.length()).Clone(); |
2099 Logger::DebugTag("Put command on command_queue."); | 1976 Logger::DebugTag("Put command on command_queue."); |
2100 command_queue_.Put(command_copy); | 1977 command_queue_.Put(command_copy); |
2101 command_received_->Signal(); | 1978 command_received_->Signal(); |
2102 | |
2103 if (!Debug::InDebugger()) { | 1979 if (!Debug::InDebugger()) { |
2104 StackGuard::DebugCommand(); | 1980 StackGuard::DebugCommand(); |
2105 } | 1981 } |
2106 } | 1982 } |
2107 | 1983 |
2108 | 1984 |
| 1985 bool Debugger::HasCommands() { |
| 1986 return !command_queue_.IsEmpty(); |
| 1987 } |
| 1988 |
| 1989 |
| 1990 void Debugger::ProcessHostDispatch(void* dispatch) { |
2109 // Puts a host dispatch comming from the public API on the queue. | 1991 // Puts a host dispatch comming from the public API on the queue. |
2110 void DebugMessageThread::ProcessHostDispatch(void* dispatch) { | |
2111 uint16_t hack[3]; | 1992 uint16_t hack[3]; |
2112 hack[0] = 0; | 1993 hack[0] = 0; |
2113 hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16; | 1994 hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16; |
2114 hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF; | 1995 hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF; |
2115 Logger::DebugTag("Put dispatch on command_queue."); | 1996 Logger::DebugTag("Put dispatch on command_queue."); |
2116 command_queue_.Put(Vector<uint16_t>(hack, 3).Clone()); | 1997 command_queue_.Put(Vector<uint16_t>(hack, 3).Clone()); |
2117 command_received_->Signal(); | 1998 command_received_->Signal(); |
2118 } | 1999 } |
2119 | 2000 |
2120 | 2001 |
2121 void DebugMessageThread::OnDebuggerInactive() { | 2002 void Debugger::UpdateActiveDebugger() { |
2122 // Send an empty command to the debugger if in a break to make JavaScript run | 2003 set_debugger_active((message_thread_ != NULL && |
2123 // again if the debugger is closed. | 2004 message_handler_ != NULL) || |
2124 if (!host_running_) { | 2005 !event_listener_.is_null()); |
2125 ProcessCommand(Vector<uint16_t>::empty()); | 2006 if (!debugger_active() && message_thread_) { |
| 2007 // Send an empty command to the debugger if in a break to make JavaScript |
| 2008 // run again if the debugger is closed. |
| 2009 ProcessCommand(Vector<const uint16_t>::empty()); |
2126 } | 2010 } |
| 2011 if (!debugger_active()) { |
| 2012 Debug::Unload(); |
| 2013 } |
| 2014 } |
| 2015 |
| 2016 |
| 2017 Handle<Object> Debugger::Call(Handle<JSFunction> fun, |
| 2018 Handle<Object> data, |
| 2019 bool* pending_exception) { |
| 2020 // Enter the debugger. |
| 2021 EnterDebugger debugger; |
| 2022 if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) { |
| 2023 return Factory::undefined_value(); |
| 2024 } |
| 2025 |
| 2026 // Create the execution state. |
| 2027 bool caught_exception = false; |
| 2028 Handle<Object> exec_state = MakeExecutionState(&caught_exception); |
| 2029 if (caught_exception) { |
| 2030 return Factory::undefined_value(); |
| 2031 } |
| 2032 |
| 2033 static const int kArgc = 2; |
| 2034 Object** argv[kArgc] = { exec_state.location(), data.location() }; |
| 2035 Handle<Object> result = Execution::Call(fun, Factory::undefined_value(), |
| 2036 kArgc, argv, pending_exception); |
| 2037 return result; |
| 2038 } |
| 2039 |
| 2040 |
| 2041 bool Debugger::StartAgent(const char* name, int port) { |
| 2042 if (Socket::Setup()) { |
| 2043 agent_ = new DebuggerAgent(name, port); |
| 2044 agent_->Start(); |
| 2045 return true; |
| 2046 } |
| 2047 |
| 2048 return false; |
| 2049 } |
| 2050 |
| 2051 |
| 2052 void Debugger::StopAgent() { |
| 2053 if (agent_ != NULL) { |
| 2054 agent_->Shutdown(); |
| 2055 agent_->Join(); |
| 2056 delete agent_; |
| 2057 agent_ = NULL; |
| 2058 } |
| 2059 } |
| 2060 |
| 2061 |
| 2062 void Debugger::TearDown() { |
| 2063 if (message_thread_ != NULL) { |
| 2064 message_thread_->Stop(); |
| 2065 delete message_thread_; |
| 2066 message_thread_ = NULL; |
| 2067 } |
| 2068 } |
| 2069 |
| 2070 |
| 2071 void DebugMessageThread::Run() { |
| 2072 // Sends debug events to an installed debugger message callback. |
| 2073 while (keep_running_) { |
| 2074 // Wait and Get are paired so that semaphore count equals queue length. |
| 2075 Debugger::message_received_->Wait(); |
| 2076 Logger::DebugTag("Get message from event message_queue."); |
| 2077 Vector<uint16_t> message = Debugger::message_queue_.Get(); |
| 2078 if (message.length() > 0) { |
| 2079 Debugger::InvokeMessageHandler(message); |
| 2080 } |
| 2081 } |
| 2082 } |
| 2083 |
| 2084 |
| 2085 void DebugMessageThread::Stop() { |
| 2086 keep_running_ = false; |
| 2087 Debugger::SendMessage(Vector<uint16_t>(NULL, 0)); |
| 2088 Join(); |
2127 } | 2089 } |
2128 | 2090 |
2129 | 2091 |
2130 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) { | 2092 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) { |
2131 messages_ = NewArray<Vector<uint16_t> >(size); | 2093 messages_ = NewArray<Vector<uint16_t> >(size); |
2132 } | 2094 } |
2133 | 2095 |
2134 | 2096 |
2135 MessageQueue::~MessageQueue() { | 2097 MessageQueue::~MessageQueue() { |
2136 DeleteArray(messages_); | 2098 DeleteArray(messages_); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2197 } | 2159 } |
2198 | 2160 |
2199 | 2161 |
2200 void LockingMessageQueue::Clear() { | 2162 void LockingMessageQueue::Clear() { |
2201 ScopedLock sl(lock_); | 2163 ScopedLock sl(lock_); |
2202 queue_.Clear(); | 2164 queue_.Clear(); |
2203 } | 2165 } |
2204 | 2166 |
2205 | 2167 |
2206 } } // namespace v8::internal | 2168 } } // namespace v8::internal |
OLD | NEW |