Bug 883333, part 15 - Add StatementList operations to the ParseHandler protocol. r=Waldo.

--HG--
extra : rebase_source : d5e801fcd5c2f53bcc670534c53502c4219d176d
This commit is contained in:
Jason Orendorff 2013-06-21 08:18:01 -05:00
parent b57a42ad25
commit 699ca9539b
5 changed files with 50 additions and 54 deletions

View File

@ -192,6 +192,33 @@ class FullParseHandler
return new_<TernaryNode>(kind, op, first, second, third);
}
ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) {
ParseNode *pn = new_<ListNode>(PNK_STATEMENTLIST, pos);
if (pn)
pn->pn_blockid = blockid;
return pn;
}
template <typename PC>
void addStatementToList(ParseNode *list, ParseNode *stmt, PC *pc) {
JS_ASSERT(list->isKind(PNK_STATEMENTLIST));
if (stmt->isKind(PNK_FUNCTION)) {
if (pc->atBodyLevel()) {
// PNX_FUNCDEFS notifies the emitter that the block contains
// body-level function definitions that should be processed
// before the rest of nodes.
list->pn_xflags |= PNX_FUNCDEFS;
} else {
// General deoptimization was done in Parser::functionDef.
JS_ASSERT_IF(pc->sc->isFunctionBox(),
pc->sc->asFunctionBox()->hasExtensibleScope());
}
}
list->append(stmt);
}
ParseNode *newEmptyStatement(const TokenPos &pos) {
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) NULL);
}

View File

@ -927,10 +927,15 @@ struct TernaryNode : public ParseNode
struct ListNode : public ParseNode
{
ListNode(ParseNodeKind kind, JSOp op, ParseNode *kid)
: ParseNode(kind, op, PN_LIST)
ListNode(ParseNodeKind kind, const TokenPos &pos)
: ParseNode(kind, JSOP_NOP, PN_LIST, pos)
{
makeEmpty();
}
ListNode(ParseNodeKind kind, JSOp op, ParseNode *kid)
: ParseNode(kind, op, PN_LIST, kid->pn_pos)
{
pn_pos = kid->pn_pos;
initList(kid);
}

View File

@ -1718,17 +1718,16 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
return false;
}
/*
* As a SpiderMonkey-specific extension, non-body-level function
* statements (e.g., functions in an "if" or "while" block) are
* dynamically bound when control flow reaches the statement. The
* emitter normally emits functions in two passes (see PNK_ARGSBODY).
*/
if (bodyLevel) {
JS_ASSERT(pn->functionIsHoisted());
JS_ASSERT_IF(pc->sc->isFunctionBox(), !pn->pn_cookie.isFree());
JS_ASSERT_IF(!pc->sc->isFunctionBox(), pn->pn_cookie.isFree());
} else {
/*
* As a SpiderMonkey-specific extension, non-body-level function
* statements (e.g., functions in an "if" or "while" block) are
* dynamically bound when control flow reaches the statement.
*/
JS_ASSERT(!pc->sc->strict);
JS_ASSERT(pn->pn_cookie.isFree());
if (pc->sc->isFunctionBox()) {
@ -2450,40 +2449,10 @@ Parser<ParseHandler>::maybeParseDirective(Node pn, bool *cont)
return true;
}
template <>
void
Parser<FullParseHandler>::addStatementToList(ParseNode *pn, ParseNode *kid)
{
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
if (kid->isKind(PNK_FUNCTION)) {
/*
* PNX_FUNCDEFS notifies the emitter that the block contains body-
* level function definitions that should be processed before the
* rest of nodes.
*/
if (pc->atBodyLevel()) {
pn->pn_xflags |= PNX_FUNCDEFS;
} else {
/* General deoptimization was done in functionDef. */
JS_ASSERT_IF(pc->sc->isFunctionBox(), pc->sc->asFunctionBox()->hasExtensibleScope());
}
}
pn->append(kid);
pn->pn_pos.end = kid->pn_pos.end;
}
template <>
void
Parser<SyntaxParseHandler>::addStatementToList(Node pn, Node kid)
{
}
/*
* Parse the statements in a block, creating a TOK_LC node that lists the
* statements' trees. If called from block-parsing code, the caller must
* match { before and } after.
* Parse the statements in a block, creating a StatementList node that lists
* the statements. If called from block-parsing code, the caller must match
* '{' before and '}' after.
*/
template <typename ParseHandler>
typename ParseHandler::Node
@ -2491,10 +2460,9 @@ Parser<ParseHandler>::statements()
{
JS_CHECK_RECURSION(context, return null());
Node pn = handler.newList(PNK_STATEMENTLIST);
Node pn = handler.newStatementList(pc->blockid(), pos());
if (!pn)
return null();
handler.setBlockId(pn, pc->blockid());
Node saveBlock = pc->blockNode;
pc->blockNode = pn;
@ -2522,7 +2490,7 @@ Parser<ParseHandler>::statements()
return null();
}
addStatementToList(pn, next);
handler.addStatementToList(pn, next, pc);
}
/*
@ -2533,8 +2501,6 @@ Parser<ParseHandler>::statements()
if (pc->blockNode != pn)
pn = pc->blockNode;
pc->blockNode = saveBlock;
handler.setEndPosition(pn, pos().end);
return pn;
}
@ -4255,11 +4221,9 @@ Parser<ParseHandler>::switchStatement()
if (!GenerateBlockId(pc, pc->topStmt->blockid))
return null();
/* The default case has pn_left == NULL */
Node caseList = handler.newList(PNK_STATEMENTLIST);
Node caseList = handler.newStatementList(pc->blockid(), pos());
if (!caseList)
return null();
handler.setBlockId(caseList, pc->blockid());
Node saveBlock = pc->blockNode;
pc->blockNode = caseList;
@ -4277,7 +4241,7 @@ Parser<ParseHandler>::switchStatement()
return null();
}
seenDefault = true;
caseExpr = null();
caseExpr = null(); // The default case has pn_left == NULL.
break;
case TOK_CASE:
@ -4296,10 +4260,9 @@ Parser<ParseHandler>::switchStatement()
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
Node body = handler.newList(PNK_STATEMENTLIST);
Node body = handler.newStatementList(pc->blockid(), pos());
if (!body)
return null();
handler.setBlockId(body, pc->blockid());
while ((tt = tokenStream.peekToken(TSF_OPERAND)) != TOK_RC &&
tt != TOK_CASE && tt != TOK_DEFAULT) {

View File

@ -486,7 +486,6 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
bool setAssignmentLhsOps(Node pn, JSOp op);
bool matchInOrOf(bool *isForOfp);
void addStatementToList(Node pn, Node kid);
bool checkFunctionArguments();
bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom);
bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind,

View File

@ -100,6 +100,8 @@ class SyntaxParseHandler
return NodeGeneric;
}
Node newStatementList(unsigned blockid, const TokenPos &pos) { return NodeGeneric; }
void addStatementToList(Node list, Node stmt, ParseContext<SyntaxParseHandler> *pc) {}
Node newEmptyStatement(const TokenPos &pos) { return NodeGeneric; }
Node newExprStatement(Node expr, uint32_t end) {