Bug 1333946 - Make IonBuilder::processIterators transitive. r=jandem a=gchang
authorShu-yu Guo <shu@rfrn.org>
Thu, 02 Feb 2017 17:22:00 +0100
changeset 378178 022d0370a2beb5cb35981b781c52a5f7f2c13b00
parent 378177 2cdc3dfa46c28a452b2b26199df0e6a2c098544a
child 378179 a00b321f8c49214f37243f3abdd987b527038fba
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, gchang
bugs1333946
milestone53.0a2
Bug 1333946 - Make IonBuilder::processIterators transitive. r=jandem a=gchang
js/src/jit-test/tests/ion/bug1333946.js
js/src/jit/IonBuilder.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1333946.js
@@ -0,0 +1,6 @@
+// |jit-test| exitstatus: 6;
+
+for (var x of [0]) {
+    timeout(0.001);
+    for (;;) {}
+}
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -858,45 +858,42 @@ IonBuilder::build()
 
     MOZ_ASSERT(loopDepth_ == 0);
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::processIterators()
 {
-    // Find phis that must directly hold an iterator live.
-    Vector<MPhi*, 0, SystemAllocPolicy> worklist;
+    // Find and mark phis that must transitively hold an iterator live.
+
+    Vector<MDefinition*, 8, SystemAllocPolicy> worklist;
+
     for (size_t i = 0; i < iterators_.length(); i++) {
-        MDefinition* def = iterators_[i];
+        if (!worklist.append(iterators_[i]))
+            return abort(AbortReason::Alloc);
+        iterators_[i]->setInWorklist();
+    }
+
+    while (!worklist.empty()) {
+        MDefinition* def = worklist.popCopy();
+        def->setNotInWorklist();
+
         if (def->isPhi()) {
-            if (!worklist.append(def->toPhi()))
-                return abort(AbortReason::Alloc);
-        } else {
-            for (MUseDefIterator iter(def); iter; iter++) {
-                if (iter.def()->isPhi()) {
-                    if (!worklist.append(iter.def()->toPhi()))
-                        return abort(AbortReason::Alloc);
-                }
-            }
-        }
-    }
-
-    // Propagate the iterator and live status of phis to all other connected
-    // phis.
-    while (!worklist.empty()) {
-        MPhi* phi = worklist.popCopy();
-        phi->setIterator();
-        phi->setImplicitlyUsedUnchecked();
-
-        for (MUseDefIterator iter(phi); iter; iter++) {
-            if (iter.def()->isPhi()) {
-                MPhi* other = iter.def()->toPhi();
-                if (!other->isIterator() && !worklist.append(other))
+            MPhi* phi = def->toPhi();
+            phi->setIterator();
+            phi->setImplicitlyUsedUnchecked();
+        }
+
+        for (MUseDefIterator iter(def); iter; iter++) {
+            MDefinition* use = iter.def();
+            if (!use->isInWorklist() && (!use->isPhi() || !use->toPhi()->isIterator())) {
+                if (!worklist.append(use))
                     return abort(AbortReason::Alloc);
+                use->setInWorklist();
             }
         }
     }
 
     return Ok();
 }
 
 AbortReasonOr<Ok>