Bug 885648 - Add barriers for generator stack value. r=terrence, a=bajaj
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 26 Jun 2013 15:16:48 +0200
changeset 147804 d8a815ac433b0b09a0a3922332a603ae103c35bb
parent 147803 9a606e0005f146dca25df686d4c5ae6a138e017e
child 147805 f7c1a43c6b184adbe114cb1ad8f16711e07ebfb7
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, bajaj
bugs885648
milestone24.0a2
Bug 885648 - Add barriers for generator stack value. r=terrence, a=bajaj
js/src/jit-test/tests/basic/bug885648.js
js/src/jsiter.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug885648.js
@@ -0,0 +1,9 @@
+gczeal(4,1);
+var iterable = {persistedProp: 17};
+iterable.__iterator__ = function() {
+    yield ["foo", 2];
+    yield ["bar", 3];
+};
+var it = Iterator(iterable);
+assertEq(it.next().toString(), "foo,2");
+assertEq(it.next().toString(), "bar,3");
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1408,21 +1408,16 @@ GeneratorState::pushInterpreterFrame(JSC
      * differently.
      *
      * We could optimize this by setting a bit on the generator to signify
      * that it has been marked. If this bit has already been set, there is no
      * need to mark again. The bit would have to be reset before the next GC,
      * or else some kind of epoch scheme would have to be used.
      */
     GeneratorWriteBarrierPre(cx, gen_);
-
-    /*
-     * Don't change the state until after the frame is successfully pushed
-     * or else we might fail to scan some generator values.
-     */
     gen_->state = futureState_;
 
     gen_->fp->clearSuspended();
 
     cx->enterGenerator(gen_);   /* OOM check above. */
     entered_ = true;
     return gen_->fp;
 }
@@ -1551,19 +1546,22 @@ SendToGenerator(JSContext *cx, JSGenerat
     JSGeneratorState futureState;
     JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
     switch (op) {
       case JSGENOP_NEXT:
       case JSGENOP_SEND:
         if (gen->state == JSGEN_OPEN) {
             /*
              * Store the argument to send as the result of the yield
-             * expression.
+             * expression. The generator stack is not barriered, so we need
+             * write barriers here.
              */
+            HeapValue::writeBarrierPre(gen->regs.sp[-1]);
             gen->regs.sp[-1] = arg;
+            HeapValue::writeBarrierPost(cx->runtime(), gen->regs.sp[-1], &gen->regs.sp[-1]);
         }
         futureState = JSGEN_RUNNING;
         break;
 
       case JSGENOP_THROW:
         cx->setPendingException(arg);
         futureState = JSGEN_RUNNING;
         break;