diff options
author | janekptacijarabaci <janekptacijarabaci@seznam.cz> | 2018-03-24 12:27:00 +0100 |
---|---|---|
committer | janekptacijarabaci <janekptacijarabaci@seznam.cz> | 2018-03-24 12:27:00 +0100 |
commit | 1ea1ed151571a523d1c8016dcd314e12238cd785 (patch) | |
tree | 86681b1375081559afa9117eb5800f1403c62e90 /js/src/frontend/BytecodeEmitter.cpp | |
parent | 2bb0252ab48a97a72c33cef9cbe54e86563f15c9 (diff) | |
download | UXP-1ea1ed151571a523d1c8016dcd314e12238cd785.tar UXP-1ea1ed151571a523d1c8016dcd314e12238cd785.tar.gz UXP-1ea1ed151571a523d1c8016dcd314e12238cd785.tar.lz UXP-1ea1ed151571a523d1c8016dcd314e12238cd785.tar.xz UXP-1ea1ed151571a523d1c8016dcd314e12238cd785.zip |
Bug 1147371: Implement calling IteratorClose and "return" on iterators in yield*
Issue #74
Diffstat (limited to 'js/src/frontend/BytecodeEmitter.cpp')
-rw-r--r-- | js/src/frontend/BytecodeEmitter.cpp | 80 |
1 files changed, 52 insertions, 28 deletions
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index e2c906850..98679eac6 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4898,6 +4898,14 @@ BytecodeEmitter::emitIteratorClose(Maybe<JumpTarget> yieldStarTryStart, bool all return false; if (!ifReturnDone.emitIfElse()) // ITER OLDRESULT FTYPE FVALUE RESULT return false; + if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER OLDRESULT FTYPE FVALUE VALUE + return false; + if (!emitPrepareIteratorResult()) // ITER OLDRESULT FTYPE FVALUE VALUE RESULT + return false; + if (!emit1(JSOP_SWAP)) // ITER OLDRESULT FTYPE FVALUE RESULT VALUE + return false; + if (!emitFinishIteratorResult(true)) // ITER OLDRESULT FTYPE FVALUE RESULT + return false; if (!emit1(JSOP_DUP)) // ITER OLDRESULT FTYPE FVALUE RESULT RESULT return false; if (!emit1(JSOP_SETRVAL)) // ITER OLDRESULT FTYPE FVALUE RESULT @@ -8059,61 +8067,77 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter, ParseNode* gen) // Catch location. stackDepth = uint32_t(depth); // ITER RESULT - if (!emit1(JSOP_POP)) // ITER - return false; - // THROW? = 'throw' in ITER - if (!emit1(JSOP_EXCEPTION)) // ITER EXCEPTION + if (!emit1(JSOP_EXCEPTION)) // ITER RESULT EXCEPTION return false; - if (!emit1(JSOP_SWAP)) // EXCEPTION ITER + if (!emitDupAt(2)) // ITER RESULT EXCEPTION ITER return false; - if (!emit1(JSOP_DUP)) // EXCEPTION ITER ITER + if (!emit1(JSOP_DUP)) // ITER RESULT EXCEPTION ITER ITER return false; - if (!emitAtomOp(cx->names().throw_, JSOP_STRING)) // EXCEPTION ITER ITER "throw" + if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP)) // ITER RESULT EXCEPTION ITER THROW return false; - if (!emit1(JSOP_SWAP)) // EXCEPTION ITER "throw" ITER + if (!emit1(JSOP_DUP)) // ITER RESULT EXCEPTION ITER THROW THROW return false; - if (!emit1(JSOP_IN)) // EXCEPTION ITER THROW? + if (!emit1(JSOP_UNDEFINED)) // ITER RESULT EXCEPTION ITER THROW THROW UNDEFINED return false; - // if (THROW?) goto delegate - JumpList checkThrow; - if (!emitJump(JSOP_IFNE, &checkThrow)) // EXCEPTION ITER + if (!emit1(JSOP_EQ)) // ITER RESULT EXCEPTION ITER THROW ?EQL return false; - if (!emit1(JSOP_POP)) // EXCEPTION + + IfThenElseEmitter ifThrowMethodIsNotDefined(this); + if (!ifThrowMethodIsNotDefined.emitIf()) // ITER RESULT EXCEPTION ITER THROW return false; - if (!emit1(JSOP_THROW)) // throw EXCEPTION + if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw return false; - - if (!emitJumpTargetAndPatch(checkThrow)) // delegate: + if (!ifThrowMethodIsNotDefined.emitEnd()) // ITER OLDRESULT EXCEPTION ITER THROW return false; - // RESULT = ITER.throw(EXCEPTION) // EXCEPTION ITER - stackDepth = uint32_t(depth); - if (!emit1(JSOP_DUP)) // EXCEPTION ITER ITER + // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.4. + // RESULT = ITER.throw(EXCEPTION) // ITER OLDRESULT EXCEPTION ITER THROW + if (!emit1(JSOP_SWAP)) // ITER OLDRESULT EXCEPTION THROW ITER return false; - if (!emit1(JSOP_DUP)) // EXCEPTION ITER ITER ITER + if (!emit2(JSOP_PICK, 2)) // ITER OLDRESULT THROW ITER EXCEPTION return false; - if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP)) // EXCEPTION ITER ITER THROW + if (!emitCall(JSOP_CALL, 1, iter)) // ITER OLDRESULT RESULT return false; - if (!emit1(JSOP_SWAP)) // EXCEPTION ITER THROW ITER + checkTypeSet(JSOP_CALL); + if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) // ITER OLDRESULT RESULT return false; - if (!emit2(JSOP_PICK, 3)) // ITER THROW ITER EXCEPTION + if (!emit1(JSOP_SWAP)) // ITER RESULT OLDRESULT return false; - if (!emitCall(JSOP_CALL, 1, iter)) // ITER RESULT + if (!emit1(JSOP_POP)) // ITER RESULT return false; - checkTypeSet(JSOP_CALL); MOZ_ASSERT(this->stackDepth == depth); JumpList checkResult; + // Note that there is no GOSUB to the finally block here. If the iterator has a + // "throw" method, it does not perform IteratorClose per + // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.ii. if (!emitJump(JSOP_GOTO, &checkResult)) // goto checkResult return false; - // Catch epilogue. + // The finally block, IteratorClose logic. + + JumpTarget finallyStart{ 0 }; + if (!emitJumpTarget(&finallyStart)) + return false; + if (!emit1(JSOP_FINALLY)) // ITER RESULT FTYPE FVALUE + return false; + if (!emitDupAt(3)) // ITER RESULT FTYPE FVALUE ITER + return false; + if (!emitIteratorClose(Some(tryStart))) // ITER RESULT FTYPE FVALUE + return false; + if (!emit1(JSOP_RETSUB)) // ITER RESULT + return false; + + // Catch and finally epilogue. // This is a peace offering to ReconstructPCStack. See the note in EmitTry. if (!emit1(JSOP_NOP)) return false; - if (!tryNoteList.append(JSTRY_CATCH, depth, tryStart.offset + JSOP_TRY_LENGTH, tryEnd.offset)) + size_t tryStartOffset = tryStart.offset + JSOP_TRY_LENGTH; + if (!tryNoteList.append(JSTRY_CATCH, depth, tryStartOffset, tryEnd.offset)) + return false; + if (!tryNoteList.append(JSTRY_FINALLY, depth, tryStartOffset, finallyStart.offset)) return false; - // After the try/catch block: send the received value to the iterator. + // After the try-catch-finally block: send the received value to the iterator. if (!emitJumpTargetAndPatch(send)) // send: return false; |