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 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 return true; | 600 return true; |
601 } | 601 } |
602 | 602 |
603 | 603 |
604 void Debug::Unload() { | 604 void Debug::Unload() { |
605 // Return debugger is not loaded. | 605 // Return debugger is not loaded. |
606 if (!IsLoaded()) { | 606 if (!IsLoaded()) { |
607 return; | 607 return; |
608 } | 608 } |
609 | 609 |
610 // Get rid of all break points and related information. | |
611 ClearAllBreakPoints(); | |
612 | |
613 // Clear debugger context global handle. | 610 // Clear debugger context global handle. |
614 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); | 611 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); |
615 debug_context_ = Handle<Context>(); | 612 debug_context_ = Handle<Context>(); |
616 } | 613 } |
617 | 614 |
618 | 615 |
619 // Set the flag indicating that preemption happened during debugging. | 616 // Set the flag indicating that preemption happened during debugging. |
620 void Debug::PreemptionWhileInDebugger() { | 617 void Debug::PreemptionWhileInDebugger() { |
621 ASSERT(InDebugger()); | 618 ASSERT(InDebugger()); |
622 Debug::set_preemption_pending(true); | 619 Debug::set_preemption_pending(true); |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1362 Handle<Object> fun(Top::global()->GetProperty(*function_name)); | 1359 Handle<Object> fun(Top::global()->GetProperty(*function_name)); |
1363 ASSERT(fun->IsJSFunction()); | 1360 ASSERT(fun->IsJSFunction()); |
1364 bool caught_exception; | 1361 bool caught_exception; |
1365 Handle<Object> js_object = Execution::TryCall( | 1362 Handle<Object> js_object = Execution::TryCall( |
1366 Handle<JSFunction>::cast(fun), | 1363 Handle<JSFunction>::cast(fun), |
1367 Handle<JSObject>(Debug::debug_context()->global()), | 1364 Handle<JSObject>(Debug::debug_context()->global()), |
1368 0, NULL, &caught_exception); | 1365 0, NULL, &caught_exception); |
1369 } | 1366 } |
1370 | 1367 |
1371 | 1368 |
| 1369 Mutex* Debugger::debugger_access_ = OS::CreateMutex(); |
1372 Handle<Object> Debugger::event_listener_ = Handle<Object>(); | 1370 Handle<Object> Debugger::event_listener_ = Handle<Object>(); |
1373 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); | 1371 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); |
1374 bool Debugger::debugger_active_ = false; | |
1375 bool Debugger::compiling_natives_ = false; | 1372 bool Debugger::compiling_natives_ = false; |
1376 bool Debugger::is_loading_debugger_ = false; | 1373 bool Debugger::is_loading_debugger_ = false; |
| 1374 bool Debugger::never_unload_debugger_ = false; |
1377 DebugMessageThread* Debugger::message_thread_ = NULL; | 1375 DebugMessageThread* Debugger::message_thread_ = NULL; |
1378 v8::DebugMessageHandler Debugger::message_handler_ = NULL; | 1376 v8::DebugMessageHandler Debugger::message_handler_ = NULL; |
| 1377 bool Debugger::message_handler_cleared_ = false; |
1379 void* Debugger::message_handler_data_ = NULL; | 1378 void* Debugger::message_handler_data_ = NULL; |
1380 v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL; | 1379 v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL; |
1381 void* Debugger::host_dispatch_handler_data_ = NULL; | 1380 void* Debugger::host_dispatch_handler_data_ = NULL; |
1382 DebuggerAgent* Debugger::agent_ = NULL; | 1381 DebuggerAgent* Debugger::agent_ = NULL; |
1383 LockingMessageQueue Debugger::command_queue_(kQueueInitialSize); | 1382 LockingMessageQueue Debugger::command_queue_(kQueueInitialSize); |
1384 LockingMessageQueue Debugger::message_queue_(kQueueInitialSize); | 1383 LockingMessageQueue Debugger::message_queue_(kQueueInitialSize); |
1385 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); | 1384 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); |
1386 Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0); | 1385 Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0); |
1387 | 1386 |
1388 | 1387 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1574 | 1573 |
1575 | 1574 |
1576 // Handle debugger actions when a new script is compiled. | 1575 // Handle debugger actions when a new script is compiled. |
1577 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) { | 1576 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) { |
1578 HandleScope scope; | 1577 HandleScope scope; |
1579 | 1578 |
1580 // No compile events while compiling natives. | 1579 // No compile events while compiling natives. |
1581 if (compiling_natives()) return; | 1580 if (compiling_natives()) return; |
1582 | 1581 |
1583 // No more to do if not debugging. | 1582 // No more to do if not debugging. |
1584 if (!debugger_active()) return; | 1583 if (!IsDebuggerActive()) return; |
1585 | 1584 |
1586 // Store whether in debugger before entering debugger. | 1585 // Store whether in debugger before entering debugger. |
1587 bool in_debugger = Debug::InDebugger(); | 1586 bool in_debugger = Debug::InDebugger(); |
1588 | 1587 |
1589 // Enter the debugger. | 1588 // Enter the debugger. |
1590 EnterDebugger debugger; | 1589 EnterDebugger debugger; |
1591 if (debugger.FailedToEnter()) return; | 1590 if (debugger.FailedToEnter()) return; |
1592 | 1591 |
1593 // If debugging there might be script break points registered for this | 1592 // If debugging there might be script break points registered for this |
1594 // script. Make sure that these break points are set. | 1593 // script. Make sure that these break points are set. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1703 // Silently ignore exceptions from debug event listeners. | 1702 // Silently ignore exceptions from debug event listeners. |
1704 } | 1703 } |
1705 } | 1704 } |
1706 } | 1705 } |
1707 | 1706 |
1708 // Clear the mirror cache. | 1707 // Clear the mirror cache. |
1709 Debug::ClearMirrorCache(); | 1708 Debug::ClearMirrorCache(); |
1710 } | 1709 } |
1711 | 1710 |
1712 | 1711 |
| 1712 void Debugger::UnloadDebugger() { |
| 1713 // Make sure that there are no breakpoints left. |
| 1714 Debug::ClearAllBreakPoints(); |
| 1715 |
| 1716 // Unload the debugger if feasible. |
| 1717 if (!never_unload_debugger_) { |
| 1718 Debug::Unload(); |
| 1719 } |
| 1720 |
| 1721 // Clear the flag indicating that the message handler was recently cleared. |
| 1722 message_handler_cleared_ = false; |
| 1723 } |
| 1724 |
| 1725 |
1713 void Debugger::NotifyMessageHandler(v8::DebugEvent event, | 1726 void Debugger::NotifyMessageHandler(v8::DebugEvent event, |
1714 Handle<Object> exec_state, | 1727 Handle<Object> exec_state, |
1715 Handle<Object> event_data, | 1728 Handle<Object> event_data, |
1716 bool auto_continue) { | 1729 bool auto_continue) { |
1717 HandleScope scope; | 1730 HandleScope scope; |
1718 | 1731 |
1719 if (!Debug::Load()) return; | 1732 if (!Debug::Load()) return; |
1720 | 1733 |
1721 // Process the individual events. | 1734 // Process the individual events. |
1722 bool interactive = false; | 1735 bool interactive = false; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1770 // Wait for new command in the queue. | 1783 // Wait for new command in the queue. |
1771 command_received_->Wait(); | 1784 command_received_->Wait(); |
1772 | 1785 |
1773 // The debug command interrupt flag might have been set when the command was | 1786 // The debug command interrupt flag might have been set when the command was |
1774 // added. | 1787 // added. |
1775 StackGuard::Continue(DEBUGCOMMAND); | 1788 StackGuard::Continue(DEBUGCOMMAND); |
1776 | 1789 |
1777 // Get the command from the queue. | 1790 // Get the command from the queue. |
1778 Vector<uint16_t> command = command_queue_.Get(); | 1791 Vector<uint16_t> command = command_queue_.Get(); |
1779 Logger::DebugTag("Got request from command queue, in interactive loop."); | 1792 Logger::DebugTag("Got request from command queue, in interactive loop."); |
1780 if (!Debugger::debugger_active()) { | 1793 if (!Debugger::IsDebuggerActive()) { |
1781 return; | 1794 return; |
1782 } | 1795 } |
1783 | 1796 |
1784 // Check if the command is a host dispatch. | 1797 // Check if the command is a host dispatch. |
1785 if (command[0] == 0) { | 1798 if (command[0] == 0) { |
1786 if (Debugger::host_dispatch_handler_) { | 1799 if (Debugger::host_dispatch_handler_) { |
1787 int32_t dispatch = (command[1] << 16) | command[2]; | 1800 int32_t dispatch = (command[1] << 16) | command[2]; |
1788 Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch), | 1801 Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch), |
1789 Debugger::host_dispatch_handler_data_); | 1802 Debugger::host_dispatch_handler_data_); |
1790 } | 1803 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1873 // If there is a new debug event listener register it together with its data | 1886 // If there is a new debug event listener register it together with its data |
1874 // object. | 1887 // object. |
1875 if (!callback->IsUndefined() && !callback->IsNull()) { | 1888 if (!callback->IsUndefined() && !callback->IsNull()) { |
1876 event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback)); | 1889 event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback)); |
1877 if (data.is_null()) { | 1890 if (data.is_null()) { |
1878 data = Factory::undefined_value(); | 1891 data = Factory::undefined_value(); |
1879 } | 1892 } |
1880 event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data)); | 1893 event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data)); |
1881 } | 1894 } |
1882 | 1895 |
1883 UpdateActiveDebugger(); | 1896 // Unload the debugger if event listener cleared. |
| 1897 if (callback->IsUndefined()) { |
| 1898 UnloadDebugger(); |
| 1899 } |
1884 } | 1900 } |
1885 | 1901 |
1886 | 1902 |
1887 void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data, | 1903 void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data, |
1888 bool message_handler_thread) { | 1904 bool message_handler_thread) { |
| 1905 ScopedLock with(debugger_access_); |
| 1906 |
1889 message_handler_ = handler; | 1907 message_handler_ = handler; |
1890 message_handler_data_ = data; | 1908 message_handler_data_ = data; |
1891 if (!message_thread_ && message_handler_thread) { | 1909 if (handler != NULL) { |
1892 message_thread_ = new DebugMessageThread(); | 1910 if (!message_thread_ && message_handler_thread) { |
1893 message_thread_->Start(); | 1911 message_thread_ = new DebugMessageThread(); |
| 1912 message_thread_->Start(); |
| 1913 } |
| 1914 } else { |
| 1915 // Indicate that the message handler was recently cleared. |
| 1916 message_handler_cleared_ = true; |
| 1917 |
| 1918 // Send an empty command to the debugger if in a break to make JavaScript |
| 1919 // run again if the debugger is closed. |
| 1920 if (Debug::InDebugger()) { |
| 1921 ProcessCommand(Vector<const uint16_t>::empty()); |
| 1922 } |
1894 } | 1923 } |
1895 UpdateActiveDebugger(); | |
1896 } | 1924 } |
1897 | 1925 |
1898 | 1926 |
1899 void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler, | 1927 void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler, |
1900 void* data) { | 1928 void* data) { |
1901 host_dispatch_handler_ = handler; | 1929 host_dispatch_handler_ = handler; |
1902 host_dispatch_handler_data_ = data; | 1930 host_dispatch_handler_data_ = data; |
1903 } | 1931 } |
1904 | 1932 |
1905 | 1933 |
1906 // Calls the registered debug message handler. This callback is part of the | 1934 // 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 | 1935 // public API. Messages are kept internally as Vector<uint16_t> strings, which |
1908 // are allocated in various places and deallocated by the calling function | 1936 // are allocated in various places and deallocated by the calling function |
1909 // sometime after this call. | 1937 // sometime after this call. |
1910 void Debugger::InvokeMessageHandler(Vector<uint16_t> message) { | 1938 void Debugger::InvokeMessageHandler(Vector<uint16_t> message) { |
| 1939 ScopedLock with(debugger_access_); |
| 1940 |
1911 if (message_handler_ != NULL) { | 1941 if (message_handler_ != NULL) { |
1912 message_handler_(message.start(), message.length(), message_handler_data_); | 1942 message_handler_(message.start(), message.length(), message_handler_data_); |
1913 } | 1943 } |
1914 } | 1944 } |
1915 | 1945 |
1916 | 1946 |
1917 void Debugger::SendMessage(Vector<uint16_t> message) { | 1947 void Debugger::SendMessage(Vector<uint16_t> message) { |
1918 if (message_thread_ == NULL) { | 1948 if (message_thread_ == NULL) { |
1919 // If there is no message thread just invoke the message handler from the | 1949 // If there is no message thread just invoke the message handler from the |
1920 // V8 thread. | 1950 // V8 thread. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1992 uint16_t hack[3]; | 2022 uint16_t hack[3]; |
1993 hack[0] = 0; | 2023 hack[0] = 0; |
1994 hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16; | 2024 hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16; |
1995 hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF; | 2025 hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF; |
1996 Logger::DebugTag("Put dispatch on command_queue."); | 2026 Logger::DebugTag("Put dispatch on command_queue."); |
1997 command_queue_.Put(Vector<uint16_t>(hack, 3).Clone()); | 2027 command_queue_.Put(Vector<uint16_t>(hack, 3).Clone()); |
1998 command_received_->Signal(); | 2028 command_received_->Signal(); |
1999 } | 2029 } |
2000 | 2030 |
2001 | 2031 |
2002 void Debugger::UpdateActiveDebugger() { | 2032 bool Debugger::IsDebuggerActive() { |
2003 set_debugger_active(message_handler_ != NULL || !event_listener_.is_null()); | 2033 ScopedLock with(debugger_access_); |
2004 if (!debugger_active() && message_thread_) { | 2034 |
2005 // Send an empty command to the debugger if in a break to make JavaScript | 2035 return message_handler_ != NULL || !event_listener_.is_null(); |
2006 // run again if the debugger is closed. | |
2007 ProcessCommand(Vector<const uint16_t>::empty()); | |
2008 } | |
2009 if (!debugger_active()) { | |
2010 Debug::Unload(); | |
2011 } | |
2012 } | 2036 } |
2013 | 2037 |
2014 | 2038 |
2015 Handle<Object> Debugger::Call(Handle<JSFunction> fun, | 2039 Handle<Object> Debugger::Call(Handle<JSFunction> fun, |
2016 Handle<Object> data, | 2040 Handle<Object> data, |
2017 bool* pending_exception) { | 2041 bool* pending_exception) { |
| 2042 // When calling functions in the debugger prevent it from beeing unloaded. |
| 2043 Debugger::never_unload_debugger_ = true; |
| 2044 |
2018 // Enter the debugger. | 2045 // Enter the debugger. |
2019 EnterDebugger debugger; | 2046 EnterDebugger debugger; |
2020 if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) { | 2047 if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) { |
2021 return Factory::undefined_value(); | 2048 return Factory::undefined_value(); |
2022 } | 2049 } |
2023 | 2050 |
2024 // Create the execution state. | 2051 // Create the execution state. |
2025 bool caught_exception = false; | 2052 bool caught_exception = false; |
2026 Handle<Object> exec_state = MakeExecutionState(&caught_exception); | 2053 Handle<Object> exec_state = MakeExecutionState(&caught_exception); |
2027 if (caught_exception) { | 2054 if (caught_exception) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2157 } | 2184 } |
2158 | 2185 |
2159 | 2186 |
2160 void LockingMessageQueue::Clear() { | 2187 void LockingMessageQueue::Clear() { |
2161 ScopedLock sl(lock_); | 2188 ScopedLock sl(lock_); |
2162 queue_.Clear(); | 2189 queue_.Clear(); |
2163 } | 2190 } |
2164 | 2191 |
2165 | 2192 |
2166 } } // namespace v8::internal | 2193 } } // namespace v8::internal |
OLD | NEW |