summaryrefslogtreecommitdiffstats
path: root/js/src/frontend/BytecodeEmitter.cpp
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-24 12:27:00 +0100
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-24 12:27:00 +0100
commit1ea1ed151571a523d1c8016dcd314e12238cd785 (patch)
tree86681b1375081559afa9117eb5800f1403c62e90 /js/src/frontend/BytecodeEmitter.cpp
parent2bb0252ab48a97a72c33cef9cbe54e86563f15c9 (diff)
downloadUXP-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.cpp80
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;