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 |