Bug 1093573 part 1 - Some generator bytecode changes. r=wingo
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 06 Nov 2014 10:12:56 +0100
changeset 214370 f8bcb09a02b3c2a2247f789aed8b11954e7ae710
parent 214369 a93bb566e665dde4e3a23ee0f219adb19472b452
child 214371 0af912c812944d82d3aa0069dde92dc38ff62dd2
push id27780
push userkwierso@gmail.com
push dateFri, 07 Nov 2014 02:25:05 +0000
treeherdermozilla-central@e6d47abb6a7b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswingo
bugs1093573
milestone36.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 1093573 part 1 - Some generator bytecode changes. r=wingo
js/src/frontend/BytecodeEmitter.cpp
js/src/jsopcode.h
js/src/vm/GeneratorObject.cpp
js/src/vm/Interpreter.cpp
js/src/vm/Opcodes.h
js/src/vm/Xdr.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3057,26 +3057,29 @@ frontend::EmitFunctionScript(ExclusiveCo
             return false;
 
         if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
             return false;
 
         if (bce->sc->asFunctionBox()->isStarGenerator() && !EmitFinishIteratorResult(cx, bce, true))
             return false;
 
+        if (Emit1(cx, bce, JSOP_SETRVAL) < 0)
+            return false;
+
         ScopeCoordinate sc;
         // We know that .generator is on the top scope chain node, as we are
         // at the function end.
         sc.setHops(0);
         MOZ_ALWAYS_TRUE(LookupAliasedNameSlot(bce, bce->script, cx->names().dotGenerator, &sc));
         if (!EmitAliasedVarOp(cx, JSOP_GETALIASEDVAR, sc, DontCheckLexical, bce))
             return false;
 
         // No need to check for finally blocks, etc as in EmitReturn.
-        if (Emit1(cx, bce, JSOP_FINALYIELD) < 0)
+        if (Emit1(cx, bce, JSOP_FINALYIELDRVAL) < 0)
             return false;
     }
 
     /*
      * Always end the script with a JSOP_RETRVAL. Some other parts of the codebase
      * depend on this opcode, e.g. js_InternalInterpret.
      */
     if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
@@ -5593,16 +5596,19 @@ EmitYield(ExclusiveContext *cx, Bytecode
     }
 
     if (!EmitTree(cx, bce, pn->pn_right))
         return false;
 
     if (Emit1(cx, bce, pn->getOp()) < 0)
         return false;
 
+    if (pn->getOp() == JSOP_INITIALYIELD && Emit1(cx, bce, JSOP_POP) < 0)
+        return false;
+
     return true;
 }
 
 static bool
 EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter, ParseNode *gen)
 {
     MOZ_ASSERT(bce->sc->isFunctionBox());
     MOZ_ASSERT(bce->sc->asFunctionBox()->isStarGenerator());
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -283,17 +283,16 @@ IsJumpOpcode(JSOp op)
 static inline bool
 BytecodeFallsThrough(JSOp op)
 {
     switch (op) {
       case JSOP_GOTO:
       case JSOP_DEFAULT:
       case JSOP_RETURN:
       case JSOP_RETRVAL:
-      case JSOP_FINALYIELD:
       case JSOP_FINALYIELDRVAL:
       case JSOP_THROW:
       case JSOP_TABLESWITCH:
         return false;
       case JSOP_GOSUB:
         /* These fall through indirectly, after executing a 'finally'. */
         return true;
       default:
@@ -592,17 +591,16 @@ FlowsIntoNext(JSOp op)
 {
     /* JSOP_YIELD is considered to flow into the next instruction, like JSOP_CALL. */
     switch (op) {
       case JSOP_RETRVAL:
       case JSOP_RETURN:
       case JSOP_THROW:
       case JSOP_GOTO:
       case JSOP_RETSUB:
-      case JSOP_FINALYIELD:
       case JSOP_FINALYIELDRVAL:
         return false;
       default:
         return true;
     }
 }
 
 inline bool
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -127,25 +127,22 @@ GeneratorObject::resume(JSContext *cx, I
         RootedObject array(cx, &genObj->expressionStack());
         GetElements(cx, array, len, activation.regs().sp);
         activation.regs().sp += len;
         genObj->clearExpressionStack();
     }
 
     activation.regs().pc = callee->nonLazyScript()->code() + genObj->suspendedBytecodeOffset();
 
-    // If we are resuming a JSOP_YIELD, always push on a value, even if we are
-    // raising an exception.  In the exception case, the stack needs to have
-    // something on it so that exception handling doesn't skip the catch
-    // blocks.  See TryNoteIter::settle.
-    if (!genObj->isNewborn()) {
-        activation.regs().sp++;
-        MOZ_ASSERT(activation.regs().spForStackDepth(activation.regs().stackDepth()));
-        activation.regs().sp[-1] = arg;
-    }
+    // Always push on a value, even if we are raising an exception. In the
+    // exception case, the stack needs to have something on it so that exception
+    // handling doesn't skip the catch blocks. See TryNoteIter::settle.
+    activation.regs().sp++;
+    MOZ_ASSERT(activation.regs().spForStackDepth(activation.regs().stackDepth()));
+    activation.regs().sp[-1] = arg;
 
     switch (resumeKind) {
       case NEXT:
         genObj->setRunning();
         return true;
 
       case THROW:
         cx->setPendingException(arg);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1654,16 +1654,17 @@ CASE(JSOP_UNUSED183)
 CASE(JSOP_UNUSED185)
 CASE(JSOP_UNUSED186)
 CASE(JSOP_UNUSED187)
 CASE(JSOP_UNUSED189)
 CASE(JSOP_UNUSED190)
 CASE(JSOP_UNUSED191)
 CASE(JSOP_UNUSED192)
 CASE(JSOP_UNUSED196)
+CASE(JSOP_UNUSED207)
 CASE(JSOP_UNUSED208)
 CASE(JSOP_UNUSED209)
 CASE(JSOP_UNUSED210)
 CASE(JSOP_UNUSED211)
 CASE(JSOP_UNUSED212)
 CASE(JSOP_UNUSED213)
 CASE(JSOP_UNUSED219)
 CASE(JSOP_UNUSED220)
@@ -3419,21 +3420,16 @@ CASE(JSOP_RESUME)
     bool ok = GeneratorObject::resume(cx, activation, gen, val, resumeKind);
     SET_SCRIPT(REGS.fp()->script());
     if (!ok)
         goto error;
 
     ADVANCE_AND_DISPATCH(0);
 }
 
-CASE(JSOP_FINALYIELD)
-    REGS.fp()->setReturnValue(REGS.sp[-2]);
-    REGS.sp[-2] = REGS.sp[-1];
-    REGS.sp--;
-    /* FALL THROUGH */
 CASE(JSOP_FINALYIELDRVAL)
 {
     RootedObject &gen = rootObject0;
     gen = &REGS.sp[-1].toObject();
     REGS.sp--;
 
     if (!GeneratorObject::finalSuspend(cx, gen)) {
         interpReturnOK = false;
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1563,66 +1563,58 @@ 1234567890123456789012345678901234567890
     /*
      * Pops the generator from the top of the stack, suspends it and stops
      * interpretation.
      *   Category: Statements
      *   Type: Generator
      *   Operands:
      *   Stack: generator =>
      */ \
-    macro(JSOP_INITIALYIELD,  202,"initialyield", NULL,   1,  1,  0,  JOF_BYTE) \
+    macro(JSOP_INITIALYIELD,  202,"initialyield", NULL,   1,  1,  1,  JOF_BYTE) \
     /*
      * Pops the generator and the return value 'rval1', stops interpretation and
      * returns 'rval1'. Pushes sent value from 'send()' onto the stack.
      *   Category: Statements
      *   Type: Generator
      *   Operands:
      *   Stack: rval1, gen => rval2
      */ \
     macro(JSOP_YIELD,         203,"yield",       NULL,    1,  2,  1,  JOF_BYTE) \
     /*
-     * Pops the generator and the value to yield from the stack. Then suspends
-     * and closes the generator.
-     *   Category: Statements
-     *   Type: Generator
-     *   Operands:
-     *   Stack: gen, val =>
-     */ \
-    macro(JSOP_FINALYIELD,    204,"finalyield",  NULL,    1,  2,  0,  JOF_BYTE) \
-    /*
      * Pops the generator and suspends and closes it. Yields the value in the
      * frame's return value slot.
      *   Category: Statements
      *   Type: Generator
      *   Operands:
      *   Stack: gen =>
      */ \
-    macro(JSOP_FINALYIELDRVAL,205,"finalyieldrval",NULL,  1,  1,  0,  JOF_BYTE) \
+    macro(JSOP_FINALYIELDRVAL,204,"finalyieldrval",NULL,  1,  1,  0,  JOF_BYTE) \
     /*
      * Pops the generator and argument from the stack, pushes a new generator
      * frame and resumes execution of it. Pushes the return value after the
      * generator yields.
      *   Category: Statements
      *   Type: Generator
      *   Operands: resume kind (GeneratorObject::ResumeKind)
      *   Stack: gen, val => rval
      */ \
-    macro(JSOP_RESUME,        206,"resume",      NULL,    3,  2,  1,  JOF_UINT8|JOF_INVOKE) \
+    macro(JSOP_RESUME,        205,"resume",      NULL,    3,  2,  1,  JOF_UINT8|JOF_INVOKE) \
     /*
      * Pops the top two values on the stack as 'obj' and 'v', pushes 'v' to
      * 'obj'.
      *
      * This opcode is used for Array Comprehension.
      *   Category: Literals
      *   Type: Array
      *   Operands:
      *   Stack: v, obj =>
      */ \
-    macro(JSOP_ARRAYPUSH,     207,"arraypush",   NULL,    1,  2,  0,  JOF_BYTE) \
+    macro(JSOP_ARRAYPUSH,     206,"arraypush",   NULL,    1,  2,  0,  JOF_BYTE) \
     \
+    macro(JSOP_UNUSED207,     207, "unused207",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED208,     208, "unused208",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED209,     209, "unused209",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED210,     210, "unused210",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED211,     211, "unused211",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED212,     212, "unused212",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED213,     213, "unused213",    NULL,  1,  0,  0,  JOF_BYTE) \
     /*
      * Pushes the global scope onto the stack.
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -29,17 +29,17 @@ namespace js {
  *  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
  *
  * === GREETINGS, FELLOW SUBTRAHEND INCREMENTER! ===
  * For the time being, please increment the subtrahend by 2 each time it
  * changes, because we have two flavors of bytecode: with JSOP_SYMBOL (in
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 192;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 194;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND
 #ifdef JS_HAS_SYMBOLS
                                                            + 1
 #endif
                                                               ));