diff options
author | Gaming4JC <g4jc@hyperbola.info> | 2019-12-12 22:26:46 -0500 |
---|---|---|
committer | Gaming4JC <g4jc@hyperbola.info> | 2019-12-17 06:25:31 -0500 |
commit | c66d2551222dda12c56fb96bb29e067414e644aa (patch) | |
tree | 22938195817738df120ca50893464ef4e337eb9d | |
parent | c9bddfca7eb5ef4642bdd8f27e35b9e2f4de65c9 (diff) | |
download | UXP-c66d2551222dda12c56fb96bb29e067414e644aa.tar UXP-c66d2551222dda12c56fb96bb29e067414e644aa.tar.gz UXP-c66d2551222dda12c56fb96bb29e067414e644aa.tar.lz UXP-c66d2551222dda12c56fb96bb29e067414e644aa.tar.xz UXP-c66d2551222dda12c56fb96bb29e067414e644aa.zip |
Bug 1454285 - Part 1: Specify the current scope when emitting await and .generator.
Tag #1287
-rw-r--r-- | js/src/frontend/BytecodeEmitter.cpp | 104 | ||||
-rw-r--r-- | js/src/frontend/BytecodeEmitter.h | 26 |
2 files changed, 81 insertions, 49 deletions
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 4710ab8e6..fda01dac2 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1988,6 +1988,8 @@ class MOZ_STACK_CLASS IfThenElseEmitter class ForOfLoopControl : public LoopControl { + using EmitterScope = BytecodeEmitter::EmitterScope; + // The stack depth of the iterator. int32_t iterDepth_; @@ -2080,8 +2082,8 @@ class ForOfLoopControl : public LoopControl MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_)); if (!bce->emitDupAt(slotFromTop)) // ITER ... EXCEPTION ITER return false; - if (!emitIteratorClose(bce, CompletionKind::Throw)) // ITER ... EXCEPTION - return false; + if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Throw)) + return false; // ITER ... EXCEPTION if (!ifIteratorIsNotClosed.emitEnd()) // ITER ... EXCEPTION return false; @@ -2104,8 +2106,8 @@ class ForOfLoopControl : public LoopControl return false; if (!bce->emitDupAt(slotFromTop + 1)) // ITER ... FTYPE FVALUE ITER return false; - if (!emitIteratorClose(bce, CompletionKind::Normal)) // ITER ... FTYPE FVALUE - return false; + if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Normal)) + return false; // ITER ... FTYPE FVALUE if (!ifGeneratorClosing.emitEnd()) // ITER ... FTYPE FVALUE return false; } @@ -2119,16 +2121,27 @@ class ForOfLoopControl : public LoopControl return true; } - bool emitIteratorClose(BytecodeEmitter* bce, - CompletionKind completionKind = CompletionKind::Normal) { + bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce, + CompletionKind completionKind = CompletionKind::Normal) { + return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind); + } + + bool emitIteratorCloseInScope(BytecodeEmitter* bce, + EmitterScope& currentScope, + CompletionKind completionKind = CompletionKind::Normal) { ptrdiff_t start = bce->offset(); - if (!bce->emitIteratorClose(iterKind_, completionKind, allowSelfHosted_)) + if (!bce->emitIteratorCloseInScope(currentScope, iterKind_, completionKind, + allowSelfHosted_)) + { return false; + } ptrdiff_t end = bce->offset(); return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end); } - bool emitPrepareForNonLocalJump(BytecodeEmitter* bce, bool isTarget) { + bool emitPrepareForNonLocalJumpFromScope(BytecodeEmitter* bce, + EmitterScope& currentScope, + bool isTarget) { // Pop unnecessary values from the stack. Effectively this means // leaving try-catch block. However, the performing IteratorClose can // reach the depth for try-catch, and effectively re-enter the @@ -2145,7 +2158,7 @@ class ForOfLoopControl : public LoopControl if (!bce->emit1(JSOP_SWAP)) // UNDEF ITER return false; - if (!emitIteratorClose(bce)) // UNDEF + if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) // UNDEF return false; if (isTarget) { @@ -2812,8 +2825,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta return false; ForOfLoopControl& loopinfo = control->as<ForOfLoopControl>(); - if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ false)) // ... + if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es, + /* isTarget = */ false)) + { // ... return false; + } } else { npops += 3; } @@ -2840,8 +2856,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta if (target && emitIteratorCloseAtTarget && target->is<ForOfLoopControl>()) { ForOfLoopControl& loopinfo = target->as<ForOfLoopControl>(); - if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ true)) // ... UNDEF UNDEF UNDEF + if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es, + /* isTarget = */ true)) + { // ... UNDEF UNDEF UNDEF return false; + } } EmitterScope* targetEmitterScope = target ? target->emitterScope() : bce_->varEmitterScope; @@ -5267,7 +5286,7 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter return false; if (iterKind == IteratorKind::Async) { - if (!emitAwait()) // ... RESULT + if (!emitAwaitInInnermostScope()) // ... RESULT return false; } @@ -5278,9 +5297,10 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter } bool -BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync */, - CompletionKind completionKind /* = CompletionKind::Normal */, - bool allowSelfHosted /* = false */) +BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope, + IteratorKind iterKind /* = IteratorKind::Sync */, + CompletionKind completionKind /* = CompletionKind::Normal */, + bool allowSelfHosted /* = false */) { MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting, ".close() on iterators is prohibited in self-hosted code because it " @@ -5372,7 +5392,7 @@ BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync if (!emit1(JSOP_SWAP)) // ... ... RVAL RESULT return false; } - if (!emitAwait()) // ... ... RVAL? RESULT + if (!emitAwaitInScope(currentScope)) // ... ... RVAL? RESULT return false; } @@ -5636,7 +5656,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav // For an empty pattern [], call IteratorClose unconditionally. Nothing // else needs to be done. if (!pattern->pn_head) - return emitIteratorClose(); // ... OBJ + return emitIteratorCloseInInnermostScope(); // ... OBJ // Push an initial FALSE value for DONE. if (!emit1(JSOP_FALSE)) // ... OBJ ITER FALSE @@ -5837,7 +5857,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav return false; if (!ifDone.emitElse()) // ... OBJ ITER return false; - if (!emitIteratorClose()) // ... OBJ + if (!emitIteratorCloseInInnermostScope()) // ... OBJ return false; if (!ifDone.emitEnd()) return false; @@ -8582,7 +8602,7 @@ BytecodeEmitter::emitReturn(ParseNode* pn) bool isAsyncGenerator = sc->asFunctionBox()->isAsync() && sc->asFunctionBox()->isStarGenerator(); if (isAsyncGenerator) { - if (!emitAwait()) + if (!emitAwaitInInnermostScope()) return false; } } else { @@ -8658,9 +8678,9 @@ BytecodeEmitter::emitReturn(ParseNode* pn) } bool -BytecodeEmitter::emitGetDotGenerator() +BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) { - NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator); + NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, ¤tScope); return emitGetNameAtLocation(cx->names().dotGenerator, loc); } @@ -8701,7 +8721,7 @@ BytecodeEmitter::emitYield(ParseNode* pn) // 11.4.3.7 AsyncGeneratorYield step 5. bool isAsyncGenerator = sc->asFunctionBox()->isAsync(); if (isAsyncGenerator) { - if (!emitAwait()) // RESULT + if (!emitAwaitInInnermostScope()) // RESULT return false; } @@ -8710,7 +8730,7 @@ BytecodeEmitter::emitYield(ParseNode* pn) return false; } - if (!emitGetDotGenerator()) + if (!emitGetDotGeneratorInInnermostScope()) return false; if (!emitYieldOp(JSOP_YIELD)) @@ -8720,24 +8740,24 @@ BytecodeEmitter::emitYield(ParseNode* pn) } bool -BytecodeEmitter::emitAwait() +BytecodeEmitter::emitAwaitInInnermostScope(ParseNode* pn) { - if (!emitGetDotGenerator()) - return false; - if (!emitYieldOp(JSOP_AWAIT)) + MOZ_ASSERT(sc->isFunctionBox()); + MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); + + if (!emitTree(pn->pn_kid)) return false; - return true; + return emitAwaitInInnermostScope(); } bool -BytecodeEmitter::emitAwait(ParseNode* pn) +BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) { - MOZ_ASSERT(sc->isFunctionBox()); - MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); - - if (!emitTree(pn->pn_kid)) + if (!emitGetDotGeneratorInScope(currentScope)) return false; - return emitAwait(); + if (!emitYieldOp(JSOP_AWAIT)) + return false; + return true; } bool @@ -8779,12 +8799,12 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) // 11.4.3.7 AsyncGeneratorYield step 5. if (isAsyncGenerator) { - if (!emitAwait()) // ITER RESULT + if (!emitAwaitInInnermostScope()) // NEXT ITER RESULT return false; } // Load the generator object. - if (!emitGetDotGenerator()) // ITER RESULT GENOBJ + if (!emitGetDotGeneratorInInnermostScope()) // NEXT ITER RESULT GENOBJ return false; // Yield RESULT as-is, without re-boxing. @@ -8821,7 +8841,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) // If the iterator does not have a "throw" method, it calls IteratorClose // and then throws a TypeError. IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync; - if (!emitIteratorClose(iterKind)) + if (!emitIteratorCloseInInnermostScope(iterKind)) // NEXT ITER RESULT EXCEPTION return false; if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw return false; @@ -8839,7 +8859,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) checkTypeSet(JSOP_CALL); if (isAsyncGenerator) { - if (!emitAwait()) // ITER OLDRESULT RESULT + if (!emitAwaitInInnermostScope()) // NEXT ITER OLDRESULT RESULT return false; } @@ -8910,7 +8930,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) checkTypeSet(JSOP_CALL); if (iterKind == IteratorKind::Async) { - if (!emitAwait()) // ... FTYPE FVALUE RESULT + if (!emitAwaitInInnermostScope()) // ... FTYPE FVALUE RESULT return false; } @@ -8991,7 +9011,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) checkTypeSet(JSOP_CALL); if (isAsyncGenerator) { - if (!emitAwait()) // ITER RESULT RESULT + if (!emitAwaitInInnermostScope()) // NEXT ITER RESULT RESULT return false; } @@ -10546,7 +10566,7 @@ BytecodeEmitter::emitFunctionBody(ParseNode* funBody) if (!emit1(JSOP_SETRVAL)) return false; - if (!emitGetDotGenerator()) + if (!emitGetDotGeneratorInInnermostScope()) return false; // No need to check for finally blocks, etc as in EmitReturn. @@ -10826,7 +10846,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_AWAIT: - if (!emitAwait(pn)) + if (!emitAwaitInInnermostScope(pn)) return false; break; diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 47bc87d76..36910c3dd 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -609,15 +609,20 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool iteratorResultShape(unsigned* shape); MOZ_MUST_USE bool emitToIteratorResult(bool done); - MOZ_MUST_USE bool emitGetDotGenerator(); + MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() { + return emitGetDotGeneratorInScope(*innermostEmitterScope); + } + MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope); MOZ_MUST_USE bool emitInitialYield(ParseNode* pn); MOZ_MUST_USE bool emitYield(ParseNode* pn); MOZ_MUST_USE bool emitYieldOp(JSOp op); MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); - MOZ_MUST_USE bool emitAwait(); - MOZ_MUST_USE bool emitAwait(ParseNode* pn); - + MOZ_MUST_USE bool emitAwaitInInnermostScope() { + return emitAwaitInScope(*innermostEmitterScope); + } + MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); + MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); MOZ_MUST_USE bool emitPropLHS(ParseNode* pn); MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op); MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn); @@ -717,9 +722,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter // onto the stack. MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync, bool allowSelfHosted = false); - MOZ_MUST_USE bool emitIteratorClose(IteratorKind iterKind = IteratorKind::Sync, - CompletionKind completionKind = CompletionKind::Normal, - bool allowSelfHosted = false); + MOZ_MUST_USE bool emitIteratorCloseInScope(EmitterScope& currentScope, + IteratorKind iterKind = IteratorKind::Sync, + CompletionKind completionKind = CompletionKind::Normal, + bool allowSelfHosted = false); + MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync, + CompletionKind completionKind = CompletionKind::Normal, + bool allowSelfHosted = false) { + return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind, + allowSelfHosted); + } template <typename InnerEmitter> MOZ_MUST_USE bool wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth, |