Bug 1331444 - Keep iterators alive in Ion in for-of loops for IteratorClose due to exceptions. (r=jandem)
authorShu-yu Guo <shu@rfrn.org>
Fri, 20 Jan 2017 12:53:41 -0800
changeset 377770 287d743f3b70f8a6d3e66264f2549f6cfc915eeb
parent 377731 24e88a2d883fff700725490665bce10aeb303551
child 377771 adbedc3ae1b40e413c133f963a9cebfb0c23e99c
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
bugs1331444
milestone53.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 1331444 - Keep iterators alive in Ion in for-of loops for IteratorClose due to exceptions. (r=jandem)
js/src/jit-test/tests/for-of/bug-1331444.js
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/for-of/bug-1331444.js
@@ -0,0 +1,7 @@
+// |jit-test| error: ReferenceError
+
+symbols = [Symbol];
+for (comparator of[, ])
+  for (a of symbols)
+    for (;;)
+      expect;
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -861,21 +861,26 @@ IonBuilder::build()
 }
 
 AbortReasonOr<Ok>
 IonBuilder::processIterators()
 {
     // Find phis that must directly hold an iterator live.
     Vector<MPhi*, 0, SystemAllocPolicy> worklist;
     for (size_t i = 0; i < iterators_.length(); i++) {
-        MInstruction* ins = iterators_[i];
-        for (MUseDefIterator iter(ins); iter; iter++) {
-            if (iter.def()->isPhi()) {
-                if (!worklist.append(iter.def()->toPhi()))
-                    return abort(AbortReason::Alloc);
+        MDefinition* def = iterators_[i];
+        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();
@@ -1994,17 +1999,22 @@ IonBuilder::inspectOpcode(JSOp op)
 
       case JSOP_FUNAPPLY:
         return jsop_funapply(GET_ARGC(pc));
 
       case JSOP_CALL:
       case JSOP_CALLITER:
       case JSOP_NEW:
       case JSOP_SUPERCALL:
-        return jsop_call(GET_ARGC(pc), (JSOp)*pc == JSOP_NEW || (JSOp)*pc == JSOP_SUPERCALL);
+        MOZ_TRY(jsop_call(GET_ARGC(pc), (JSOp)*pc == JSOP_NEW || (JSOp)*pc == JSOP_SUPERCALL));
+        if (op == JSOP_CALLITER) {
+            if (!outermostBuilder()->iterators_.append(current->peek(-1)))
+                return abort(AbortReason::Alloc);
+        }
+        return Ok();
 
       case JSOP_EVAL:
       case JSOP_STRICTEVAL:
         return jsop_eval(GET_ARGC(pc));
 
       case JSOP_INT8:
         pushConstant(Int32Value(GET_INT8(pc)));
         return Ok();
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -1031,17 +1031,17 @@ class IonBuilder
         jsbytecode* pc;
         MBasicBlock* header;
 
         LoopHeader(jsbytecode* pc, MBasicBlock* header)
           : pc(pc), header(header)
         {}
     };
 
-    Vector<MInstruction*, 2, JitAllocPolicy> iterators_;
+    Vector<MDefinition*, 2, JitAllocPolicy> iterators_;
     Vector<LoopHeader, 0, JitAllocPolicy> loopHeaders_;
     Vector<MBasicBlock*, 0, JitAllocPolicy> loopHeaderStack_;
 #ifdef DEBUG
     Vector<const CFGBlock*, 0, JitAllocPolicy> cfgLoopHeaderStack_;
 #endif
 
     BaselineInspector* inspector;