Fix various bugs relating to do-while loops and if-no-else (bug 659782, r=adrake).
authorDavid Anderson <danderson@mozilla.com>
Wed, 25 May 2011 23:18:11 -0700
changeset 104814 c0b5d680c1367200e6b905b39dea92302ff93f2c
parent 104813 f5e6fe3c5e8cb1ebb76539c3849b5b42a2c31f26
child 104815 3e098050470c6038b35ff6359b6bd3b8d3b5fe8e
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersadrake
bugs659782
milestone6.0a1
Fix various bugs relating to do-while loops and if-no-else (bug 659782, r=adrake).
js/src/ion/IonBuilder.cpp
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -536,16 +536,17 @@ IonBuilder::processIfEnd(CFGState &state
         if (!current->end(ins))
             return ControlStatus_Error;
 
         if (!current->addPredecessor(state.branch.ifFalse))
             return ControlStatus_Error;
     }
 
     current = state.branch.ifFalse;
+    pc = current->pc();
     return ControlStatus_Joined;
 }
 
 IonBuilder::ControlStatus
 IonBuilder::processIfElseTrueEnd(CFGState &state)
 {
     // We've reached the end of the true branch of an if-else. Don't
     // create an edge yet, just transition to parsing the false branch.
@@ -621,21 +622,21 @@ IonBuilder::finalizeLoop(CFGState &state
     MBasicBlock *successor = state.loop.successor
                              ? state.loop.successor
                              : breaks;
 
     // Place phis in the loop header, propagating their assignment to the
     // successor block. If there is no |current|, then the successor is still
     // reachable via the original test branch, and thus its state is coherent.
     if (current) {
-        JS_ASSERT_IF(last, state.loop.successor);
+        JS_ASSERT_IF(last, successor);
 
         MControlInstruction *ins;
         if (last)
-            ins = MTest::New(last, state.loop.entry, state.loop.successor);
+            ins = MTest::New(last, state.loop.entry, successor);
         else
             ins = MGoto::New(state.loop.entry);
         if (!current->end(ins))
             return false;
 
         if (!state.loop.entry->setBackedge(current, successor))
             return false;
     }
@@ -654,17 +655,26 @@ IonBuilder::finalizeLoop(CFGState &state
     return true;
 }
 
 IonBuilder::ControlStatus
 IonBuilder::processDoWhileEnd(CFGState &state)
 {
     if (!processDeferredContinues(state))
         return ControlStatus_Error;
-    if (!finalizeLoop(state, NULL))
+
+    MInstruction *last = NULL;
+    if (current) {
+        last = current->pop();
+        state.loop.successor = newBlock(current, GetNextPc(pc));
+        if (!state.loop.successor)
+            return ControlStatus_Error;
+    }
+
+    if (!finalizeLoop(state, last))
         return ControlStatus_Error;
 
     current = state.loop.successor;
     if (!current)
         return ControlStatus_Ended;
 
     pc = current->pc();
     return ControlStatus_Joined;
@@ -940,16 +950,17 @@ IonBuilder::doWhileLoop(JSOp op, jssrcno
         return ControlStatus_Error;
 
     current = header;
     jsbytecode *bodyStart = GetNextPc(GetNextPc(pc));
     jsbytecode *exitpc = GetNextPc(ifne);
     if (!pushLoop(CFGState::DO_WHILE_LOOP, ifne, header, bodyStart, ifne, exitpc))
         return ControlStatus_Error;
 
+    pc = GetNextPc(GetNextPc(pc));
     return ControlStatus_Jumped;
 }
 
 IonBuilder::ControlStatus
 IonBuilder::whileLoop(JSOp op, jssrcnote *sn)
 {
     // while (cond) { } loops have the following structure:
     //    GOTO cond   ; SRC_WHILE (offset to IFNE)