Add more tests of breaks in infinite loops
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Nov 2010 12:08:52 +0000 (12:08 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Nov 2010 12:08:52 +0000 (12:08 +0000)
Move stack check in do while loops to before the continue target to enable breaks even if continue was always used in the loop.
Review URL: http://codereview.chromium.org/5184007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5862 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/full-codegen.cc
test/cctest/test-debug.cc

index 8592472..19971a2 100644 (file)
@@ -882,12 +882,12 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
   Visit(stmt->body());
 
   // Check stack before looping.
+  __ bind(loop_statement.continue_target());
   __ StackLimitCheck(&stack_limit_hit);
   __ bind(&stack_check_success);
 
   // Record the position of the do while condition and make sure it is
   // possible to break on the condition.
-  __ bind(loop_statement.continue_target());
   SetExpressionPosition(stmt->cond(), stmt->condition_position());
   VisitForControl(stmt->cond(),
                   &body,
index 748e3e8..7791185 100644 (file)
@@ -6900,26 +6900,71 @@ TEST(DebugEventBreakData) {
 
 
 // Test that setting the terminate execution flag during debug break processing.
+static void TestDebugBreakInLoop(const char* loop_head,
+                                 const char** loop_bodies,
+                                 const char* loop_tail) {
+  // Receive 100 breaks for each test and then terminate JavaScript execution.
+  static int count = 0;
+
+  for (int i = 0; loop_bodies[i] != NULL; i++) {
+    count++;
+    max_break_point_hit_count = count * 100;
+    terminate_after_max_break_point_hit = true;
+
+    EmbeddedVector<char, 1024> buffer;
+    OS::SNPrintF(buffer,
+                 "function f() {%s%s%s}",
+                 loop_head, loop_bodies[i], loop_tail);
+
+    // Function with infinite loop.
+    CompileRun(buffer.start());
+
+    // Set the debug break to enter the debugger as soon as possible.
+    v8::Debug::DebugBreak();
+
+    // Call function with infinite loop.
+    CompileRun("f();");
+    CHECK_EQ(count * 100, break_point_hit_count);
+
+    CHECK(!v8::V8::IsExecutionTerminating());
+  }
+}
+
+
 TEST(DebugBreakLoop) {
   v8::HandleScope scope;
   DebugLocalContext env;
 
-  // Receive 100 breaks and terminate.
-  max_break_point_hit_count = 100;
-  terminate_after_max_break_point_hit = true;
-
   // Register a debug event listener which sets the break flag and counts.
   v8::Debug::SetDebugEventListener(DebugEventBreakMax);
 
-  // Function with infinite loop.
-  CompileRun("function f() { while (true) { } }");
+  CompileRun("var a = 1;");
+  CompileRun("function g() { }");
+  CompileRun("function h() { }");
+
+  const char* loop_bodies[] = {
+      "",
+      "g()",
+      "if (a == 0) { g() }",
+      "if (a == 1) { g() }",
+      "if (a == 0) { g() } else { h() }",
+      "if (a == 0) { continue }",
+      "if (a == 1) { continue }",
+      "switch (a) { case 1: g(); }",
+      "switch (a) { case 1: continue; }",
+      "switch (a) { case 1: g(); break; default: h() }",
+      "switch (a) { case 1: continue; break; default: h() }",
+      NULL
+  };
+
+  TestDebugBreakInLoop("while (true) {", loop_bodies, "}");
+  TestDebugBreakInLoop("while (a == 1) {", loop_bodies, "}");
 
-  // Set the debug break to enter the debugger as soon as possible.
-  v8::Debug::DebugBreak();
+  TestDebugBreakInLoop("do {", loop_bodies, "} while (true)");
+  TestDebugBreakInLoop("do {", loop_bodies, "} while (a == 1)");
 
-  // Call function with infinite loop.
-  CompileRun("f();");
-  CHECK_EQ(100, break_point_hit_count);
+  TestDebugBreakInLoop("for (;;) {", loop_bodies, "}");
+  TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}");
 
   // Get rid of the debug event listener.
   v8::Debug::SetDebugEventListener(NULL);