summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2019-12-12 22:26:46 -0500
committerGaming4JC <g4jc@hyperbola.info>2019-12-17 06:25:31 -0500
commitc66d2551222dda12c56fb96bb29e067414e644aa (patch)
tree22938195817738df120ca50893464ef4e337eb9d
parentc9bddfca7eb5ef4642bdd8f27e35b9e2f4de65c9 (diff)
downloaduxp-c66d2551222dda12c56fb96bb29e067414e644aa.tar.gz
Bug 1454285 - Part 1: Specify the current scope when emitting await and .generator.
Tag #1287
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp104
-rw-r--r--js/src/frontend/BytecodeEmitter.h26
2 files changed, 81 insertions, 49 deletions
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 4710ab8e63..fda01dac2f 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, &currentScope);
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 47bc87d76a..36910c3dd4 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,