Bug 858749 - OdinMonkey: fix join after break when block is empty (r=sstangl)
authorLuke Wagner <luke@mozilla.com>
Wed, 17 Apr 2013 17:33:54 -0700
changeset 129219 d061ec6e84511e6fdd0fc467b577765a0a6f9afe
parent 129218 36ffb85842acb54d5e2544f6eb458b6aaa10981f
child 129220 5b25aba83eebfb933364249f0fcafdddd72f45a4
push id24562
push userryanvm@gmail.com
push dateFri, 19 Apr 2013 01:24:04 +0000
treeherdermozilla-central@f8d27fe5d7c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs858749
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 858749 - OdinMonkey: fix join after break when block is empty (r=sstangl)
js/src/ion/AsmJS.cpp
js/src/jit-test/tests/asm.js/testControlFlow.js
--- a/js/src/ion/AsmJS.cpp
+++ b/js/src/ion/AsmJS.cpp
@@ -2083,27 +2083,29 @@ class FunctionCompiler
                 curBlock_ = afterLoop;
             }
         }
         return bindUnlabeledBreaks(pn);
     }
 
     bool bindContinues(ParseNode *pn, const LabelVector *maybeLabels)
     {
+        bool createdJoinBlock = false;
         if (UnlabeledBlockMap::Ptr p = unlabeledContinues_.lookup(pn)) {
-            if (!bindBreaksOrContinues(&p->value))
+            if (!bindBreaksOrContinues(&p->value, &createdJoinBlock))
                 return false;
             unlabeledContinues_.remove(p);
         }
-        return bindLabeledBreaksOrContinues(maybeLabels, &labeledContinues_);
+        return bindLabeledBreaksOrContinues(maybeLabels, &labeledContinues_, &createdJoinBlock);
     }
 
     bool bindLabeledBreaks(const LabelVector *maybeLabels)
     {
-        return bindLabeledBreaksOrContinues(maybeLabels, &labeledBreaks_);
+        bool createdJoinBlock = false;
+        return bindLabeledBreaksOrContinues(maybeLabels, &labeledBreaks_, &createdJoinBlock);
     }
 
     bool addBreak(PropertyName *maybeLabel) {
         if (maybeLabel)
             return addBreakOrContinue(maybeLabel, &labeledBreaks_);
         return addBreakOrContinue(breakableStack_.back(), &unlabeledBreaks_);
     }
 
@@ -2195,48 +2197,50 @@ class FunctionCompiler
         return true;
     }
 
     bool newBlock(MBasicBlock *pred, MBasicBlock **block)
     {
         return newBlockWithDepth(pred, loopStack_.length(), block);
     }
 
-    bool bindBreaksOrContinues(BlockVector *preds)
+    bool bindBreaksOrContinues(BlockVector *preds, bool *createdJoinBlock)
     {
         for (unsigned i = 0; i < preds->length(); i++) {
             MBasicBlock *pred = (*preds)[i];
-            if (curBlock_ && curBlock_->begin() == curBlock_->end()) {
+            if (*createdJoinBlock) {
                 pred->end(MGoto::New(curBlock_));
                 curBlock_->addPredecessor(pred);
             } else {
                 MBasicBlock *next;
                 if (!newBlock(pred, &next))
                     return false;
                 pred->end(MGoto::New(next));
                 if (curBlock_) {
                     curBlock_->end(MGoto::New(next));
                     next->addPredecessor(curBlock_);
                 }
                 curBlock_ = next;
+                *createdJoinBlock = true;
             }
             JS_ASSERT(curBlock_->begin() == curBlock_->end());
         }
         preds->clear();
         return true;
     }
 
-    bool bindLabeledBreaksOrContinues(const LabelVector *maybeLabels, LabeledBlockMap *map)
+    bool bindLabeledBreaksOrContinues(const LabelVector *maybeLabels, LabeledBlockMap *map,
+                                      bool *createdJoinBlock)
     {
         if (!maybeLabels)
             return true;
         const LabelVector &labels = *maybeLabels;
         for (unsigned i = 0; i < labels.length(); i++) {
             if (LabeledBlockMap::Ptr p = map->lookup(labels[i])) {
-                if (!bindBreaksOrContinues(&p->value))
+                if (!bindBreaksOrContinues(&p->value, createdJoinBlock))
                     return false;
                 map->remove(p);
             }
         }
         return true;
     }
 
     template <class Key, class Map>
@@ -2253,18 +2257,19 @@ class FunctionCompiler
         if (!p->value.append(curBlock_))
             return false;
         curBlock_ = NULL;
         return true;
     }
 
     bool bindUnlabeledBreaks(ParseNode *pn)
     {
+        bool createdJoinBlock = false;
         if (UnlabeledBlockMap::Ptr p = unlabeledBreaks_.lookup(pn)) {
-            if (!bindBreaksOrContinues(&p->value))
+            if (!bindBreaksOrContinues(&p->value, &createdJoinBlock))
                 return false;
             unlabeledBreaks_.remove(p);
         }
         return true;
     }
 };
 
 /*****************************************************************************/
--- a/js/src/jit-test/tests/asm.js/testControlFlow.js
+++ b/js/src/jit-test/tests/asm.js/testControlFlow.js
@@ -94,16 +94,20 @@ assertEq(asmLink(asmCompile(USE_ASM + "f
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; while(1) { if (i) { break; } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;1;) { if (i) { break; } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; do { if (i) { break; } else { return i|0 } i = 1 } while (0); return i|0 } return f"))(3), 3);
 
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; while(1) { if (i) { return i|0 } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;;) { if (i) { return i|0 } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; do { if (i) { return i|0 } else { return i|0 } i = 1 } while (0); return i|0 } return f"))(3), 3);
 
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; while(j){ if(0) continue; j=i } return j|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; for(;j;){ if(0) continue; j=i } return j|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; do{ if(0) continue; j=i } while(j) return j|0 } return f"))(), 0);
+
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;;) { return i|0 } return 0 } return f"))(42), 42);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(n) { n=n|0; var i=0,s=0; for(;;i=(i+1)|0) { if (~~i==~~n) return s|0; s=(s+i)|0 } return 0 } return f"))(8), 28);
 
 var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; while((n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0) { sum = (sum+i)|0; i=(i+1)|0 } return sum|0 } return f"));
 assertEq(f(1,5), 10);
 assertEq(f(6,5), 15);
 
 var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; for(; (n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0; i=(i+1)|0) { sum = (sum+i)|0 } return sum|0 } return f"));