| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 } | 846 } |
| 847 | 847 |
| 848 | 848 |
| 849 // Debug event handler which re-issues a debug break until a limit has been | 849 // Debug event handler which re-issues a debug break until a limit has been |
| 850 // reached. | 850 // reached. |
| 851 int max_break_point_hit_count = 0; | 851 int max_break_point_hit_count = 0; |
| 852 bool terminate_after_max_break_point_hit = false; | 852 bool terminate_after_max_break_point_hit = false; |
| 853 static void DebugEventBreakMax( | 853 static void DebugEventBreakMax( |
| 854 const v8::Debug::EventDetails& event_details) { | 854 const v8::Debug::EventDetails& event_details) { |
| 855 v8::DebugEvent event = event_details.GetEvent(); | 855 v8::DebugEvent event = event_details.GetEvent(); |
| 856 v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); | |
| 857 v8::Isolate* v8_isolate = CcTest::isolate(); | 856 v8::Isolate* v8_isolate = CcTest::isolate(); |
| 858 v8::internal::Isolate* isolate = CcTest::i_isolate(); | 857 v8::internal::Isolate* isolate = CcTest::i_isolate(); |
| 859 v8::internal::Debug* debug = isolate->debug(); | 858 v8::internal::Debug* debug = isolate->debug(); |
| 860 // When hitting a debug event listener there must be a break set. | 859 // When hitting a debug event listener there must be a break set. |
| 861 CHECK_NE(debug->break_id(), 0); | 860 CHECK_NE(debug->break_id(), 0); |
| 862 | 861 |
| 863 if (event == v8::Break) { | 862 if (event == v8::Break) { |
| 864 if (break_point_hit_count < max_break_point_hit_count) { | 863 if (break_point_hit_count < max_break_point_hit_count) { |
| 865 // Count the number of breaks. | 864 // Count the number of breaks. |
| 866 break_point_hit_count++; | 865 break_point_hit_count++; |
| 867 | 866 |
| 868 // Collect the JavsScript stack height if the function frame_count is | |
| 869 // compiled. | |
| 870 if (!frame_count.IsEmpty()) { | |
| 871 static const int kArgc = 1; | |
| 872 v8::Handle<v8::Value> argv[kArgc] = { exec_state }; | |
| 873 // Using exec_state as receiver is just to have a receiver. | |
| 874 v8::Handle<v8::Value> result = | |
| 875 frame_count->Call(exec_state, kArgc, argv); | |
| 876 last_js_stack_height = result->Int32Value(); | |
| 877 } | |
| 878 | |
| 879 // Set the break flag again to come back here as soon as possible. | 867 // Set the break flag again to come back here as soon as possible. |
| 880 v8::Debug::DebugBreak(v8_isolate); | 868 v8::Debug::DebugBreak(v8_isolate); |
| 881 | 869 |
| 882 } else if (terminate_after_max_break_point_hit) { | 870 } else if (terminate_after_max_break_point_hit) { |
| 883 // Terminate execution after the last break if requested. | 871 // Terminate execution after the last break if requested. |
| 884 v8::V8::TerminateExecution(v8_isolate); | 872 v8::V8::TerminateExecution(v8_isolate); |
| 885 } | 873 } |
| 886 | 874 |
| 887 // Perform a full deoptimization when the specified number of | 875 // Perform a full deoptimization when the specified number of |
| 888 // breaks have been hit. | 876 // breaks have been hit. |
| (...skipping 6191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7080 "}" | 7068 "}" |
| 7081 "loop(0);"; | 7069 "loop(0);"; |
| 7082 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), src))->Run(); | 7070 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), src))->Run(); |
| 7083 } | 7071 } |
| 7084 | 7072 |
| 7085 | 7073 |
| 7086 // Test that setting the terminate execution flag during debug break processing. | 7074 // Test that setting the terminate execution flag during debug break processing. |
| 7087 static void TestDebugBreakInLoop(const char* loop_head, | 7075 static void TestDebugBreakInLoop(const char* loop_head, |
| 7088 const char** loop_bodies, | 7076 const char** loop_bodies, |
| 7089 const char* loop_tail) { | 7077 const char* loop_tail) { |
| 7090 // Receive 100 breaks for each test and then terminate JavaScript execution. | 7078 // Receive 10 breaks for each test and then terminate JavaScript execution. |
| 7091 static const int kBreaksPerTest = 100; | 7079 static const int kBreaksPerTest = 10; |
| 7092 | 7080 |
| 7093 for (int i = 0; loop_bodies[i] != NULL; i++) { | 7081 for (int i = 0; loop_bodies[i] != NULL; i++) { |
| 7094 // Perform a lazy deoptimization after various numbers of breaks | 7082 // Perform a lazy deoptimization after various numbers of breaks |
| 7095 // have been hit. | 7083 // have been hit. |
| 7096 for (int j = 0; j < 7; j++) { | 7084 |
| 7085 EmbeddedVector<char, 1024> buffer; |
| 7086 SNPrintF(buffer, "function f() {%s%s%s}", loop_head, loop_bodies[i], |
| 7087 loop_tail); |
| 7088 |
| 7089 i::PrintF("%s\n", buffer.start()); |
| 7090 |
| 7091 for (int j = 0; j < 3; j++) { |
| 7097 break_point_hit_count_deoptimize = j; | 7092 break_point_hit_count_deoptimize = j; |
| 7098 if (j == 6) { | 7093 if (j == 2) { |
| 7099 break_point_hit_count_deoptimize = kBreaksPerTest; | 7094 break_point_hit_count_deoptimize = kBreaksPerTest; |
| 7100 } | 7095 } |
| 7101 | 7096 |
| 7102 break_point_hit_count = 0; | 7097 break_point_hit_count = 0; |
| 7103 max_break_point_hit_count = kBreaksPerTest; | 7098 max_break_point_hit_count = kBreaksPerTest; |
| 7104 terminate_after_max_break_point_hit = true; | 7099 terminate_after_max_break_point_hit = true; |
| 7105 | 7100 |
| 7106 EmbeddedVector<char, 1024> buffer; | |
| 7107 SNPrintF(buffer, | |
| 7108 "function f() {%s%s%s}", | |
| 7109 loop_head, loop_bodies[i], loop_tail); | |
| 7110 | |
| 7111 // Function with infinite loop. | 7101 // Function with infinite loop. |
| 7112 CompileRun(buffer.start()); | 7102 CompileRun(buffer.start()); |
| 7113 | 7103 |
| 7114 // Set the debug break to enter the debugger as soon as possible. | 7104 // Set the debug break to enter the debugger as soon as possible. |
| 7115 v8::Debug::DebugBreak(CcTest::isolate()); | 7105 v8::Debug::DebugBreak(CcTest::isolate()); |
| 7116 | 7106 |
| 7117 // Call function with infinite loop. | 7107 // Call function with infinite loop. |
| 7118 CompileRun("f();"); | 7108 CompileRun("f();"); |
| 7119 CHECK_EQ(kBreaksPerTest, break_point_hit_count); | 7109 CHECK_EQ(kBreaksPerTest, break_point_hit_count); |
| 7120 | 7110 |
| 7121 CHECK(!v8::V8::IsExecutionTerminating()); | 7111 CHECK(!v8::V8::IsExecutionTerminating()); |
| 7122 } | 7112 } |
| 7123 } | 7113 } |
| 7124 } | 7114 } |
| 7125 | 7115 |
| 7126 | 7116 |
| 7127 TEST(DebugBreakLoop) { | 7117 static const char* loop_bodies_1[] = {"", |
| 7118 "g()", |
| 7119 "if (a == 0) { g() }", |
| 7120 "if (a == 1) { g() }", |
| 7121 "if (a == 0) { g() } else { h() }", |
| 7122 "if (a == 0) { continue }", |
| 7123 NULL}; |
| 7124 |
| 7125 |
| 7126 static const char* loop_bodies_2[] = { |
| 7127 "if (a == 1) { continue }", |
| 7128 "switch (a) { case 1: g(); }", |
| 7129 "switch (a) { case 1: continue; }", |
| 7130 "switch (a) { case 1: g(); break; default: h() }", |
| 7131 "switch (a) { case 1: continue; break; default: h() }", |
| 7132 NULL}; |
| 7133 |
| 7134 |
| 7135 void DebugBreakLoop(const char* loop_header, const char** loop_bodies, |
| 7136 const char* loop_footer) { |
| 7128 DebugLocalContext env; | 7137 DebugLocalContext env; |
| 7129 v8::HandleScope scope(env->GetIsolate()); | 7138 v8::HandleScope scope(env->GetIsolate()); |
| 7130 | 7139 |
| 7131 // Register a debug event listener which sets the break flag and counts. | 7140 // Register a debug event listener which sets the break flag and counts. |
| 7132 v8::Debug::SetDebugEventListener(DebugEventBreakMax); | 7141 v8::Debug::SetDebugEventListener(DebugEventBreakMax); |
| 7133 | 7142 |
| 7134 // Create a function for getting the frame count when hitting the break. | 7143 CompileRun( |
| 7135 frame_count = CompileFunction(&env, frame_count_source, "frame_count"); | 7144 "var a = 1;\n" |
| 7145 "function g() { }\n" |
| 7146 "function h() { }"); |
| 7136 | 7147 |
| 7137 CompileRun("var a = 1;"); | 7148 TestDebugBreakInLoop(loop_header, loop_bodies, loop_footer); |
| 7138 CompileRun("function g() { }"); | |
| 7139 CompileRun("function h() { }"); | |
| 7140 | |
| 7141 const char* loop_bodies[] = { | |
| 7142 "", | |
| 7143 "g()", | |
| 7144 "if (a == 0) { g() }", | |
| 7145 "if (a == 1) { g() }", | |
| 7146 "if (a == 0) { g() } else { h() }", | |
| 7147 "if (a == 0) { continue }", | |
| 7148 "if (a == 1) { continue }", | |
| 7149 "switch (a) { case 1: g(); }", | |
| 7150 "switch (a) { case 1: continue; }", | |
| 7151 "switch (a) { case 1: g(); break; default: h() }", | |
| 7152 "switch (a) { case 1: continue; break; default: h() }", | |
| 7153 NULL | |
| 7154 }; | |
| 7155 | |
| 7156 TestDebugBreakInLoop("while (true) {", loop_bodies, "}"); | |
| 7157 TestDebugBreakInLoop("while (a == 1) {", loop_bodies, "}"); | |
| 7158 | |
| 7159 TestDebugBreakInLoop("do {", loop_bodies, "} while (true)"); | |
| 7160 TestDebugBreakInLoop("do {", loop_bodies, "} while (a == 1)"); | |
| 7161 | |
| 7162 TestDebugBreakInLoop("for (;;) {", loop_bodies, "}"); | |
| 7163 TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}"); | |
| 7164 | 7149 |
| 7165 // Get rid of the debug event listener. | 7150 // Get rid of the debug event listener. |
| 7166 v8::Debug::SetDebugEventListener(NULL); | 7151 v8::Debug::SetDebugEventListener(NULL); |
| 7167 CheckDebuggerUnloaded(); | 7152 CheckDebuggerUnloaded(); |
| 7168 } | 7153 } |
| 7169 | 7154 |
| 7170 | 7155 |
| 7156 TEST(DebugBreakInWhileTrue1) { |
| 7157 DebugBreakLoop("while (true) {", loop_bodies_1, "}"); |
| 7158 } |
| 7159 |
| 7160 |
| 7161 TEST(DebugBreakInWhileTrue2) { |
| 7162 DebugBreakLoop("while (true) {", loop_bodies_2, "}"); |
| 7163 } |
| 7164 |
| 7165 |
| 7166 TEST(DebugBreakInWhileCondition1) { |
| 7167 DebugBreakLoop("while (a == 1) {", loop_bodies_1, "}"); |
| 7168 } |
| 7169 |
| 7170 |
| 7171 TEST(DebugBreakInWhileCondition2) { |
| 7172 DebugBreakLoop("while (a == 1) {", loop_bodies_2, "}"); |
| 7173 } |
| 7174 |
| 7175 |
| 7176 TEST(DebugBreakInDoWhileTrue1) { |
| 7177 DebugBreakLoop("do {", loop_bodies_1, "} while (true)"); |
| 7178 } |
| 7179 |
| 7180 |
| 7181 TEST(DebugBreakInDoWhileTrue2) { |
| 7182 DebugBreakLoop("do {", loop_bodies_2, "} while (true)"); |
| 7183 } |
| 7184 |
| 7185 |
| 7186 TEST(DebugBreakInDoWhileCondition1) { |
| 7187 DebugBreakLoop("do {", loop_bodies_1, "} while (a == 1)"); |
| 7188 } |
| 7189 |
| 7190 |
| 7191 TEST(DebugBreakInDoWhileCondition2) { |
| 7192 DebugBreakLoop("do {", loop_bodies_2, "} while (a == 1)"); |
| 7193 } |
| 7194 |
| 7195 |
| 7196 TEST(DebugBreakInFor1) { DebugBreakLoop("for (;;) {", loop_bodies_1, "}"); } |
| 7197 |
| 7198 |
| 7199 TEST(DebugBreakInFor2) { DebugBreakLoop("for (;;) {", loop_bodies_2, "}"); } |
| 7200 |
| 7201 |
| 7202 TEST(DebugBreakInForCondition1) { |
| 7203 DebugBreakLoop("for (;a == 1;) {", loop_bodies_1, "}"); |
| 7204 } |
| 7205 |
| 7206 |
| 7207 TEST(DebugBreakInForCondition2) { |
| 7208 DebugBreakLoop("for (;a == 1;) {", loop_bodies_2, "}"); |
| 7209 } |
| 7210 |
| 7211 |
| 7171 v8::Local<v8::Script> inline_script; | 7212 v8::Local<v8::Script> inline_script; |
| 7172 | 7213 |
| 7173 static void DebugBreakInlineListener( | 7214 static void DebugBreakInlineListener( |
| 7174 const v8::Debug::EventDetails& event_details) { | 7215 const v8::Debug::EventDetails& event_details) { |
| 7175 v8::DebugEvent event = event_details.GetEvent(); | 7216 v8::DebugEvent event = event_details.GetEvent(); |
| 7176 if (event != v8::Break) return; | 7217 if (event != v8::Break) return; |
| 7177 | 7218 |
| 7178 int expected_frame_count = 4; | 7219 int expected_frame_count = 4; |
| 7179 int expected_line_number[] = {1, 4, 7, 12}; | 7220 int expected_line_number[] = {1, 4, 7, 12}; |
| 7180 | 7221 |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7572 "let y = 2; \n" | 7613 "let y = 2; \n" |
| 7573 "debugger; \n" | 7614 "debugger; \n" |
| 7574 "x * y", | 7615 "x * y", |
| 7575 30); | 7616 30); |
| 7576 ExpectInt32( | 7617 ExpectInt32( |
| 7577 "x = 1; y = 2; \n" | 7618 "x = 1; y = 2; \n" |
| 7578 "debugger;" | 7619 "debugger;" |
| 7579 "x * y", | 7620 "x * y", |
| 7580 30); | 7621 30); |
| 7581 } | 7622 } |
| OLD | NEW |