Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(426)

Side by Side Diff: src/debug.cc

Issue 42173: Added automatic debug break for processing debugger commands (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/debug.h ('k') | src/execution.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 681
682 // Notify debugger if a real break point is triggered or if performing single 682 // Notify debugger if a real break point is triggered or if performing single
683 // stepping with no more steps to perform. Otherwise do another step. 683 // stepping with no more steps to perform. Otherwise do another step.
684 if (!break_points_hit->IsUndefined() || 684 if (!break_points_hit->IsUndefined() ||
685 (thread_local_.last_step_action_ != StepNone && 685 (thread_local_.last_step_action_ != StepNone &&
686 thread_local_.step_count_ == 0)) { 686 thread_local_.step_count_ == 0)) {
687 // Clear all current stepping setup. 687 // Clear all current stepping setup.
688 ClearStepping(); 688 ClearStepping();
689 689
690 // Notify the debug event listeners. 690 // Notify the debug event listeners.
691 Debugger::OnDebugBreak(break_points_hit); 691 Debugger::OnDebugBreak(break_points_hit, false);
692 } else if (thread_local_.last_step_action_ != StepNone) { 692 } else if (thread_local_.last_step_action_ != StepNone) {
693 // Hold on to last step action as it is cleared by the call to 693 // Hold on to last step action as it is cleared by the call to
694 // ClearStepping. 694 // ClearStepping.
695 StepAction step_action = thread_local_.last_step_action_; 695 StepAction step_action = thread_local_.last_step_action_;
696 int step_count = thread_local_.step_count_; 696 int step_count = thread_local_.step_count_;
697 697
698 // Clear all current stepping setup. 698 // Clear all current stepping setup.
699 ClearStepping(); 699 ClearStepping();
700 700
701 // Set up for the remaining steps. 701 // Set up for the remaining steps.
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 if (!caught_exception) { 1501 if (!caught_exception) {
1502 event_data = MakeExceptionEvent(exec_state, exception, uncaught, 1502 event_data = MakeExceptionEvent(exec_state, exception, uncaught,
1503 &caught_exception); 1503 &caught_exception);
1504 } 1504 }
1505 // Bail out and don't call debugger if exception. 1505 // Bail out and don't call debugger if exception.
1506 if (caught_exception) { 1506 if (caught_exception) {
1507 return; 1507 return;
1508 } 1508 }
1509 1509
1510 // Process debug event 1510 // Process debug event
1511 ProcessDebugEvent(v8::Exception, event_data); 1511 ProcessDebugEvent(v8::Exception, event_data, false);
1512 // Return to continue execution from where the exception was thrown. 1512 // Return to continue execution from where the exception was thrown.
1513 } 1513 }
1514 1514
1515 1515
1516 void Debugger::OnDebugBreak(Handle<Object> break_points_hit) { 1516 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
1517 bool auto_continue) {
1517 HandleScope scope; 1518 HandleScope scope;
1518 1519
1519 // Debugger has already been entered by caller. 1520 // Debugger has already been entered by caller.
1520 ASSERT(Top::context() == *Debug::debug_context()); 1521 ASSERT(Top::context() == *Debug::debug_context());
1521 1522
1522 // Bail out if there is no listener for this event 1523 // Bail out if there is no listener for this event
1523 if (!Debugger::EventActive(v8::Break)) return; 1524 if (!Debugger::EventActive(v8::Break)) return;
1524 1525
1525 // Debugger must be entered in advance. 1526 // Debugger must be entered in advance.
1526 ASSERT(Top::context() == *Debug::debug_context()); 1527 ASSERT(Top::context() == *Debug::debug_context());
1527 1528
1528 // Create the event data object. 1529 // Create the event data object.
1529 bool caught_exception = false; 1530 bool caught_exception = false;
1530 Handle<Object> exec_state = MakeExecutionState(&caught_exception); 1531 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1531 Handle<Object> event_data; 1532 Handle<Object> event_data;
1532 if (!caught_exception) { 1533 if (!caught_exception) {
1533 event_data = MakeBreakEvent(exec_state, break_points_hit, 1534 event_data = MakeBreakEvent(exec_state, break_points_hit,
1534 &caught_exception); 1535 &caught_exception);
1535 } 1536 }
1536 // Bail out and don't call debugger if exception. 1537 // Bail out and don't call debugger if exception.
1537 if (caught_exception) { 1538 if (caught_exception) {
1538 return; 1539 return;
1539 } 1540 }
1540 1541
1541 // Process debug event 1542 // Process debug event
1542 ProcessDebugEvent(v8::Break, event_data); 1543 ProcessDebugEvent(v8::Break, event_data, auto_continue);
1543 } 1544 }
1544 1545
1545 1546
1546 void Debugger::OnBeforeCompile(Handle<Script> script) { 1547 void Debugger::OnBeforeCompile(Handle<Script> script) {
1547 HandleScope scope; 1548 HandleScope scope;
1548 1549
1549 // Bail out based on state or if there is no listener for this event 1550 // Bail out based on state or if there is no listener for this event
1550 if (Debug::InDebugger()) return; 1551 if (Debug::InDebugger()) return;
1551 if (compiling_natives()) return; 1552 if (compiling_natives()) return;
1552 if (!EventActive(v8::BeforeCompile)) return; 1553 if (!EventActive(v8::BeforeCompile)) return;
1553 1554
1554 // Enter the debugger. 1555 // Enter the debugger.
1555 EnterDebugger debugger; 1556 EnterDebugger debugger;
1556 if (debugger.FailedToEnter()) return; 1557 if (debugger.FailedToEnter()) return;
1557 1558
1558 // Create the event data object. 1559 // Create the event data object.
1559 bool caught_exception = false; 1560 bool caught_exception = false;
1560 Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception); 1561 Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
1561 // Bail out and don't call debugger if exception. 1562 // Bail out and don't call debugger if exception.
1562 if (caught_exception) { 1563 if (caught_exception) {
1563 return; 1564 return;
1564 } 1565 }
1565 1566
1566 // Process debug event 1567 // Process debug event
1567 ProcessDebugEvent(v8::BeforeCompile, event_data); 1568 ProcessDebugEvent(v8::BeforeCompile, event_data, false);
1568 } 1569 }
1569 1570
1570 1571
1571 // Handle debugger actions when a new script is compiled. 1572 // Handle debugger actions when a new script is compiled.
1572 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) { 1573 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
1573 HandleScope scope; 1574 HandleScope scope;
1574 1575
1575 // No compile events while compiling natives. 1576 // No compile events while compiling natives.
1576 if (compiling_natives()) return; 1577 if (compiling_natives()) return;
1577 1578
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 1619
1619 // Create the compile state object. 1620 // Create the compile state object.
1620 Handle<Object> event_data = MakeCompileEvent(script, 1621 Handle<Object> event_data = MakeCompileEvent(script,
1621 false, 1622 false,
1622 &caught_exception); 1623 &caught_exception);
1623 // Bail out and don't call debugger if exception. 1624 // Bail out and don't call debugger if exception.
1624 if (caught_exception) { 1625 if (caught_exception) {
1625 return; 1626 return;
1626 } 1627 }
1627 // Process debug event 1628 // Process debug event
1628 ProcessDebugEvent(v8::AfterCompile, event_data); 1629 ProcessDebugEvent(v8::AfterCompile, event_data, false);
1629 } 1630 }
1630 1631
1631 1632
1632 void Debugger::OnNewFunction(Handle<JSFunction> function) { 1633 void Debugger::OnNewFunction(Handle<JSFunction> function) {
1633 return; 1634 return;
1634 HandleScope scope; 1635 HandleScope scope;
1635 1636
1636 // Bail out based on state or if there is no listener for this event 1637 // Bail out based on state or if there is no listener for this event
1637 if (Debug::InDebugger()) return; 1638 if (Debug::InDebugger()) return;
1638 if (compiling_natives()) return; 1639 if (compiling_natives()) return;
1639 if (!Debugger::EventActive(v8::NewFunction)) return; 1640 if (!Debugger::EventActive(v8::NewFunction)) return;
1640 1641
1641 // Enter the debugger. 1642 // Enter the debugger.
1642 EnterDebugger debugger; 1643 EnterDebugger debugger;
1643 if (debugger.FailedToEnter()) return; 1644 if (debugger.FailedToEnter()) return;
1644 1645
1645 // Create the event object. 1646 // Create the event object.
1646 bool caught_exception = false; 1647 bool caught_exception = false;
1647 Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception); 1648 Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception);
1648 // Bail out and don't call debugger if exception. 1649 // Bail out and don't call debugger if exception.
1649 if (caught_exception) { 1650 if (caught_exception) {
1650 return; 1651 return;
1651 } 1652 }
1652 // Process debug event. 1653 // Process debug event.
1653 ProcessDebugEvent(v8::NewFunction, event_data); 1654 ProcessDebugEvent(v8::NewFunction, event_data, false);
1654 } 1655 }
1655 1656
1656 1657
1657 void Debugger::ProcessDebugEvent(v8::DebugEvent event, 1658 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
1658 Handle<Object> event_data) { 1659 Handle<Object> event_data,
1660 bool auto_continue) {
1659 HandleScope scope; 1661 HandleScope scope;
1660 1662
1661 // Create the execution state. 1663 // Create the execution state.
1662 bool caught_exception = false; 1664 bool caught_exception = false;
1663 Handle<Object> exec_state = MakeExecutionState(&caught_exception); 1665 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1664 if (caught_exception) { 1666 if (caught_exception) {
1665 return; 1667 return;
1666 } 1668 }
1667 // First notify the builtin debugger. 1669 // First notify the builtin debugger.
1668 if (message_thread_ != NULL) { 1670 if (message_thread_ != NULL) {
1669 message_thread_->DebugEvent(event, exec_state, event_data); 1671 message_thread_->DebugEvent(event, exec_state, event_data, auto_continue);
1670 } 1672 }
1671 // Notify registered debug event listener. This can be either a C or a 1673 // Notify registered debug event listener. This can be either a C or a
1672 // JavaScript function. 1674 // JavaScript function.
1673 if (!event_listener_.is_null()) { 1675 if (!event_listener_.is_null()) {
1674 if (event_listener_->IsProxy()) { 1676 if (event_listener_->IsProxy()) {
1675 // C debug event listener. 1677 // C debug event listener.
1676 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); 1678 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
1677 v8::DebugEventCallback callback = 1679 v8::DebugEventCallback callback =
1678 FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy()); 1680 FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
1679 callback(event, 1681 callback(event,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1766 1768
1767 void Debugger::ProcessCommand(Vector<const uint16_t> command) { 1769 void Debugger::ProcessCommand(Vector<const uint16_t> command) {
1768 if (message_thread_ != NULL) { 1770 if (message_thread_ != NULL) {
1769 message_thread_->ProcessCommand( 1771 message_thread_->ProcessCommand(
1770 Vector<uint16_t>(const_cast<uint16_t *>(command.start()), 1772 Vector<uint16_t>(const_cast<uint16_t *>(command.start()),
1771 command.length())); 1773 command.length()));
1772 } 1774 }
1773 } 1775 }
1774 1776
1775 1777
1778 bool Debugger::HasCommands() {
1779 if (message_thread_ != NULL) {
1780 return message_thread_->HasCommands();
1781 } else {
1782 return false;
1783 }
1784 }
1785
1786
1776 void Debugger::ProcessHostDispatch(void* dispatch) { 1787 void Debugger::ProcessHostDispatch(void* dispatch) {
1777 if (message_thread_ != NULL) { 1788 if (message_thread_ != NULL) {
1778 message_thread_->ProcessHostDispatch(dispatch); 1789 message_thread_->ProcessHostDispatch(dispatch);
1779 } 1790 }
1780 } 1791 }
1781 1792
1782 1793
1783 void Debugger::UpdateActiveDebugger() { 1794 void Debugger::UpdateActiveDebugger() {
1784 set_debugger_active((message_thread_ != NULL && 1795 set_debugger_active((message_thread_ != NULL &&
1785 message_handler_ != NULL) || 1796 message_handler_ != NULL) ||
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1897 Debugger::SendMessage(message); 1908 Debugger::SendMessage(message);
1898 } 1909 }
1899 } 1910 }
1900 } 1911 }
1901 1912
1902 1913
1903 // This method is called by the V8 thread whenever a debug event occurs in 1914 // This method is called by the V8 thread whenever a debug event occurs in
1904 // the VM. 1915 // the VM.
1905 void DebugMessageThread::DebugEvent(v8::DebugEvent event, 1916 void DebugMessageThread::DebugEvent(v8::DebugEvent event,
1906 Handle<Object> exec_state, 1917 Handle<Object> exec_state,
1907 Handle<Object> event_data) { 1918 Handle<Object> event_data,
1919 bool auto_continue) {
1908 HandleScope scope; 1920 HandleScope scope;
1909 1921
1910 if (!Debug::Load()) return; 1922 if (!Debug::Load()) return;
1911 1923
1912 // Process the individual events. 1924 // Process the individual events.
1913 bool interactive = false; 1925 bool interactive = false;
1914 switch (event) { 1926 switch (event) {
1915 case v8::Break: 1927 case v8::Break:
1916 interactive = true; // Break event is always interactive 1928 interactive = true; // Break event is always interactive
1917 break; 1929 break;
(...skipping 22 matching lines...) Expand all
1940 v8::Function::Cast(*api_exec_state->Get(fun_name)); 1952 v8::Function::Cast(*api_exec_state->Get(fun_name));
1941 v8::TryCatch try_catch; 1953 v8::TryCatch try_catch;
1942 v8::Local<v8::Object> cmd_processor = 1954 v8::Local<v8::Object> cmd_processor =
1943 v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL)); 1955 v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL));
1944 if (try_catch.HasCaught()) { 1956 if (try_catch.HasCaught()) {
1945 PrintLn(try_catch.Exception()); 1957 PrintLn(try_catch.Exception());
1946 return; 1958 return;
1947 } 1959 }
1948 1960
1949 // Notify the debugger that a debug event has occurred. 1961 // Notify the debugger that a debug event has occurred.
1950 bool success = SetEventJSONFromEvent(event_data); 1962 if (!auto_continue) {
1951 if (!success) { 1963 bool success = SetEventJSONFromEvent(event_data);
1952 // If failed to notify debugger just continue running. 1964 if (!success) {
1953 return; 1965 // If failed to notify debugger just continue running.
1966 return;
1967 }
1954 } 1968 }
1955 1969
1956 // Wait for requests from the debugger. 1970 // Process requests from the debugger.
1957 host_running_ = false; 1971 host_running_ = false;
1958 while (true) { 1972 while (true) {
1973 // Wait for new command in the queue.
1959 command_received_->Wait(); 1974 command_received_->Wait();
1975
1976 // The debug command interrupt flag might have been set when the command was
1977 // added.
1978 StackGuard::Continue(DEBUGCOMMAND);
1979
1980 // Get the command from the queue.
1981 Vector<uint16_t> command = command_queue_.Get();
1960 Logger::DebugTag("Got request from command queue, in interactive loop."); 1982 Logger::DebugTag("Got request from command queue, in interactive loop.");
1961 Vector<uint16_t> command = command_queue_.Get();
1962 ASSERT(!host_running_); 1983 ASSERT(!host_running_);
1963 if (!Debugger::debugger_active()) { 1984 if (!Debugger::debugger_active()) {
1964 host_running_ = true; 1985 host_running_ = true;
1965 return; 1986 return;
1966 } 1987 }
1967 1988
1968 // Check if the command is a host dispatch. 1989 // Check if the command is a host dispatch.
1969 if (command[0] == 0) { 1990 if (command[0] == 0) {
1970 if (Debugger::host_dispatch_handler_) { 1991 if (Debugger::host_dispatch_handler_) {
1971 int32_t dispatch = (command[1] << 16) | command[2]; 1992 int32_t dispatch = (command[1] << 16) | command[2];
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2024 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val), 2045 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
2025 response->Length()); 2046 response->Length());
2026 2047
2027 // Set host_running_ correctly for nested debugger evaluations. 2048 // Set host_running_ correctly for nested debugger evaluations.
2028 host_running_ = running; 2049 host_running_ = running;
2029 2050
2030 // Return the result. 2051 // Return the result.
2031 SendMessage(str); 2052 SendMessage(str);
2032 2053
2033 // Return from debug event processing is VM should be running. 2054 // Return from debug event processing is VM should be running.
2034 if (running) { 2055 if (running || (auto_continue && !HasCommands())) {
2035 return; 2056 return;
2036 } 2057 }
2037 } 2058 }
2038 } 2059 }
2039 2060
2040 2061
2041 // Puts a command coming from the public API on the queue. Creates 2062 // Puts a command coming from the public API on the queue. Creates
2042 // a copy of the command string managed by the debugger. Up to this 2063 // a copy of the command string managed by the debugger. Up to this
2043 // point, the command data was managed by the API client. Called 2064 // point, the command data was managed by the API client. Called
2044 // by the API client thread. This is where the API client hands off 2065 // by the API client thread. This is where the API client hands off
2045 // processing of the command to the DebugMessageThread thread. 2066 // processing of the command to the DebugMessageThread thread.
2046 // The new copy of the command is destroyed in HandleCommand(). 2067 // The new copy of the command is destroyed in HandleCommand().
2047 void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) { 2068 void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) {
2048 Vector<uint16_t> command_copy = command.Clone(); 2069 Vector<uint16_t> command_copy = command.Clone();
2049 Logger::DebugTag("Put command on command_queue."); 2070 Logger::DebugTag("Put command on command_queue.");
2050 command_queue_.Put(command_copy); 2071 command_queue_.Put(command_copy);
2051 command_received_->Signal(); 2072 command_received_->Signal();
2073
2074 if (!Debug::InDebugger()) {
2075 StackGuard::DebugCommand();
2076 }
2052 } 2077 }
2053 2078
2054 2079
2055 // Puts a host dispatch comming from the public API on the queue. 2080 // Puts a host dispatch comming from the public API on the queue.
2056 void DebugMessageThread::ProcessHostDispatch(void* dispatch) { 2081 void DebugMessageThread::ProcessHostDispatch(void* dispatch) {
2057 uint16_t hack[3]; 2082 uint16_t hack[3];
2058 hack[0] = 0; 2083 hack[0] = 0;
2059 hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16; 2084 hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16;
2060 hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF; 2085 hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF;
2061 Logger::DebugTag("Put dispatch on command_queue."); 2086 Logger::DebugTag("Put dispatch on command_queue.");
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 } 2168 }
2144 2169
2145 2170
2146 void LockingMessageQueue::Clear() { 2171 void LockingMessageQueue::Clear() {
2147 ScopedLock sl(lock_); 2172 ScopedLock sl(lock_);
2148 queue_.Clear(); 2173 queue_.Clear();
2149 } 2174 }
2150 2175
2151 2176
2152 } } // namespace v8::internal 2177 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/execution.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698