summaryrefslogtreecommitdiffstats
path: root/js/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend')
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp59
-rw-r--r--js/src/frontend/BytecodeEmitter.h49
2 files changed, 76 insertions, 32 deletions
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index fda01dac2..f4574b248 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -100,7 +100,7 @@ class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::Nestab
NestableControl(BytecodeEmitter* bce, StatementKind kind)
: Nestable<NestableControl>(&bce->innermostNestableControl),
kind_(kind),
- emitterScope_(bce->innermostEmitterScope)
+ emitterScope_(bce->innermostEmitterScopeNoCheck())
{ }
public:
@@ -426,7 +426,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc
// enclosing BCE.
if ((*bce)->parent) {
*bce = (*bce)->parent;
- return (*bce)->innermostEmitterScope;
+ return (*bce)->innermostEmitterScopeNoCheck();
}
return nullptr;
@@ -460,7 +460,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc
public:
explicit EmitterScope(BytecodeEmitter* bce)
- : Nestable<EmitterScope>(&bce->innermostEmitterScope),
+ : Nestable<EmitterScope>(&bce->innermostEmitterScope_),
nameCache_(bce->cx->frontendCollectionPool()),
hasEnvironment_(false),
environmentChainLength_(0),
@@ -866,7 +866,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind
Handle<LexicalScope::Data*> bindings)
{
MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda);
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
if (!ensureCache(bce))
return false;
@@ -935,7 +935,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind
bool
BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
MOZ_ASSERT(funbox->namedLambdaBindings());
if (!ensureCache(bce))
@@ -1002,7 +1002,7 @@ BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce,
bool
BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
if (!ensureCache(bce))
return false;
@@ -1035,7 +1035,7 @@ BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
bool
BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
// If there are parameter expressions, there is an extra var scope.
if (!funbox->hasExtraBodyVarScope())
@@ -1126,7 +1126,7 @@ BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, F
MOZ_ASSERT(funbox->hasParameterExprs);
MOZ_ASSERT(funbox->extraVarScopeBindings() ||
funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings());
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
// The extra var scope is never popped once it's entered. It replaces the
// function scope as the var emitter scope.
@@ -1212,7 +1212,7 @@ class DynamicBindingIter : public BindingIter
bool
BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
bce->setVarEmitterScope(this);
@@ -1272,7 +1272,7 @@ BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedCon
bool
BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
bce->setVarEmitterScope(this);
@@ -1327,7 +1327,7 @@ BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext
bool
BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
bce->setVarEmitterScope(this);
@@ -1384,7 +1384,7 @@ BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedCon
bool
BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce)
{
- MOZ_ASSERT(this == bce->innermostEmitterScope);
+ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
if (!ensureCache(bce))
return false;
@@ -1412,7 +1412,7 @@ BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
{
// If we aren't leaving the scope due to a non-local jump (e.g., break),
// we must be the innermost scope.
- MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope);
+ MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScopeNoCheck());
ScopeKind kind = scope(bce)->kind();
switch (kind) {
@@ -2123,7 +2123,7 @@ class ForOfLoopControl : public LoopControl
bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce,
CompletionKind completionKind = CompletionKind::Normal) {
- return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind);
+ return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(), completionKind);
}
bool emitIteratorCloseInScope(BytecodeEmitter* bce,
@@ -2201,8 +2201,11 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
bodyScopeIndex(UINT32_MAX),
varEmitterScope(nullptr),
innermostNestableControl(nullptr),
- innermostEmitterScope(nullptr),
+ innermostEmitterScope_(nullptr),
innermostTDZCheckCache(nullptr),
+#ifdef DEBUG
+ unstableEmitterScope(false),
+#endif
constList(cx),
scopeList(cx),
tryNoteList(cx),
@@ -2259,13 +2262,13 @@ BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
NameLocation
BytecodeEmitter::lookupName(JSAtom* name)
{
- return innermostEmitterScope->lookup(this, name);
+ return innermostEmitterScope()->lookup(this, name);
}
Maybe<NameLocation>
BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target)
{
- return innermostEmitterScope->locationBoundInScope(this, name, target);
+ return innermostEmitterScope()->locationBoundInScope(this, name, target);
}
Maybe<NameLocation>
@@ -2726,7 +2729,7 @@ class NonLocalExitControl
: bce_(bce),
savedScopeNoteIndex_(bce->scopeNoteList.length()),
savedDepth_(bce->stackDepth),
- openScopeNoteIndex_(bce->innermostEmitterScope->noteIndex()),
+ openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
kind_(kind)
{ }
@@ -2772,9 +2775,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta
using NestableControl = BytecodeEmitter::NestableControl;
using EmitterScope = BytecodeEmitter::EmitterScope;
- EmitterScope* es = bce_->innermostEmitterScope;
+ EmitterScope* es = bce_->innermostEmitterScope();
int npops = 0;
+ AutoCheckUnstableEmitterScope cues(bce_);
+
// For 'continue', 'break', and 'return' statements, emit IteratorClose
// bytecode inline. 'continue' statements do not call IteratorClose for
// the loop they are continuing.
@@ -2895,7 +2900,7 @@ BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteTy
Scope*
BytecodeEmitter::innermostScope() const
{
- return innermostEmitterScope->scope(this);
+ return innermostEmitterScope()->scope(this);
}
bool
@@ -3555,7 +3560,7 @@ BytecodeEmitter::needsImplicitThis()
return true;
// Otherwise see if the current point is under a 'with'.
- for (EmitterScope* es = innermostEmitterScope; es; es = es->enclosingInFrame()) {
+ for (EmitterScope* es = innermostEmitterScope(); es; es = es->enclosingInFrame()) {
if (es->scope(this)->kind() == ScopeKind::With)
return true;
}
@@ -5206,7 +5211,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri
// destructuring declaration needs to initialize the name in
// the function scope. The innermost scope is the var scope,
// and its enclosing scope is the function scope.
- EmitterScope* funScope = innermostEmitterScope->enclosingInFrame();
+ EmitterScope* funScope = innermostEmitterScope()->enclosingInFrame();
NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope);
if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true))
return false;
@@ -7308,7 +7313,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
// bindings inducing an environment, recreate the current environment.
DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST));
- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
+ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
if (headLexicalEmitterScope->hasEnvironment()) {
@@ -7490,7 +7495,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte
// it must be the innermost one. If that scope has closed-over
// bindings inducing an environment, recreate the current environment.
MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST));
- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
+ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
if (headLexicalEmitterScope->hasEnvironment()) {
@@ -7619,7 +7624,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
// exists for the head, it must be the innermost one. If that scope
// has closed-over bindings inducing an environment, recreate the
// current environment.
- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
+ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
if (headLexicalEmitterScope->hasEnvironment()) {
@@ -7667,7 +7672,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
// ES 13.7.4.8 step 3.e. The per-iteration freshening.
if (forLoopRequiresFreshening) {
- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
+ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
if (headLexicalEmitterScope->hasEnvironment()) {
@@ -10366,7 +10371,7 @@ BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn)
{
ParseNode* funBody = pn->last();
FunctionBox* funbox = sc->asFunctionBox();
- EmitterScope* funScope = innermostEmitterScope;
+ EmitterScope* funScope = innermostEmitterScope();
bool hasParameterExprs = funbox->hasParameterExprs;
bool hasRest = funbox->hasRest();
diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
index 36910c3dd..8ad409c11 100644
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -228,9 +228,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter
EmitterScope* varEmitterScope;
NestableControl* innermostNestableControl;
- EmitterScope* innermostEmitterScope;
+ EmitterScope* innermostEmitterScope_;
TDZCheckCache* innermostTDZCheckCache;
+#ifdef DEBUG
+ bool unstableEmitterScope;
+
+ friend class AutoCheckUnstableEmitterScope;
+#endif
+
+ EmitterScope* innermostEmitterScope() const {
+ MOZ_ASSERT(!unstableEmitterScope);
+ return innermostEmitterScopeNoCheck();
+ }
+ EmitterScope* innermostEmitterScopeNoCheck() const {
+ return innermostEmitterScope_;
+ }
+
CGConstList constList; /* constants to be included with the script */
CGObjectList objectList; /* list of emitted objects */
CGScopeList scopeList; /* list of emitted scopes */
@@ -319,7 +333,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
EmitterScope* source);
mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(JSAtom* name) {
- return locationOfNameBoundInFunctionScope(name, innermostEmitterScope);
+ return locationOfNameBoundInFunctionScope(name, innermostEmitterScope());
}
void setVarEmitterScope(EmitterScope* emitterScope) {
@@ -610,7 +624,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitToIteratorResult(bool done);
MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() {
- return emitGetDotGeneratorInScope(*innermostEmitterScope);
+ return emitGetDotGeneratorInScope(*innermostEmitterScope());
}
MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope);
@@ -619,7 +633,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitYieldOp(JSOp op);
MOZ_MUST_USE bool emitYieldStar(ParseNode* iter);
MOZ_MUST_USE bool emitAwaitInInnermostScope() {
- return emitAwaitInScope(*innermostEmitterScope);
+ return emitAwaitInScope(*innermostEmitterScope());
}
MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn);
MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope);
@@ -729,7 +743,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync,
CompletionKind completionKind = CompletionKind::Normal,
bool allowSelfHosted = false) {
- return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind,
+ return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, completionKind,
allowSelfHosted);
}
@@ -829,6 +843,31 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
};
+class MOZ_RAII AutoCheckUnstableEmitterScope {
+#ifdef DEBUG
+ bool prev_;
+ BytecodeEmitter* bce_;
+#endif
+
+ public:
+ AutoCheckUnstableEmitterScope() = delete;
+ explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce)
+#ifdef DEBUG
+ : bce_(bce)
+#endif
+ {
+#ifdef DEBUG
+ prev_ = bce_->unstableEmitterScope;
+ bce_->unstableEmitterScope = true;
+#endif
+ }
+ ~AutoCheckUnstableEmitterScope() {
+#ifdef DEBUG
+ bce_->unstableEmitterScope = prev_;
+#endif
+ }
+};
+
} /* namespace frontend */
} /* namespace js */