mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1179063 - Cleanup: rename top -> innermost, down -> enclosing in StmtInfoStack. (r=efaust)
This commit is contained in:
parent
820ac92185
commit
14172251ce
@ -55,8 +55,8 @@ using mozilla::UniquePtr;
|
||||
|
||||
struct frontend::StmtInfoBCE : public StmtInfoBase
|
||||
{
|
||||
StmtInfoBCE* down; /* info for enclosing statement */
|
||||
StmtInfoBCE* downScope; /* next enclosing lexical scope */
|
||||
StmtInfoBCE* enclosing;
|
||||
StmtInfoBCE* enclosingScope;
|
||||
|
||||
ptrdiff_t update; /* loop update offset (top if none) */
|
||||
ptrdiff_t breaks; /* offset of last break in loop */
|
||||
@ -384,17 +384,17 @@ static_assert(MOZ_ARRAY_LENGTH(statementName) == uint16_t(StmtType::LIMIT),
|
||||
"statementName array and StmtType enum must be consistent");
|
||||
|
||||
static const char*
|
||||
StatementName(StmtInfoBCE* topStmt)
|
||||
StatementName(StmtInfoBCE* stmt)
|
||||
{
|
||||
if (!topStmt)
|
||||
if (!stmt)
|
||||
return js_script_str;
|
||||
return statementName[uint16_t(topStmt->type)];
|
||||
return statementName[uint16_t(stmt->type)];
|
||||
}
|
||||
|
||||
static void
|
||||
ReportStatementTooLarge(TokenStream& ts, StmtInfoBCE* topStmt)
|
||||
ReportStatementTooLarge(TokenStream& ts, StmtInfoBCE* stmt)
|
||||
{
|
||||
ts.reportError(JSMSG_NEED_DIET, StatementName(topStmt));
|
||||
ts.reportError(JSMSG_NEED_DIET, StatementName(stmt));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -509,7 +509,7 @@ BytecodeEmitter::emitLoopEntry(ParseNode* nextpn)
|
||||
return false;
|
||||
}
|
||||
|
||||
LoopStmtInfo* loop = LoopStmtInfo::fromStmtInfo(topStmt());
|
||||
LoopStmtInfo* loop = LoopStmtInfo::fromStmtInfo(innermostStmt());
|
||||
MOZ_ASSERT(loop->loopDepth > 0);
|
||||
|
||||
uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loop->loopDepth, loop->canIonOsr);
|
||||
@ -574,7 +574,7 @@ class NonLocalExitScope {
|
||||
savedDepth(bce->stackDepth),
|
||||
openScopeIndex(UINT32_MAX)
|
||||
{
|
||||
if (StmtInfoBCE* stmt = bce->topScopeStmt())
|
||||
if (StmtInfoBCE* stmt = bce->innermostScopeStmt())
|
||||
openScopeIndex = stmt->blockScopeIndex;
|
||||
}
|
||||
~NonLocalExitScope() {
|
||||
@ -606,7 +606,7 @@ NonLocalExitScope::prepareForNonLocalJump(StmtInfoBCE* toStmt)
|
||||
|
||||
#define FLUSH_POPS() if (npops && !bce->flushPops(&npops)) return false
|
||||
|
||||
for (StmtInfoBCE* stmt = bce->topStmt(); stmt != toStmt; stmt = stmt->down) {
|
||||
for (StmtInfoBCE* stmt = bce->innermostStmt(); stmt != toStmt; stmt = stmt->enclosing) {
|
||||
switch (stmt->type) {
|
||||
case StmtType::FINALLY:
|
||||
FLUSH_POPS();
|
||||
@ -721,16 +721,16 @@ BytecodeEmitter::pushLoopStatement(LoopStmtInfo* stmt, StmtType type, ptrdiff_t
|
||||
pushStatementInner(stmt, type, top);
|
||||
MOZ_ASSERT(stmt->isLoop());
|
||||
|
||||
LoopStmtInfo* downLoop = nullptr;
|
||||
for (StmtInfoBCE* outer = stmt->down; outer; outer = outer->down) {
|
||||
LoopStmtInfo* enclosingLoop = nullptr;
|
||||
for (StmtInfoBCE* outer = stmt->enclosing; outer; outer = outer->enclosing) {
|
||||
if (outer->isLoop()) {
|
||||
downLoop = LoopStmtInfo::fromStmtInfo(outer);
|
||||
enclosingLoop = LoopStmtInfo::fromStmtInfo(outer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stmt->stackDepth = this->stackDepth;
|
||||
stmt->loopDepth = downLoop ? downLoop->loopDepth + 1 : 1;
|
||||
stmt->loopDepth = enclosingLoop ? enclosingLoop->loopDepth + 1 : 1;
|
||||
|
||||
int loopSlots;
|
||||
if (type == StmtType::SPREAD)
|
||||
@ -742,17 +742,18 @@ BytecodeEmitter::pushLoopStatement(LoopStmtInfo* stmt, StmtType type, ptrdiff_t
|
||||
|
||||
MOZ_ASSERT(loopSlots <= stmt->stackDepth);
|
||||
|
||||
if (downLoop)
|
||||
stmt->canIonOsr = (downLoop->canIonOsr &&
|
||||
stmt->stackDepth == downLoop->stackDepth + loopSlots);
|
||||
else
|
||||
if (enclosingLoop) {
|
||||
stmt->canIonOsr = (enclosingLoop->canIonOsr &&
|
||||
stmt->stackDepth == enclosingLoop->stackDepth + loopSlots);
|
||||
} else {
|
||||
stmt->canIonOsr = stmt->stackDepth == loopSlots;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
BytecodeEmitter::enclosingStaticScope()
|
||||
{
|
||||
if (StmtInfoBCE* stmt = topScopeStmt())
|
||||
if (StmtInfoBCE* stmt = innermostScopeStmt())
|
||||
return stmt->staticScope;
|
||||
|
||||
if (!sc->isFunctionBox()) {
|
||||
@ -820,7 +821,7 @@ BytecodeEmitter::computeLocalOffset(Handle<StaticBlockObject*> blockObj)
|
||||
: 0;
|
||||
unsigned localOffset = nbodyfixed;
|
||||
|
||||
if (StmtInfoBCE* stmt = topScopeStmt()) {
|
||||
if (StmtInfoBCE* stmt = innermostScopeStmt()) {
|
||||
Rooted<NestedScopeObject*> outer(cx, stmt->staticScope);
|
||||
for (; outer; outer = outer->enclosingNestedScope()) {
|
||||
if (outer->is<StaticBlockObject>()) {
|
||||
@ -920,7 +921,7 @@ BytecodeEmitter::enterNestedScope(StmtInfoBCE* stmt, ObjectBox* objbox, StmtType
|
||||
}
|
||||
|
||||
uint32_t parent = BlockScopeNote::NoBlockScopeIndex;
|
||||
if (StmtInfoBCE* stmt = topScopeStmt())
|
||||
if (StmtInfoBCE* stmt = innermostScopeStmt())
|
||||
parent = stmt->blockScopeIndex;
|
||||
|
||||
stmt->blockScopeIndex = blockScopeList.length();
|
||||
@ -929,7 +930,7 @@ BytecodeEmitter::enterNestedScope(StmtInfoBCE* stmt, ObjectBox* objbox, StmtType
|
||||
|
||||
pushStatement(stmt, stmtType, offset());
|
||||
scopeObj->initEnclosingNestedScope(enclosingStaticScope());
|
||||
stmtStack.linkAsTopScopal(stmt, *scopeObj);
|
||||
stmtStack.linkAsInnermostScopal(stmt, *scopeObj);
|
||||
MOZ_ASSERT(stmt->linksScope());
|
||||
stmt->isBlockScope = (stmtType == StmtType::BLOCK);
|
||||
|
||||
@ -941,9 +942,9 @@ BytecodeEmitter::enterNestedScope(StmtInfoBCE* stmt, ObjectBox* objbox, StmtType
|
||||
void
|
||||
BytecodeEmitter::popStatement()
|
||||
{
|
||||
if (!topStmt()->isTrying()) {
|
||||
backPatch(topStmt()->breaks, code().end(), JSOP_GOTO);
|
||||
backPatch(topStmt()->continues, code(topStmt()->update), JSOP_GOTO);
|
||||
if (!innermostStmt()->isTrying()) {
|
||||
backPatch(innermostStmt()->breaks, code().end(), JSOP_GOTO);
|
||||
backPatch(innermostStmt()->continues, code(innermostStmt()->update), JSOP_GOTO);
|
||||
}
|
||||
|
||||
stmtStack.pop();
|
||||
@ -952,7 +953,7 @@ BytecodeEmitter::popStatement()
|
||||
bool
|
||||
BytecodeEmitter::leaveNestedScope(StmtInfoBCE* stmt)
|
||||
{
|
||||
MOZ_ASSERT(stmt == topScopeStmt());
|
||||
MOZ_ASSERT(stmt == innermostScopeStmt());
|
||||
MOZ_ASSERT(stmt->isBlockScope == !(stmt->type == StmtType::WITH));
|
||||
uint32_t blockScopeIndex = stmt->blockScopeIndex;
|
||||
|
||||
@ -1162,7 +1163,7 @@ unsigned
|
||||
BytecodeEmitter::dynamicNestedScopeDepth()
|
||||
{
|
||||
unsigned depth = 0;
|
||||
if (StmtInfoBCE* stmt = topScopeStmt()) {
|
||||
if (StmtInfoBCE* stmt = innermostScopeStmt()) {
|
||||
for (NestedScopeObject* b = stmt->staticScope; b; b = b->enclosingNestedScope()) {
|
||||
if (!b->is<StaticBlockObject>() || b->as<StaticBlockObject>().needsClone())
|
||||
++depth;
|
||||
@ -1306,8 +1307,8 @@ BytecodeEmitter::emitAliasedVarOp(JSOp op, ParseNode* pn)
|
||||
JS_ALWAYS_TRUE(bceOfDef->lookupAliasedNameSlot(pn->name(), &sc));
|
||||
} else {
|
||||
MOZ_ASSERT_IF(this->sc->isFunctionBox(), local <= bceOfDef->script->bindings.numLocals());
|
||||
MOZ_ASSERT(bceOfDef->topScopeStmt()->staticScope->is<StaticBlockObject>());
|
||||
StmtInfoBCE* stmt = bceOfDef->topScopeStmt();
|
||||
MOZ_ASSERT(bceOfDef->innermostScopeStmt()->staticScope->is<StaticBlockObject>());
|
||||
StmtInfoBCE* stmt = bceOfDef->innermostScopeStmt();
|
||||
Rooted<StaticBlockObject*> b(cx, &stmt->staticScope->as<StaticBlockObject>());
|
||||
local = bceOfDef->localsToFrameSlots_[local];
|
||||
while (local < b->localOffset()) {
|
||||
@ -1513,7 +1514,7 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
||||
if (emitterMode == BytecodeEmitter::LazyFunction) {
|
||||
// The only statements within a lazy function which can push lexical
|
||||
// scopes are try/catch blocks. Use generic ops in this case.
|
||||
for (StmtInfoBCE* stmt = topStmt(); stmt; stmt = stmt->down) {
|
||||
for (StmtInfoBCE* stmt = innermostStmt(); stmt; stmt = stmt->enclosing) {
|
||||
if (stmt->type == StmtType::CATCH)
|
||||
return true;
|
||||
}
|
||||
@ -2312,7 +2313,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
bool
|
||||
BytecodeEmitter::isInLoop()
|
||||
{
|
||||
for (StmtInfoBCE* stmt = topStmt(); stmt; stmt = stmt->down) {
|
||||
for (StmtInfoBCE* stmt = innermostStmt(); stmt; stmt = stmt->enclosing) {
|
||||
if (stmt->isLoop())
|
||||
return true;
|
||||
}
|
||||
@ -2340,7 +2341,7 @@ BytecodeEmitter::needsImplicitThis()
|
||||
if (sc->inWith())
|
||||
return true;
|
||||
|
||||
for (StmtInfoBCE* stmt = topStmt(); stmt; stmt = stmt->down) {
|
||||
for (StmtInfoBCE* stmt = innermostStmt(); stmt; stmt = stmt->enclosing) {
|
||||
if (stmt->type == StmtType::WITH)
|
||||
return true;
|
||||
}
|
||||
@ -4766,12 +4767,12 @@ BytecodeEmitter::emitCatch(ParseNode* pn)
|
||||
* Morph StmtType::BLOCK to StmtType::CATCH, note the block entry code offset,
|
||||
* and save the block object atom.
|
||||
*/
|
||||
StmtInfoBCE* stmt = topStmt();
|
||||
StmtInfoBCE* stmt = innermostStmt();
|
||||
MOZ_ASSERT(stmt->type == StmtType::BLOCK && stmt->isBlockScope);
|
||||
stmt->type = StmtType::CATCH;
|
||||
|
||||
/* Go up one statement info record to the TRY or FINALLY record. */
|
||||
stmt = stmt->down;
|
||||
stmt = stmt->enclosing;
|
||||
MOZ_ASSERT(stmt->type == StmtType::TRY || stmt->type == StmtType::FINALLY);
|
||||
|
||||
/* Pick up the pending exception and bind it to the catch variable. */
|
||||
@ -5354,7 +5355,7 @@ BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn, ptrdiff_t top)
|
||||
StmtInfoBCE* stmt = &stmtInfo;
|
||||
do {
|
||||
stmt->update = offset();
|
||||
} while ((stmt = stmt->down) != nullptr && stmt->type == StmtType::LABEL);
|
||||
} while ((stmt = stmt->enclosing) != nullptr && stmt->type == StmtType::LABEL);
|
||||
} else {
|
||||
if (!emit1(JSOP_INITELEM_INC)) // ITER ARR (I+1)
|
||||
return false;
|
||||
@ -5396,7 +5397,7 @@ BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn, ptrdiff_t top)
|
||||
return false;
|
||||
|
||||
// Fixup breaks and continues.
|
||||
// For StmtType::SPREAD, just pop pc->topStmt.
|
||||
// For StmtType::SPREAD, just pop innermostStmt().
|
||||
popStatement();
|
||||
|
||||
if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top, offset()))
|
||||
@ -5495,7 +5496,7 @@ BytecodeEmitter::emitForIn(ParseNode* pn, ptrdiff_t top)
|
||||
StmtInfoBCE* stmt = &stmtInfo;
|
||||
do {
|
||||
stmt->update = offset();
|
||||
} while ((stmt = stmt->down) != nullptr && stmt->type == StmtType::LABEL);
|
||||
} while ((stmt = stmt->enclosing) != nullptr && stmt->type == StmtType::LABEL);
|
||||
|
||||
/*
|
||||
* Fixup the goto that starts the loop to jump down to JSOP_MOREITER.
|
||||
@ -5616,21 +5617,21 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top)
|
||||
StmtInfoBCE* stmt = &stmtInfo;
|
||||
do {
|
||||
stmt->update = offset();
|
||||
} while ((stmt = stmt->down) != nullptr && stmt->type == StmtType::LABEL);
|
||||
} while ((stmt = stmt->enclosing) != nullptr && stmt->type == StmtType::LABEL);
|
||||
|
||||
// Freshen the block on the scope chain to expose distinct bindings for each loop
|
||||
// iteration.
|
||||
if (forLoopRequiresFreshening) {
|
||||
// The scope chain only includes an actual block *if* the scope object
|
||||
// is captured and therefore requires cloning. Get the static block
|
||||
// object from the parent let-block statement (which *must* be the
|
||||
// object from the enclosing let-block statement (which *must* be the
|
||||
// let-statement for the guarding condition to have held) and freshen
|
||||
// if the block object needs cloning.
|
||||
StmtInfoBCE* parent = stmtInfo.down;
|
||||
MOZ_ASSERT(parent->type == StmtType::BLOCK);
|
||||
MOZ_ASSERT(parent->isBlockScope);
|
||||
StmtInfoBCE* enclosing = stmtInfo.enclosing;
|
||||
MOZ_ASSERT(enclosing->type == StmtType::BLOCK);
|
||||
MOZ_ASSERT(enclosing->isBlockScope);
|
||||
|
||||
if (parent->staticScope->as<StaticBlockObject>().needsClone()) {
|
||||
if (enclosing->staticScope->as<StaticBlockObject>().needsClone()) {
|
||||
if (!emit1(JSOP_FRESHENBLOCKSCOPE))
|
||||
return false;
|
||||
}
|
||||
@ -5844,7 +5845,7 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
if (!sc->isFunctionBox()) {
|
||||
MOZ_ASSERT(pn->pn_cookie.isFree());
|
||||
MOZ_ASSERT(pn->getOp() == JSOP_NOP);
|
||||
MOZ_ASSERT(!topStmt());
|
||||
MOZ_ASSERT(!innermostStmt());
|
||||
switchToPrologue();
|
||||
if (!emitIndex32(JSOP_DEFFUN, index))
|
||||
return false;
|
||||
@ -5907,7 +5908,7 @@ BytecodeEmitter::emitDo(ParseNode* pn)
|
||||
StmtInfoBCE* stmt = &stmtInfo;
|
||||
do {
|
||||
stmt->update = off;
|
||||
} while ((stmt = stmt->down) != nullptr && stmt->type == StmtType::LABEL);
|
||||
} while ((stmt = stmt->enclosing) != nullptr && stmt->type == StmtType::LABEL);
|
||||
|
||||
/* Compile the loop condition, now that continues know where to go. */
|
||||
if (!emitTree(pn->pn_right))
|
||||
@ -5993,15 +5994,15 @@ BytecodeEmitter::emitWhile(ParseNode* pn, ptrdiff_t top)
|
||||
bool
|
||||
BytecodeEmitter::emitBreak(PropertyName* label)
|
||||
{
|
||||
StmtInfoBCE* stmt = topStmt();
|
||||
StmtInfoBCE* stmt = innermostStmt();
|
||||
SrcNoteType noteType;
|
||||
if (label) {
|
||||
while (stmt->type != StmtType::LABEL || stmt->label != label)
|
||||
stmt = stmt->down;
|
||||
stmt = stmt->enclosing;
|
||||
noteType = SRC_BREAK2LABEL;
|
||||
} else {
|
||||
while (!stmt->isLoop() && stmt->type != StmtType::SWITCH)
|
||||
stmt = stmt->down;
|
||||
stmt = stmt->enclosing;
|
||||
noteType = (stmt->type == StmtType::SWITCH) ? SRC_SWITCHBREAK : SRC_BREAK;
|
||||
}
|
||||
|
||||
@ -6011,19 +6012,19 @@ BytecodeEmitter::emitBreak(PropertyName* label)
|
||||
bool
|
||||
BytecodeEmitter::emitContinue(PropertyName* label)
|
||||
{
|
||||
StmtInfoBCE* stmt = topStmt();
|
||||
StmtInfoBCE* stmt = innermostStmt();
|
||||
if (label) {
|
||||
/* Find the loop statement enclosed by the matching label. */
|
||||
StmtInfoBCE* loop = nullptr;
|
||||
while (stmt->type != StmtType::LABEL || stmt->label != label) {
|
||||
if (stmt->isLoop())
|
||||
loop = stmt;
|
||||
stmt = stmt->down;
|
||||
stmt = stmt->enclosing;
|
||||
}
|
||||
stmt = loop;
|
||||
} else {
|
||||
while (!stmt->isLoop())
|
||||
stmt = stmt->down;
|
||||
stmt = stmt->enclosing;
|
||||
}
|
||||
|
||||
return emitGoto(stmt, &stmt->continues, SRC_CONTINUE);
|
||||
@ -6032,7 +6033,7 @@ BytecodeEmitter::emitContinue(PropertyName* label)
|
||||
bool
|
||||
BytecodeEmitter::inTryBlockWithFinally()
|
||||
{
|
||||
for (StmtInfoBCE* stmt = topStmt(); stmt; stmt = stmt->down) {
|
||||
for (StmtInfoBCE* stmt = innermostStmt(); stmt; stmt = stmt->enclosing) {
|
||||
if (stmt->type == StmtType::FINALLY)
|
||||
return true;
|
||||
}
|
||||
@ -6372,13 +6373,13 @@ BytecodeEmitter::emitStatement(ParseNode* pn)
|
||||
|
||||
/*
|
||||
* Don't eliminate apparently useless expressions if they are
|
||||
* labeled expression statements. The pc->topStmt->update test
|
||||
* labeled expression statements. The innermostStmt()->update test
|
||||
* catches the case where we are nesting in emitTree for a labeled
|
||||
* compound statement.
|
||||
*/
|
||||
if (topStmt() &&
|
||||
topStmt()->type == StmtType::LABEL &&
|
||||
topStmt()->update >= offset())
|
||||
if (innermostStmt() &&
|
||||
innermostStmt()->type == StmtType::LABEL &&
|
||||
innermostStmt()->update >= offset())
|
||||
{
|
||||
useful = true;
|
||||
}
|
||||
@ -8126,7 +8127,7 @@ bool
|
||||
BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset)
|
||||
{
|
||||
if (!SN_REPRESENTABLE_OFFSET(offset)) {
|
||||
ReportStatementTooLarge(parser->tokenStream, topStmt());
|
||||
ReportStatementTooLarge(parser->tokenStream, innermostStmt());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -219,8 +219,8 @@ struct BytecodeEmitter
|
||||
bool init();
|
||||
bool updateLocalsToFrameSlots();
|
||||
|
||||
StmtInfoBCE* topStmt() const { return stmtStack.top(); }
|
||||
StmtInfoBCE* topScopeStmt() const { return stmtStack.topScopal(); }
|
||||
StmtInfoBCE* innermostStmt() const { return stmtStack.innermost(); }
|
||||
StmtInfoBCE* innermostScopeStmt() const { return stmtStack.innermostScopal(); }
|
||||
|
||||
bool isAliasedName(ParseNode* pn);
|
||||
|
||||
|
@ -1284,8 +1284,8 @@ LexicalLookup(ContextT* ct, HandleAtom atom, StmtInfoPC* stmt = nullptr)
|
||||
RootedId id(ct->sc->context, AtomToId(atom));
|
||||
|
||||
if (!stmt)
|
||||
stmt = ct->topScopeStmt();
|
||||
for (; stmt; stmt = stmt->downScope) {
|
||||
stmt = ct->innermostScopeStmt();
|
||||
for (; stmt; stmt = stmt->enclosingScope) {
|
||||
/*
|
||||
* With-statements introduce dynamic bindings. Since dynamic bindings
|
||||
* can potentially override any static bindings introduced by statements
|
||||
@ -3141,11 +3141,12 @@ template <typename ParseHandler>
|
||||
static void
|
||||
AccumulateBlockScopeDepth(ParseContext<ParseHandler>* pc)
|
||||
{
|
||||
uint32_t innerDepth = pc->topStmt()->innerBlockScopeDepth;
|
||||
StmtInfoPC* outer = pc->topStmt()->down;
|
||||
StmtInfoPC* stmt = pc->innermostStmt();
|
||||
uint32_t innerDepth = stmt->innerBlockScopeDepth;
|
||||
StmtInfoPC* outer = stmt->enclosing;
|
||||
|
||||
if (pc->topStmt()->isBlockScope)
|
||||
innerDepth += pc->topStmt()->staticScope->template as<StaticBlockObject>().numVariables();
|
||||
if (stmt->isBlockScope)
|
||||
innerDepth += stmt->staticScope->template as<StaticBlockObject>().numVariables();
|
||||
|
||||
if (outer) {
|
||||
if (outer->innerBlockScopeDepth < innerDepth)
|
||||
@ -3175,7 +3176,7 @@ Parser<ParseHandler>::AutoPushStmtInfoPC::AutoPushStmtInfoPC(Parser<ParseHandler
|
||||
{
|
||||
stmt_.blockid = parser.pc->blockid();
|
||||
NestedScopeObject* enclosing = nullptr;
|
||||
if (StmtInfoPC* stmt = parser.pc->topScopeStmt())
|
||||
if (StmtInfoPC* stmt = parser.pc->innermostScopeStmt())
|
||||
enclosing = stmt->staticScope;
|
||||
staticScope.initEnclosingNestedScopeFromParser(enclosing);
|
||||
parser.pc->stmtStack.pushNestedScope(&stmt_, type, staticScope);
|
||||
@ -3192,7 +3193,7 @@ Parser<ParseHandler>::AutoPushStmtInfoPC::~AutoPushStmtInfoPC()
|
||||
ParseContext<ParseHandler>* pc = parser_.pc;
|
||||
TokenStream& ts = parser_.tokenStream;
|
||||
|
||||
MOZ_ASSERT(pc->topStmt() == &stmt_);
|
||||
MOZ_ASSERT(pc->innermostStmt() == &stmt_);
|
||||
RootedNestedScopeObject scopeObj(parser_.context, stmt_.staticScope);
|
||||
|
||||
AccumulateBlockScopeDepth(pc);
|
||||
@ -3217,10 +3218,10 @@ Parser<ParseHandler>::AutoPushStmtInfoPC::generateBlockId()
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::AutoPushStmtInfoPC::makeTopLexicalScope(StaticBlockObject& blockObj)
|
||||
Parser<ParseHandler>::AutoPushStmtInfoPC::makeInnermostLexicalScope(StaticBlockObject& blockObj)
|
||||
{
|
||||
MOZ_ASSERT(parser_.pc->stmtStack.top() == &stmt_);
|
||||
parser_.pc->stmtStack.makeTopLexicalScope(blockObj);
|
||||
MOZ_ASSERT(parser_.pc->stmtStack.innermost() == &stmt_);
|
||||
parser_.pc->stmtStack.makeInnermostLexicalScope(blockObj);
|
||||
return generateBlockId();
|
||||
}
|
||||
|
||||
@ -3228,8 +3229,8 @@ template <typename ParseHandler>
|
||||
static inline bool
|
||||
OuterLet(ParseContext<ParseHandler>* pc, StmtInfoPC* stmt, HandleAtom atom)
|
||||
{
|
||||
while (stmt->downScope) {
|
||||
stmt = LexicalLookup(pc, atom, stmt->downScope);
|
||||
while (stmt->enclosingScope) {
|
||||
stmt = LexicalLookup(pc, atom, stmt->enclosingScope);
|
||||
if (!stmt)
|
||||
return false;
|
||||
if (stmt->type == StmtType::BLOCK)
|
||||
@ -3677,7 +3678,7 @@ Parser<ParseHandler>::pushLexicalScope(HandleStaticBlockObject blockObj,
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
if (!stmt.makeTopLexicalScope(*blockObj))
|
||||
if (!stmt.makeInnermostLexicalScope(*blockObj))
|
||||
return null();
|
||||
handler.setBlockId(pn, stmt->blockid);
|
||||
return pn;
|
||||
@ -4065,7 +4066,7 @@ Parser<FullParseHandler>::checkAndPrepareLexical(bool isConst, const TokenPos& e
|
||||
* enclosing maybe-scope StmtInfoPC isn't yet a scope statement) then
|
||||
* we also need to set pc->blockNode to be our PNK_LEXICALSCOPE.
|
||||
*/
|
||||
StmtInfoPC* stmt = pc->topStmt();
|
||||
StmtInfoPC* stmt = pc->innermostStmt();
|
||||
if (stmt && (!stmt->maybeScope() || stmt->isForLetBlock)) {
|
||||
reportWithOffset(ParseError, false, errorPos.begin, JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,
|
||||
isConst ? "const" : "lexical");
|
||||
@ -4086,7 +4087,7 @@ Parser<FullParseHandler>::checkAndPrepareLexical(bool isConst, const TokenPos& e
|
||||
* conflicting slots. Forbid top-level let declarations to
|
||||
* prevent such conflicts from ever occurring.
|
||||
*/
|
||||
bool isGlobal = !pc->sc->isFunctionBox() && stmt == pc->topScopeStmt();
|
||||
bool isGlobal = !pc->sc->isFunctionBox() && stmt == pc->innermostScopeStmt();
|
||||
if (options().selfHostingMode && isGlobal) {
|
||||
report(ParseError, false, null(), JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL,
|
||||
isConst ? "'const'" : "'let'");
|
||||
@ -4097,14 +4098,14 @@ Parser<FullParseHandler>::checkAndPrepareLexical(bool isConst, const TokenPos& e
|
||||
|
||||
if (stmt->isBlockScope) {
|
||||
// Nothing to do, the top statement already has a block scope.
|
||||
MOZ_ASSERT(pc->topScopeStmt() == stmt);
|
||||
MOZ_ASSERT(pc->innermostScopeStmt() == stmt);
|
||||
} else {
|
||||
/* Convert the block statement into a scope statement. */
|
||||
StaticBlockObject* blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return false;
|
||||
NestedScopeObject* enclosing = nullptr;
|
||||
if (StmtInfoPC* stmt = pc->topScopeStmt())
|
||||
if (StmtInfoPC* stmt = pc->innermostScopeStmt())
|
||||
enclosing = stmt->staticScope;
|
||||
blockObj->initEnclosingNestedScopeFromParser(enclosing);
|
||||
|
||||
@ -4118,7 +4119,7 @@ Parser<FullParseHandler>::checkAndPrepareLexical(bool isConst, const TokenPos& e
|
||||
* catch block (catch is a lexical scope by definition).
|
||||
*/
|
||||
MOZ_ASSERT(stmt->canBeBlockScope() && stmt->type != StmtType::CATCH);
|
||||
pc->stmtStack.makeTopLexicalScope(*blockObj);
|
||||
pc->stmtStack.makeInnermostLexicalScope(*blockObj);
|
||||
|
||||
#ifdef DEBUG
|
||||
ParseNode* tmp = pc->blockNode;
|
||||
@ -4138,7 +4139,7 @@ static StaticBlockObject*
|
||||
CurrentLexicalStaticBlock(ParseContext<FullParseHandler>* pc)
|
||||
{
|
||||
return pc->atBodyLevel() ? nullptr :
|
||||
&pc->topStmt()->staticScope->as<StaticBlockObject>();
|
||||
&pc->innermostStmt()->staticScope->as<StaticBlockObject>();
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -5279,7 +5280,7 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
||||
|
||||
AutoPushStmtInfoPC stmtInfo(*this, StmtType::SWITCH);
|
||||
|
||||
if (!GenerateBlockId(tokenStream, pc, pc->topStmt()->blockid))
|
||||
if (!GenerateBlockId(tokenStream, pc, pc->innermostStmt()->blockid))
|
||||
return null();
|
||||
|
||||
Node caseList = handler.newStatementList(pc->blockid(), pos());
|
||||
@ -5405,9 +5406,9 @@ Parser<ParseHandler>::continueStatement(YieldHandling yieldHandling)
|
||||
if (!matchLabel(yieldHandling, &label))
|
||||
return null();
|
||||
|
||||
StmtInfoPC* stmt = pc->topStmt();
|
||||
StmtInfoPC* stmt = pc->innermostStmt();
|
||||
if (label) {
|
||||
for (StmtInfoPC* stmt2 = nullptr; ; stmt = stmt->down) {
|
||||
for (StmtInfoPC* stmt2 = nullptr; ; stmt = stmt->enclosing) {
|
||||
if (!stmt) {
|
||||
report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
|
||||
return null();
|
||||
@ -5425,7 +5426,7 @@ Parser<ParseHandler>::continueStatement(YieldHandling yieldHandling)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (; ; stmt = stmt->down) {
|
||||
for (; ; stmt = stmt->enclosing) {
|
||||
if (!stmt) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_CONTINUE);
|
||||
return null();
|
||||
@ -5451,9 +5452,9 @@ Parser<ParseHandler>::breakStatement(YieldHandling yieldHandling)
|
||||
RootedPropertyName label(context);
|
||||
if (!matchLabel(yieldHandling, &label))
|
||||
return null();
|
||||
StmtInfoPC* stmt = pc->topStmt();
|
||||
StmtInfoPC* stmt = pc->innermostStmt();
|
||||
if (label) {
|
||||
for (; ; stmt = stmt->down) {
|
||||
for (; ; stmt = stmt->enclosing) {
|
||||
if (!stmt) {
|
||||
report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
|
||||
return null();
|
||||
@ -5462,7 +5463,7 @@ Parser<ParseHandler>::breakStatement(YieldHandling yieldHandling)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (; ; stmt = stmt->down) {
|
||||
for (; ; stmt = stmt->enclosing) {
|
||||
if (!stmt) {
|
||||
report(ParseError, false, null(), JSMSG_TOUGH_BREAK);
|
||||
return null();
|
||||
@ -5744,7 +5745,7 @@ Parser<ParseHandler>::labeledStatement(YieldHandling yieldHandling)
|
||||
{
|
||||
uint32_t begin = pos().begin;
|
||||
RootedPropertyName label(context, tokenStream.currentName());
|
||||
for (StmtInfoPC* stmt = pc->topStmt(); stmt; stmt = stmt->down) {
|
||||
for (StmtInfoPC* stmt = pc->innermostStmt(); stmt; stmt = stmt->enclosing) {
|
||||
if (stmt->type == StmtType::LABEL && stmt->label == label) {
|
||||
report(ParseError, false, null(), JSMSG_DUPLICATE_LABEL);
|
||||
return null();
|
||||
@ -5874,7 +5875,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
* an intentional change that anticipates ECMA Ed. 4.
|
||||
*/
|
||||
data.initLexical(HoistVars,
|
||||
&pc->topScopeStmt()->staticScope->template as<StaticBlockObject>(),
|
||||
&stmtInfo->staticScope->template as<StaticBlockObject>(),
|
||||
JSMSG_TOO_MANY_CATCH_VARS);
|
||||
MOZ_ASSERT(data.let.blockObj);
|
||||
|
||||
@ -7043,7 +7044,7 @@ LegacyCompExprTransplanter::transplant(ParseNode* pn)
|
||||
RootedAtom atom(parser->context, pn->pn_atom);
|
||||
#ifdef DEBUG
|
||||
StmtInfoPC* stmt = LexicalLookup(pc, atom);
|
||||
MOZ_ASSERT(!stmt || stmt != pc->topStmt());
|
||||
MOZ_ASSERT(!stmt || stmt != pc->innermostStmt());
|
||||
#endif
|
||||
if (isGenexp && !dn->isOp(JSOP_CALLEE)) {
|
||||
MOZ_ASSERT_IF(!pc->sc->isDotVariable(atom), !pc->decls().lookupFirst(atom));
|
||||
@ -7152,7 +7153,7 @@ template <typename ParseHandler>
|
||||
static unsigned
|
||||
LegacyComprehensionHeadBlockScopeDepth(ParseContext<ParseHandler>* pc)
|
||||
{
|
||||
return pc->topStmt() ? pc->topStmt()->innerBlockScopeDepth : pc->blockScopeDepth;
|
||||
return pc->innermostStmt() ? pc->innermostStmt()->innerBlockScopeDepth : pc->blockScopeDepth;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -7242,9 +7243,10 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode* bodyExpr, unsigned
|
||||
if (!transplanter.transplant(bodyExpr))
|
||||
return null();
|
||||
|
||||
MOZ_ASSERT(pc->topScopeStmt() && pc->topScopeStmt()->staticScope == pn->pn_objbox->object);
|
||||
MOZ_ASSERT(pc->innermostScopeStmt() &&
|
||||
pc->innermostScopeStmt()->staticScope == pn->pn_objbox->object);
|
||||
data.initLexical(HoistVars,
|
||||
&pc->topScopeStmt()->staticScope->as<StaticBlockObject>(),
|
||||
&pc->innermostScopeStmt()->staticScope->as<StaticBlockObject>(),
|
||||
JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
|
||||
while (true) {
|
||||
@ -7418,7 +7420,7 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode* bodyExpr, unsigned
|
||||
|
||||
*pnp = bodyStmt;
|
||||
|
||||
pc->topStmt()->innerBlockScopeDepth += innerBlockScopeDepth;
|
||||
pc->innermostStmt()->innerBlockScopeDepth += innerBlockScopeDepth;
|
||||
|
||||
handler.setEndPosition(pn, pos().end);
|
||||
|
||||
|
@ -25,8 +25,8 @@ namespace frontend {
|
||||
|
||||
struct StmtInfoPC : public StmtInfoBase
|
||||
{
|
||||
StmtInfoPC* down; /* info for enclosing statement */
|
||||
StmtInfoPC* downScope; /* next enclosing lexical scope */
|
||||
StmtInfoPC* enclosing;
|
||||
StmtInfoPC* enclosingScope;
|
||||
|
||||
uint32_t blockid; /* for simplified dominance computation */
|
||||
uint32_t innerBlockScopeDepth; /* maximum depth of nested block scopes, in slots */
|
||||
@ -284,10 +284,10 @@ struct ParseContext : public GenericParseContext
|
||||
|
||||
bool init(TokenStream& ts);
|
||||
|
||||
unsigned blockid() { return stmtStack.top() ? stmtStack.top()->blockid : bodyid; }
|
||||
unsigned blockid() { return stmtStack.innermost() ? stmtStack.innermost()->blockid : bodyid; }
|
||||
|
||||
StmtInfoPC* topStmt() const { return stmtStack.top(); }
|
||||
StmtInfoPC* topScopeStmt() const { return stmtStack.topScopal(); }
|
||||
StmtInfoPC* innermostStmt() const { return stmtStack.innermost(); }
|
||||
StmtInfoPC* innermostScopeStmt() const { return stmtStack.innermostScopal(); }
|
||||
|
||||
// True if we are at the topmost level of a entire script or function body.
|
||||
// For example, while parsing this code we would encounter f1 and f2 at
|
||||
@ -296,8 +296,8 @@ struct ParseContext : public GenericParseContext
|
||||
// function f1() { function f2() { } }
|
||||
// if (cond) { function f3() { if (cond) { function f4() { } } } }
|
||||
//
|
||||
bool atBodyLevel() { return !topStmt(); }
|
||||
bool atGlobalLevel() { return atBodyLevel() && !sc->isFunctionBox() && !topScopeStmt(); }
|
||||
bool atBodyLevel() { return !innermostStmt(); }
|
||||
bool atGlobalLevel() { return atBodyLevel() && !sc->isFunctionBox() && !innermostScopeStmt(); }
|
||||
|
||||
// True if this is the ParseContext for the body of a function created by
|
||||
// the Function constructor.
|
||||
@ -354,7 +354,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
~AutoPushStmtInfoPC();
|
||||
|
||||
bool generateBlockId();
|
||||
bool makeTopLexicalScope(StaticBlockObject& blockObj);
|
||||
bool makeInnermostLexicalScope(StaticBlockObject& blockObj);
|
||||
|
||||
StmtInfoPC& operator*() { return stmt_; }
|
||||
StmtInfoPC* operator->() { return &stmt_; }
|
||||
|
@ -555,24 +555,19 @@ template <class StmtInfo>
|
||||
class MOZ_STACK_CLASS StmtInfoStack
|
||||
{
|
||||
// Top of the stack.
|
||||
StmtInfo* topStmt_;
|
||||
StmtInfo* innermostStmt_;
|
||||
|
||||
// Top scope statement with a nested scope.
|
||||
StmtInfo* topScopeStmt_;
|
||||
StmtInfo* innermostScopeStmt_;
|
||||
|
||||
public:
|
||||
explicit StmtInfoStack(ExclusiveContext* cx)
|
||||
: topStmt_(nullptr),
|
||||
topScopeStmt_(nullptr)
|
||||
: innermostStmt_(nullptr),
|
||||
innermostScopeStmt_(nullptr)
|
||||
{ }
|
||||
|
||||
StmtInfo* top() const { return topStmt_; }
|
||||
StmtInfo* topScopal() const { return topScopeStmt_; }
|
||||
NestedScopeObject* topStaticScope() const {
|
||||
if (!topScopal())
|
||||
return nullptr;
|
||||
return topScopal()->staticScope;
|
||||
}
|
||||
StmtInfo* innermost() const { return innermostStmt_; }
|
||||
StmtInfo* innermostScopal() const { return innermostScopeStmt_; }
|
||||
|
||||
void push(StmtInfo* stmt, StmtType type) {
|
||||
stmt->type = type;
|
||||
@ -580,36 +575,36 @@ class MOZ_STACK_CLASS StmtInfoStack
|
||||
stmt->isForLetBlock = false;
|
||||
stmt->label = nullptr;
|
||||
stmt->staticScope = nullptr;
|
||||
stmt->down = topStmt_;
|
||||
stmt->downScope = nullptr;
|
||||
topStmt_ = stmt;
|
||||
stmt->enclosing = innermostStmt_;
|
||||
stmt->enclosingScope = nullptr;
|
||||
innermostStmt_ = stmt;
|
||||
}
|
||||
|
||||
void pushNestedScope(StmtInfo* stmt, StmtType type, NestedScopeObject& staticScope) {
|
||||
push(stmt, type);
|
||||
linkAsTopScopal(stmt, staticScope);
|
||||
linkAsInnermostScopal(stmt, staticScope);
|
||||
}
|
||||
|
||||
void pop() {
|
||||
StmtInfo* stmt = topStmt_;
|
||||
topStmt_ = stmt->down;
|
||||
StmtInfo* stmt = innermostStmt_;
|
||||
innermostStmt_ = stmt->enclosing;
|
||||
if (stmt->linksScope())
|
||||
topScopeStmt_ = stmt->downScope;
|
||||
innermostScopeStmt_ = stmt->enclosingScope;
|
||||
}
|
||||
|
||||
void linkAsTopScopal(StmtInfo* stmt, NestedScopeObject& staticScope) {
|
||||
MOZ_ASSERT(stmt != topScopal());
|
||||
MOZ_ASSERT(!stmt->downScope);
|
||||
stmt->downScope = topScopeStmt_;
|
||||
topScopeStmt_ = stmt;
|
||||
void linkAsInnermostScopal(StmtInfo* stmt, NestedScopeObject& staticScope) {
|
||||
MOZ_ASSERT(stmt != innermostScopal());
|
||||
MOZ_ASSERT(!stmt->enclosingScope);
|
||||
stmt->enclosingScope = innermostScopeStmt_;
|
||||
innermostScopeStmt_ = stmt;
|
||||
stmt->staticScope = &staticScope;
|
||||
}
|
||||
|
||||
void makeTopLexicalScope(StaticBlockObject& blockObj) {
|
||||
MOZ_ASSERT(!topStmt_->isBlockScope);
|
||||
MOZ_ASSERT(topStmt_->canBeBlockScope());
|
||||
topStmt_->isBlockScope = true;
|
||||
linkAsTopScopal(topStmt_, blockObj);
|
||||
void makeInnermostLexicalScope(StaticBlockObject& blockObj) {
|
||||
MOZ_ASSERT(!innermostStmt_->isBlockScope);
|
||||
MOZ_ASSERT(innermostStmt_->canBeBlockScope());
|
||||
innermostStmt_->isBlockScope = true;
|
||||
linkAsInnermostScopal(innermostStmt_, blockObj);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user