| 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 23 matching lines...) Expand all Loading... |
| 34 #include "compiler.h" | 34 #include "compiler.h" |
| 35 #include "debug.h" | 35 #include "debug.h" |
| 36 #include "execution.h" | 36 #include "execution.h" |
| 37 #include "global-handles.h" | 37 #include "global-handles.h" |
| 38 #include "ic.h" | 38 #include "ic.h" |
| 39 #include "ic-inl.h" | 39 #include "ic-inl.h" |
| 40 #include "natives.h" | 40 #include "natives.h" |
| 41 #include "stub-cache.h" | 41 #include "stub-cache.h" |
| 42 #include "log.h" | 42 #include "log.h" |
| 43 | 43 |
| 44 #include "../include/v8-debug.h" | |
| 45 | |
| 46 namespace v8 { namespace internal { | 44 namespace v8 { namespace internal { |
| 47 | 45 |
| 48 #ifdef ENABLE_DEBUGGER_SUPPORT | 46 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 49 static void PrintLn(v8::Local<v8::Value> value) { | 47 static void PrintLn(v8::Local<v8::Value> value) { |
| 50 v8::Local<v8::String> s = value->ToString(); | 48 v8::Local<v8::String> s = value->ToString(); |
| 51 char* data = NewArray<char>(s->Length() + 1); | 49 char* data = NewArray<char>(s->Length() + 1); |
| 52 if (data == NULL) { | 50 if (data == NULL) { |
| 53 V8::FatalProcessOutOfMemory("PrintLn"); | 51 V8::FatalProcessOutOfMemory("PrintLn"); |
| 54 return; | 52 return; |
| 55 } | 53 } |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 // Patch the code to invoke the builtin debug break function matching the | 370 // Patch the code to invoke the builtin debug break function matching the |
| 373 // calling convention used by the call site. | 371 // calling convention used by the call site. |
| 374 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode)); | 372 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode)); |
| 375 rinfo()->set_target_address(dbgbrk_code->entry()); | 373 rinfo()->set_target_address(dbgbrk_code->entry()); |
| 376 | 374 |
| 377 // For stubs that refer back to an inlined version clear the cached map for | 375 // For stubs that refer back to an inlined version clear the cached map for |
| 378 // the inlined case to always go through the IC. As long as the break point | 376 // the inlined case to always go through the IC. As long as the break point |
| 379 // is set the patching performed by the runtime system will take place in | 377 // is set the patching performed by the runtime system will take place in |
| 380 // the code copy and will therefore have no effect on the running code | 378 // the code copy and will therefore have no effect on the running code |
| 381 // keeping it from using the inlined code. | 379 // keeping it from using the inlined code. |
| 382 if (code->is_keyed_load_stub() && KeyedLoadIC::HasInlinedVersion(pc())) { | 380 if (code->is_keyed_load_stub()) KeyedLoadIC::ClearInlinedVersion(pc()); |
| 383 KeyedLoadIC::ClearInlinedVersion(pc()); | |
| 384 } | |
| 385 } | 381 } |
| 386 } | 382 } |
| 387 | 383 |
| 388 | 384 |
| 389 void BreakLocationIterator::ClearDebugBreakAtIC() { | 385 void BreakLocationIterator::ClearDebugBreakAtIC() { |
| 390 // Patch the code to the original invoke. | 386 // Patch the code to the original invoke. |
| 391 rinfo()->set_target_address(original_rinfo()->target_address()); | 387 rinfo()->set_target_address(original_rinfo()->target_address()); |
| 392 } | 388 } |
| 393 | 389 |
| 394 | 390 |
| (...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 Handle<Object> event_data; | 1545 Handle<Object> event_data; |
| 1550 if (!caught_exception) { | 1546 if (!caught_exception) { |
| 1551 event_data = MakeExceptionEvent(exec_state, exception, uncaught, | 1547 event_data = MakeExceptionEvent(exec_state, exception, uncaught, |
| 1552 &caught_exception); | 1548 &caught_exception); |
| 1553 } | 1549 } |
| 1554 // Bail out and don't call debugger if exception. | 1550 // Bail out and don't call debugger if exception. |
| 1555 if (caught_exception) { | 1551 if (caught_exception) { |
| 1556 return; | 1552 return; |
| 1557 } | 1553 } |
| 1558 | 1554 |
| 1559 // Process debug event. | 1555 // Process debug event |
| 1560 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 1556 ProcessDebugEvent(v8::Exception, event_data, false); |
| 1561 // Return to continue execution from where the exception was thrown. | 1557 // Return to continue execution from where the exception was thrown. |
| 1562 } | 1558 } |
| 1563 | 1559 |
| 1564 | 1560 |
| 1565 void Debugger::OnDebugBreak(Handle<Object> break_points_hit, | 1561 void Debugger::OnDebugBreak(Handle<Object> break_points_hit, |
| 1566 bool auto_continue) { | 1562 bool auto_continue) { |
| 1567 HandleScope scope; | 1563 HandleScope scope; |
| 1568 | 1564 |
| 1569 // Debugger has already been entered by caller. | 1565 // Debugger has already been entered by caller. |
| 1570 ASSERT(Top::context() == *Debug::debug_context()); | 1566 ASSERT(Top::context() == *Debug::debug_context()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1581 Handle<Object> event_data; | 1577 Handle<Object> event_data; |
| 1582 if (!caught_exception) { | 1578 if (!caught_exception) { |
| 1583 event_data = MakeBreakEvent(exec_state, break_points_hit, | 1579 event_data = MakeBreakEvent(exec_state, break_points_hit, |
| 1584 &caught_exception); | 1580 &caught_exception); |
| 1585 } | 1581 } |
| 1586 // Bail out and don't call debugger if exception. | 1582 // Bail out and don't call debugger if exception. |
| 1587 if (caught_exception) { | 1583 if (caught_exception) { |
| 1588 return; | 1584 return; |
| 1589 } | 1585 } |
| 1590 | 1586 |
| 1591 // Process debug event. | 1587 // Process debug event |
| 1592 ProcessDebugEvent(v8::Break, | 1588 ProcessDebugEvent(v8::Break, event_data, auto_continue); |
| 1593 Handle<JSObject>::cast(event_data), | |
| 1594 auto_continue); | |
| 1595 } | 1589 } |
| 1596 | 1590 |
| 1597 | 1591 |
| 1598 void Debugger::OnBeforeCompile(Handle<Script> script) { | 1592 void Debugger::OnBeforeCompile(Handle<Script> script) { |
| 1599 HandleScope scope; | 1593 HandleScope scope; |
| 1600 | 1594 |
| 1601 // Bail out based on state or if there is no listener for this event | 1595 // Bail out based on state or if there is no listener for this event |
| 1602 if (Debug::InDebugger()) return; | 1596 if (Debug::InDebugger()) return; |
| 1603 if (compiling_natives()) return; | 1597 if (compiling_natives()) return; |
| 1604 if (!EventActive(v8::BeforeCompile)) return; | 1598 if (!EventActive(v8::BeforeCompile)) return; |
| 1605 | 1599 |
| 1606 // Enter the debugger. | 1600 // Enter the debugger. |
| 1607 EnterDebugger debugger; | 1601 EnterDebugger debugger; |
| 1608 if (debugger.FailedToEnter()) return; | 1602 if (debugger.FailedToEnter()) return; |
| 1609 | 1603 |
| 1610 // Create the event data object. | 1604 // Create the event data object. |
| 1611 bool caught_exception = false; | 1605 bool caught_exception = false; |
| 1612 Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception); | 1606 Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception); |
| 1613 // Bail out and don't call debugger if exception. | 1607 // Bail out and don't call debugger if exception. |
| 1614 if (caught_exception) { | 1608 if (caught_exception) { |
| 1615 return; | 1609 return; |
| 1616 } | 1610 } |
| 1617 | 1611 |
| 1618 // Process debug event. | 1612 // Process debug event |
| 1619 ProcessDebugEvent(v8::BeforeCompile, | 1613 ProcessDebugEvent(v8::BeforeCompile, event_data, true); |
| 1620 Handle<JSObject>::cast(event_data), | |
| 1621 true); | |
| 1622 } | 1614 } |
| 1623 | 1615 |
| 1624 | 1616 |
| 1625 // Handle debugger actions when a new script is compiled. | 1617 // Handle debugger actions when a new script is compiled. |
| 1626 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) { | 1618 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) { |
| 1627 HandleScope scope; | 1619 HandleScope scope; |
| 1628 | 1620 |
| 1629 // No compile events while compiling natives. | 1621 // No compile events while compiling natives. |
| 1630 if (compiling_natives()) return; | 1622 if (compiling_natives()) return; |
| 1631 | 1623 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 if (!Debugger::EventActive(v8::AfterCompile)) return; | 1663 if (!Debugger::EventActive(v8::AfterCompile)) return; |
| 1672 | 1664 |
| 1673 // Create the compile state object. | 1665 // Create the compile state object. |
| 1674 Handle<Object> event_data = MakeCompileEvent(script, | 1666 Handle<Object> event_data = MakeCompileEvent(script, |
| 1675 false, | 1667 false, |
| 1676 &caught_exception); | 1668 &caught_exception); |
| 1677 // Bail out and don't call debugger if exception. | 1669 // Bail out and don't call debugger if exception. |
| 1678 if (caught_exception) { | 1670 if (caught_exception) { |
| 1679 return; | 1671 return; |
| 1680 } | 1672 } |
| 1681 // Process debug event. | 1673 // Process debug event |
| 1682 ProcessDebugEvent(v8::AfterCompile, | 1674 ProcessDebugEvent(v8::AfterCompile, event_data, true); |
| 1683 Handle<JSObject>::cast(event_data), | |
| 1684 true); | |
| 1685 } | 1675 } |
| 1686 | 1676 |
| 1687 | 1677 |
| 1688 void Debugger::OnNewFunction(Handle<JSFunction> function) { | 1678 void Debugger::OnNewFunction(Handle<JSFunction> function) { |
| 1689 return; | 1679 return; |
| 1690 HandleScope scope; | 1680 HandleScope scope; |
| 1691 | 1681 |
| 1692 // Bail out based on state or if there is no listener for this event | 1682 // Bail out based on state or if there is no listener for this event |
| 1693 if (Debug::InDebugger()) return; | 1683 if (Debug::InDebugger()) return; |
| 1694 if (compiling_natives()) return; | 1684 if (compiling_natives()) return; |
| 1695 if (!Debugger::EventActive(v8::NewFunction)) return; | 1685 if (!Debugger::EventActive(v8::NewFunction)) return; |
| 1696 | 1686 |
| 1697 // Enter the debugger. | 1687 // Enter the debugger. |
| 1698 EnterDebugger debugger; | 1688 EnterDebugger debugger; |
| 1699 if (debugger.FailedToEnter()) return; | 1689 if (debugger.FailedToEnter()) return; |
| 1700 | 1690 |
| 1701 // Create the event object. | 1691 // Create the event object. |
| 1702 bool caught_exception = false; | 1692 bool caught_exception = false; |
| 1703 Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception); | 1693 Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception); |
| 1704 // Bail out and don't call debugger if exception. | 1694 // Bail out and don't call debugger if exception. |
| 1705 if (caught_exception) { | 1695 if (caught_exception) { |
| 1706 return; | 1696 return; |
| 1707 } | 1697 } |
| 1708 // Process debug event. | 1698 // Process debug event. |
| 1709 ProcessDebugEvent(v8::NewFunction, Handle<JSObject>::cast(event_data), true); | 1699 ProcessDebugEvent(v8::NewFunction, event_data, true); |
| 1710 } | 1700 } |
| 1711 | 1701 |
| 1712 | 1702 |
| 1713 void Debugger::ProcessDebugEvent(v8::DebugEvent event, | 1703 void Debugger::ProcessDebugEvent(v8::DebugEvent event, |
| 1714 Handle<JSObject> event_data, | 1704 Handle<Object> event_data, |
| 1715 bool auto_continue) { | 1705 bool auto_continue) { |
| 1716 HandleScope scope; | 1706 HandleScope scope; |
| 1717 | 1707 |
| 1718 // Create the execution state. | 1708 // Create the execution state. |
| 1719 bool caught_exception = false; | 1709 bool caught_exception = false; |
| 1720 Handle<Object> exec_state = MakeExecutionState(&caught_exception); | 1710 Handle<Object> exec_state = MakeExecutionState(&caught_exception); |
| 1721 if (caught_exception) { | 1711 if (caught_exception) { |
| 1722 return; | 1712 return; |
| 1723 } | 1713 } |
| 1724 // First notify the message handler if any. | 1714 // First notify the message handler if any. |
| 1725 if (message_handler_ != NULL) { | 1715 if (message_handler_ != NULL) { |
| 1726 NotifyMessageHandler(event, | 1716 NotifyMessageHandler(event, exec_state, event_data, auto_continue); |
| 1727 Handle<JSObject>::cast(exec_state), | |
| 1728 event_data, | |
| 1729 auto_continue); | |
| 1730 } | 1717 } |
| 1731 // Notify registered debug event listener. This can be either a C or a | 1718 // Notify registered debug event listener. This can be either a C or a |
| 1732 // JavaScript function. | 1719 // JavaScript function. |
| 1733 if (!event_listener_.is_null()) { | 1720 if (!event_listener_.is_null()) { |
| 1734 if (event_listener_->IsProxy()) { | 1721 if (event_listener_->IsProxy()) { |
| 1735 // C debug event listener. | 1722 // C debug event listener. |
| 1736 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); | 1723 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); |
| 1737 v8::Debug::EventCallback callback = | 1724 v8::Debug::EventCallback callback = |
| 1738 FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy()); | 1725 FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy()); |
| 1739 callback(event, | 1726 callback(event, |
| 1740 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), | 1727 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
| 1741 v8::Utils::ToLocal(event_data), | 1728 v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)), |
| 1742 v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_))); | 1729 v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_))); |
| 1743 } else { | 1730 } else { |
| 1744 // JavaScript debug event listener. | 1731 // JavaScript debug event listener. |
| 1745 ASSERT(event_listener_->IsJSFunction()); | 1732 ASSERT(event_listener_->IsJSFunction()); |
| 1746 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); | 1733 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); |
| 1747 | 1734 |
| 1748 // Invoke the JavaScript debug event listener. | 1735 // Invoke the JavaScript debug event listener. |
| 1749 const int argc = 4; | 1736 const int argc = 4; |
| 1750 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), | 1737 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), |
| 1751 exec_state.location(), | 1738 exec_state.location(), |
| 1752 Handle<Object>::cast(event_data).location(), | 1739 event_data.location(), |
| 1753 event_listener_data_.location() }; | 1740 event_listener_data_.location() }; |
| 1754 Handle<Object> result = Execution::TryCall(fun, Top::global(), | 1741 Handle<Object> result = Execution::TryCall(fun, Top::global(), |
| 1755 argc, argv, &caught_exception); | 1742 argc, argv, &caught_exception); |
| 1756 if (caught_exception) { | 1743 if (caught_exception) { |
| 1757 // Silently ignore exceptions from debug event listeners. | 1744 // Silently ignore exceptions from debug event listeners. |
| 1758 } | 1745 } |
| 1759 } | 1746 } |
| 1760 } | 1747 } |
| 1761 | 1748 |
| 1762 // Clear the mirror cache. | 1749 // Clear the mirror cache. |
| 1763 Debug::ClearMirrorCache(); | 1750 Debug::ClearMirrorCache(); |
| 1764 } | 1751 } |
| 1765 | 1752 |
| 1766 | 1753 |
| 1767 void Debugger::UnloadDebugger() { | 1754 void Debugger::UnloadDebugger() { |
| 1768 // Make sure that there are no breakpoints left. | 1755 // Make sure that there are no breakpoints left. |
| 1769 Debug::ClearAllBreakPoints(); | 1756 Debug::ClearAllBreakPoints(); |
| 1770 | 1757 |
| 1771 // Unload the debugger if feasible. | 1758 // Unload the debugger if feasible. |
| 1772 if (!never_unload_debugger_) { | 1759 if (!never_unload_debugger_) { |
| 1773 Debug::Unload(); | 1760 Debug::Unload(); |
| 1774 } | 1761 } |
| 1775 | 1762 |
| 1776 // Clear the flag indicating that the message handler was recently cleared. | 1763 // Clear the flag indicating that the message handler was recently cleared. |
| 1777 message_handler_cleared_ = false; | 1764 message_handler_cleared_ = false; |
| 1778 } | 1765 } |
| 1779 | 1766 |
| 1780 | 1767 |
| 1781 void Debugger::NotifyMessageHandler(v8::DebugEvent event, | 1768 void Debugger::NotifyMessageHandler(v8::DebugEvent event, |
| 1782 Handle<JSObject> exec_state, | 1769 Handle<Object> exec_state, |
| 1783 Handle<JSObject> event_data, | 1770 Handle<Object> event_data, |
| 1784 bool auto_continue) { | 1771 bool auto_continue) { |
| 1785 HandleScope scope; | 1772 HandleScope scope; |
| 1786 | 1773 |
| 1787 if (!Debug::Load()) return; | 1774 if (!Debug::Load()) return; |
| 1788 | 1775 |
| 1789 // Process the individual events. | 1776 // Process the individual events. |
| 1790 bool sendEventMessage = false; | 1777 bool sendEventMessage = false; |
| 1791 switch (event) { | 1778 switch (event) { |
| 1792 case v8::Break: | 1779 case v8::Break: |
| 1793 sendEventMessage = !auto_continue; | 1780 sendEventMessage = !auto_continue; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1808 | 1795 |
| 1809 // The debug command interrupt flag might have been set when the command was | 1796 // The debug command interrupt flag might have been set when the command was |
| 1810 // added. It should be enough to clear the flag only once while we are in the | 1797 // added. It should be enough to clear the flag only once while we are in the |
| 1811 // debugger. | 1798 // debugger. |
| 1812 ASSERT(Debug::InDebugger()); | 1799 ASSERT(Debug::InDebugger()); |
| 1813 StackGuard::Continue(DEBUGCOMMAND); | 1800 StackGuard::Continue(DEBUGCOMMAND); |
| 1814 | 1801 |
| 1815 // Notify the debugger that a debug event has occurred unless auto continue is | 1802 // Notify the debugger that a debug event has occurred unless auto continue is |
| 1816 // active in which case no event is send. | 1803 // active in which case no event is send. |
| 1817 if (sendEventMessage) { | 1804 if (sendEventMessage) { |
| 1818 MessageImpl message = MessageImpl::NewEvent( | 1805 InvokeMessageHandlerWithEvent(event_data); |
| 1819 event, | |
| 1820 auto_continue, | |
| 1821 Handle<JSObject>::cast(exec_state), | |
| 1822 Handle<JSObject>::cast(event_data)); | |
| 1823 InvokeMessageHandler(message); | |
| 1824 } | 1806 } |
| 1825 if (auto_continue && !HasCommands()) { | 1807 if (auto_continue && !HasCommands()) { |
| 1826 return; | 1808 return; |
| 1827 } | 1809 } |
| 1828 | 1810 |
| 1829 // Get the DebugCommandProcessor. | 1811 // Get the DebugCommandProcessor. |
| 1830 v8::Local<v8::Object> api_exec_state = | 1812 v8::Local<v8::Object> api_exec_state = |
| 1831 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)); | 1813 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)); |
| 1832 v8::Local<v8::String> fun_name = | 1814 v8::Local<v8::String> fun_name = |
| 1833 v8::String::New("debugCommandProcessor"); | 1815 v8::String::New("debugCommandProcessor"); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 // Invoke JavaScript to process the debug request. | 1850 // Invoke JavaScript to process the debug request. |
| 1869 v8::Local<v8::String> fun_name; | 1851 v8::Local<v8::String> fun_name; |
| 1870 v8::Local<v8::Function> fun; | 1852 v8::Local<v8::Function> fun; |
| 1871 v8::Local<v8::Value> request; | 1853 v8::Local<v8::Value> request; |
| 1872 v8::TryCatch try_catch; | 1854 v8::TryCatch try_catch; |
| 1873 fun_name = v8::String::New("processDebugRequest"); | 1855 fun_name = v8::String::New("processDebugRequest"); |
| 1874 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); | 1856 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); |
| 1875 | 1857 |
| 1876 request = v8::String::New(command.text().start(), | 1858 request = v8::String::New(command.text().start(), |
| 1877 command.text().length()); | 1859 command.text().length()); |
| 1860 command.text().Dispose(); |
| 1878 static const int kArgc = 1; | 1861 static const int kArgc = 1; |
| 1879 v8::Handle<Value> argv[kArgc] = { request }; | 1862 v8::Handle<Value> argv[kArgc] = { request }; |
| 1880 v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv); | 1863 v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv); |
| 1881 | 1864 |
| 1882 // Get the response. | 1865 // Get the response. |
| 1883 v8::Local<v8::String> response; | 1866 v8::Local<v8::String> response; |
| 1884 bool running = false; | 1867 bool running = false; |
| 1885 if (!try_catch.HasCaught()) { | 1868 if (!try_catch.HasCaught()) { |
| 1886 // Get response string. | 1869 // Get response string. |
| 1887 if (!response_val->IsUndefined()) { | 1870 if (!response_val->IsUndefined()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1904 v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv); | 1887 v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv); |
| 1905 if (!try_catch.HasCaught()) { | 1888 if (!try_catch.HasCaught()) { |
| 1906 running = running_val->ToBoolean()->Value(); | 1889 running = running_val->ToBoolean()->Value(); |
| 1907 } | 1890 } |
| 1908 } else { | 1891 } else { |
| 1909 // In case of failure the result text is the exception text. | 1892 // In case of failure the result text is the exception text. |
| 1910 response = try_catch.Exception()->ToString(); | 1893 response = try_catch.Exception()->ToString(); |
| 1911 } | 1894 } |
| 1912 | 1895 |
| 1913 // Return the result. | 1896 // Return the result. |
| 1914 MessageImpl message = MessageImpl::NewResponse( | 1897 InvokeMessageHandler(response, command.client_data()); |
| 1915 event, | |
| 1916 running, | |
| 1917 Handle<JSObject>::cast(exec_state), | |
| 1918 Handle<JSObject>::cast(event_data), | |
| 1919 Handle<String>(Utils::OpenHandle(*response)), | |
| 1920 command.client_data()); | |
| 1921 InvokeMessageHandler(message); | |
| 1922 command.Dispose(); | |
| 1923 | 1898 |
| 1924 // Return from debug event processing if either the VM is put into the | 1899 // Return from debug event processing if either the VM is put into the |
| 1925 // runnning state (through a continue command) or auto continue is active | 1900 // runnning state (through a continue command) or auto continue is active |
| 1926 // and there are no more commands queued. | 1901 // and there are no more commands queued. |
| 1927 if (running || (auto_continue && !HasCommands())) { | 1902 if (running || (auto_continue && !HasCommands())) { |
| 1928 return; | 1903 return; |
| 1929 } | 1904 } |
| 1930 } | 1905 } |
| 1931 } | 1906 } |
| 1932 | 1907 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1983 | 1958 |
| 1984 | 1959 |
| 1985 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, | 1960 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, |
| 1986 int period) { | 1961 int period) { |
| 1987 host_dispatch_handler_ = handler; | 1962 host_dispatch_handler_ = handler; |
| 1988 host_dispatch_micros_ = period * 1000; | 1963 host_dispatch_micros_ = period * 1000; |
| 1989 } | 1964 } |
| 1990 | 1965 |
| 1991 | 1966 |
| 1992 // Calls the registered debug message handler. This callback is part of the | 1967 // Calls the registered debug message handler. This callback is part of the |
| 1993 // public API. | 1968 // public API. Messages are kept internally as Vector<uint16_t> strings, which |
| 1994 void Debugger::InvokeMessageHandler(MessageImpl message) { | 1969 // are allocated in various places and deallocated by the calling function |
| 1970 // sometime after this call. |
| 1971 void Debugger::InvokeMessageHandler(v8::Handle<v8::String> output, |
| 1972 v8::Debug::ClientData* data) { |
| 1995 ScopedLock with(debugger_access_); | 1973 ScopedLock with(debugger_access_); |
| 1996 | 1974 |
| 1997 if (message_handler_ != NULL) { | 1975 if (message_handler_ != NULL) { |
| 1998 message_handler_(message); | 1976 Vector<uint16_t> text = Vector<uint16_t>::New(output->Length()); |
| 1977 output->Write(text.start(), 0, output->Length()); |
| 1978 |
| 1979 message_handler_(text.start(), |
| 1980 text.length(), |
| 1981 data); |
| 1982 |
| 1983 text.Dispose(); |
| 1999 } | 1984 } |
| 1985 delete data; |
| 1986 } |
| 1987 |
| 1988 |
| 1989 bool Debugger::InvokeMessageHandlerWithEvent(Handle<Object> event_data) { |
| 1990 v8::HandleScope scope; |
| 1991 // Call toJSONProtocol on the debug event object. |
| 1992 v8::Local<v8::Object> api_event_data = |
| 1993 v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)); |
| 1994 v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol"); |
| 1995 v8::Local<v8::Function> fun = |
| 1996 v8::Function::Cast(*api_event_data->Get(fun_name)); |
| 1997 v8::TryCatch try_catch; |
| 1998 v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL); |
| 1999 v8::Local<v8::String> json_event_string; |
| 2000 if (!try_catch.HasCaught()) { |
| 2001 if (!json_event->IsUndefined()) { |
| 2002 json_event_string = json_event->ToString(); |
| 2003 if (FLAG_trace_debug_json) { |
| 2004 PrintLn(json_event_string); |
| 2005 } |
| 2006 InvokeMessageHandler(json_event_string, |
| 2007 NULL /* no user data since there was no request */); |
| 2008 } else { |
| 2009 InvokeMessageHandler(v8::String::Empty(), NULL); |
| 2010 } |
| 2011 } else { |
| 2012 PrintLn(try_catch.Exception()); |
| 2013 return false; |
| 2014 } |
| 2015 return true; |
| 2000 } | 2016 } |
| 2001 | 2017 |
| 2002 | 2018 |
| 2003 // Puts a command coming from the public API on the queue. Creates | 2019 // Puts a command coming from the public API on the queue. Creates |
| 2004 // a copy of the command string managed by the debugger. Up to this | 2020 // a copy of the command string managed by the debugger. Up to this |
| 2005 // point, the command data was managed by the API client. Called | 2021 // point, the command data was managed by the API client. Called |
| 2006 // by the API client thread. | 2022 // by the API client thread. |
| 2007 void Debugger::ProcessCommand(Vector<const uint16_t> command, | 2023 void Debugger::ProcessCommand(Vector<const uint16_t> command, |
| 2008 v8::Debug::ClientData* client_data) { | 2024 v8::Debug::ClientData* client_data) { |
| 2009 // Need to cast away const. | 2025 // Need to cast away const. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 void Debugger::StopAgent() { | 2091 void Debugger::StopAgent() { |
| 2076 if (agent_ != NULL) { | 2092 if (agent_ != NULL) { |
| 2077 agent_->Shutdown(); | 2093 agent_->Shutdown(); |
| 2078 agent_->Join(); | 2094 agent_->Join(); |
| 2079 delete agent_; | 2095 delete agent_; |
| 2080 agent_ = NULL; | 2096 agent_ = NULL; |
| 2081 } | 2097 } |
| 2082 } | 2098 } |
| 2083 | 2099 |
| 2084 | 2100 |
| 2085 MessageImpl MessageImpl::NewEvent(DebugEvent event, | |
| 2086 bool running, | |
| 2087 Handle<JSObject> exec_state, | |
| 2088 Handle<JSObject> event_data) { | |
| 2089 MessageImpl message(true, event, running, | |
| 2090 exec_state, event_data, Handle<String>(), NULL); | |
| 2091 return message; | |
| 2092 } | |
| 2093 | |
| 2094 | |
| 2095 MessageImpl MessageImpl::NewResponse(DebugEvent event, | |
| 2096 bool running, | |
| 2097 Handle<JSObject> exec_state, | |
| 2098 Handle<JSObject> event_data, | |
| 2099 Handle<String> response_json, | |
| 2100 v8::Debug::ClientData* client_data) { | |
| 2101 MessageImpl message(false, event, running, | |
| 2102 exec_state, event_data, response_json, client_data); | |
| 2103 return message; | |
| 2104 } | |
| 2105 | |
| 2106 | |
| 2107 MessageImpl::MessageImpl(bool is_event, | |
| 2108 DebugEvent event, | |
| 2109 bool running, | |
| 2110 Handle<JSObject> exec_state, | |
| 2111 Handle<JSObject> event_data, | |
| 2112 Handle<String> response_json, | |
| 2113 v8::Debug::ClientData* client_data) | |
| 2114 : is_event_(is_event), | |
| 2115 event_(event), | |
| 2116 running_(running), | |
| 2117 exec_state_(exec_state), | |
| 2118 event_data_(event_data), | |
| 2119 response_json_(response_json), | |
| 2120 client_data_(client_data) {} | |
| 2121 | |
| 2122 | |
| 2123 bool MessageImpl::IsEvent() const { | |
| 2124 return is_event_; | |
| 2125 } | |
| 2126 | |
| 2127 | |
| 2128 bool MessageImpl::IsResponse() const { | |
| 2129 return !is_event_; | |
| 2130 } | |
| 2131 | |
| 2132 | |
| 2133 DebugEvent MessageImpl::GetEvent() const { | |
| 2134 return event_; | |
| 2135 } | |
| 2136 | |
| 2137 | |
| 2138 bool MessageImpl::WillStartRunning() const { | |
| 2139 return running_; | |
| 2140 } | |
| 2141 | |
| 2142 | |
| 2143 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const { | |
| 2144 return v8::Utils::ToLocal(exec_state_); | |
| 2145 } | |
| 2146 | |
| 2147 | |
| 2148 v8::Handle<v8::Object> MessageImpl::GetEventData() const { | |
| 2149 return v8::Utils::ToLocal(event_data_); | |
| 2150 } | |
| 2151 | |
| 2152 | |
| 2153 v8::Handle<v8::String> MessageImpl::GetJSON() const { | |
| 2154 v8::HandleScope scope; | |
| 2155 | |
| 2156 if (IsEvent()) { | |
| 2157 // Call toJSONProtocol on the debug event object. | |
| 2158 Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol"); | |
| 2159 if (!fun->IsJSFunction()) { | |
| 2160 return v8::Handle<v8::String>(); | |
| 2161 } | |
| 2162 bool caught_exception; | |
| 2163 Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun), | |
| 2164 event_data_, | |
| 2165 0, NULL, &caught_exception); | |
| 2166 if (caught_exception || !json->IsString()) { | |
| 2167 return v8::Handle<v8::String>(); | |
| 2168 } | |
| 2169 return scope.Close(v8::Utils::ToLocal(Handle<String>::cast(json))); | |
| 2170 } else { | |
| 2171 return v8::Utils::ToLocal(response_json_); | |
| 2172 } | |
| 2173 } | |
| 2174 | |
| 2175 | |
| 2176 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { | |
| 2177 return v8::Handle<v8::Context>(); | |
| 2178 } | |
| 2179 | |
| 2180 | |
| 2181 v8::Debug::ClientData* MessageImpl::GetClientData() const { | |
| 2182 return client_data_; | |
| 2183 } | |
| 2184 | |
| 2185 | |
| 2186 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()), | 2101 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()), |
| 2187 client_data_(NULL) { | 2102 client_data_(NULL) { |
| 2188 } | 2103 } |
| 2189 | 2104 |
| 2190 | 2105 |
| 2191 CommandMessage::CommandMessage(const Vector<uint16_t>& text, | 2106 CommandMessage::CommandMessage(const Vector<uint16_t>& text, |
| 2192 v8::Debug::ClientData* data) | 2107 v8::Debug::ClientData* data) |
| 2193 : text_(text), | 2108 : text_(text), |
| 2194 client_data_(data) { | 2109 client_data_(data) { |
| 2195 } | 2110 } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2291 | 2206 |
| 2292 | 2207 |
| 2293 void LockingCommandMessageQueue::Clear() { | 2208 void LockingCommandMessageQueue::Clear() { |
| 2294 ScopedLock sl(lock_); | 2209 ScopedLock sl(lock_); |
| 2295 queue_.Clear(); | 2210 queue_.Clear(); |
| 2296 } | 2211 } |
| 2297 | 2212 |
| 2298 #endif // ENABLE_DEBUGGER_SUPPORT | 2213 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2299 | 2214 |
| 2300 } } // namespace v8::internal | 2215 } } // namespace v8::internal |
| OLD | NEW |