Bug 701620 - Split up PNK_LC into PNK_STATEMENTLIST and PNK_XMLCURLYEXPR. r=jorendorff

--HG--
extra : rebase_source : 4d781725639c6c94da53fd33fcfcedf221634a35
This commit is contained in:
Jeff Walden 2011-11-11 18:05:43 -08:00
parent 2a586af759
commit 3c5ca419bc
6 changed files with 65 additions and 57 deletions

View File

@ -1454,7 +1454,8 @@ EmitTraceOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
* instruction. nextpn is often a block, in which case the next
* instruction typically comes from the first statement inside.
*/
if (nextpn->isKind(PNK_LC) && nextpn->isArity(PN_LIST) && nextpn->pn_head)
JS_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
nextpn = nextpn->pn_head;
if (!UpdateLineNumberNotes(cx, bce, nextpn->pn_pos.begin.lineno))
return -1;
@ -3345,7 +3346,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
#if !JS_HAS_BLOCK_SCOPE
PushStatement(bce, &stmtInfo, STMT_SWITCH, top);
#else
if (pn2->isKind(PNK_LC)) {
if (pn2->isKind(PNK_STATEMENTLIST)) {
PushStatement(bce, &stmtInfo, STMT_SWITCH, top);
} else {
/* Re-push the switch's statement info record. */
@ -5319,7 +5320,7 @@ EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
JS_ASSERT(pn->pn_count != 0);
ParseNode *pn2 = pn->pn_head;
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return false;
if (!EmitTree(cx, bce, pn2))
return false;
@ -5328,11 +5329,11 @@ EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
uint32 i;
for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) {
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return false;
if (!EmitTree(cx, bce, pn2))
return false;
if ((i & 1) && pn2->isKind(PNK_LC)) {
if ((i & 1) && pn2->isKind(PNK_XMLCURLYEXPR)) {
if (Emit1(cx, bce, JSOP_TOATTRVAL) < 0)
return false;
}
@ -5788,7 +5789,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/*
* This second pass is needed to emit JSOP_NOP with a source note
* for the already-emitted function definition prolog opcode. See
* comments in the PNK_LC case.
* comments in the PNK_STATEMENTLIST case.
*/
JS_ASSERT(pn->isOp(JSOP_NOP));
JS_ASSERT(bce->inFunction());
@ -6176,18 +6177,18 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
#endif
case PNK_LC:
{
#if JS_HAS_XML_SUPPORT
if (pn->isArity(PN_UNARY)) {
case PNK_XMLCURLYEXPR:
JS_ASSERT(pn->isArity(PN_UNARY));
if (!EmitTree(cx, bce, pn->pn_kid))
return JS_FALSE;
if (Emit1(cx, bce, pn->getOp()) < 0)
return JS_FALSE;
break;
}
#endif
case PNK_STATEMENTLIST:
{
JS_ASSERT(pn->isArity(PN_LIST));
noteIndex = -1;
@ -6355,9 +6356,9 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return JS_FALSE;
pn2 = pn->expr();
noteType = (pn2->isKind(PNK_LC) ||
noteType = (pn2->isKind(PNK_STATEMENTLIST) ||
(pn2->isKind(PNK_LEXICALSCOPE) &&
pn2->expr()->isKind(PNK_LC)))
pn2->expr()->isKind(PNK_STATEMENTLIST)))
? SRC_LABELBRACE
: SRC_LABEL;
noteIndex = NewSrcNote2(cx, bce, noteType, ptrdiff_t(index));
@ -7291,7 +7292,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return JS_FALSE;
if (!EmitTree(cx, bce, pn2))
return JS_FALSE;
@ -7330,7 +7331,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (pn->isArity(PN_LIST)) {
JS_ASSERT(pn->pn_count != 0);
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return JS_FALSE;
if (!EmitTree(cx, bce, pn2))
return JS_FALSE;

View File

@ -594,7 +594,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
* NB: pn must be a PNK_IF as PNK_HOOK can never have a null kid
* or an empty statement for a child.
*/
pn->setKind(PNK_LC);
pn->setKind(PNK_STATEMENTLIST);
pn->setArity(PN_LIST);
pn->makeEmpty();
}

View File

@ -80,7 +80,8 @@ enum ParseNodeKind {
PNK_DOT,
PNK_LB,
PNK_RB,
PNK_LC,
PNK_STATEMENTLIST,
PNK_XMLCURLYEXPR,
PNK_RC,
PNK_LP,
PNK_RP,
@ -205,30 +206,33 @@ enum ParseNodeKind {
* create the function object at parse (not emit)
* time to specialize arg and var bytecodes early.
* pn_body: PNK_UPVARS if the function's source body
* depends on outer names, else PNK_ARGSBODY
* if formal parameters, else PNK_LC node for
* function body statements, else PNK_RETURN
* for expression closure, else PNK_SEQ for
* expression closure with destructured
* formal parameters
* depends on outer names,
* PNK_ARGSBODY if formal parameters,
* PNK_STATEMENTLIST node for function body
* statements,
* PNK_RETURN for expression closure, or
* PNK_SEQ for expression closure with
* destructured formal parameters
* pn_cookie: static level and var index for function
* pn_dflags: PND_* definition/use flags (see below)
* pn_blockid: block id number
* PNK_ARGSBODY list list of formal parameters followed by PNK_LC node
* for function body statements as final element
* PNK_ARGSBODY list list of formal parameters followed by
* PNK_STATEMENTLIST node for function body
* statements as final element
* pn_count: 1 + number of formal parameters
* PNK_UPVARS nameset pn_names: lexical dependencies (js::Definitions)
* defined in enclosing scopes, or ultimately not
* defined (free variables, either global property
* references or reference errors).
* pn_tree: PNK_ARGSBODY or PNK_LC node
* pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
*
* <Statements>
* PNK_LC list pn_head: list of pn_count statements
* PNK_STATEMENTLIST list pn_head: list of pn_count statements
* PNK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
* In body of a comprehension or desugared generator
* expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
* or (if the push was optimized away) empty PNK_LC.
* or (if the push was optimized away) empty
* PNK_STATEMENTLIST.
* PNK_SWITCH binary pn_left: discriminant
* pn_right: list of PNK_CASE nodes, with at most one
* PNK_DEFAULT node, or if there are let bindings
@ -236,9 +240,11 @@ enum ParseNodeKind {
* PNK_LEXICALSCOPE node that contains the list of
* PNK_CASE nodes.
* PNK_CASE, binary pn_left: case expr
* pn_right: PNK_LC node for this case's statements
* pn_right: PNK_STATEMENTLIST node for this case's
* statements
* PNK_DEFAULT binary pn_left: null
* pn_right: PNK_LC node for this default's statements
* pn_right: PNK_STATEMENTLIST node for this default's
* statements
* pn_val: constant value if lookup or table switch
* PNK_WHILE binary pn_left: cond, pn_right: body
* PNK_DOWHILE binary pn_left: body, pn_right: cond
@ -417,7 +423,7 @@ enum ParseNodeKind {
* PNK_XMLPI nullary pn_pitarget: XML processing instruction target
* pn_pidata: XML PI data, or null if no data
* PNK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string
* PNK_LC unary {expr} in XML tag or content; pn_kid is expr
* PNK_XMLCURLYEXPR unary {expr} in XML tag or content; pn_kid is expr
*
* So an XML tag with no {expr} and three attributes is a list with the form:
*
@ -432,7 +438,7 @@ enum ParseNodeKind {
* ((name1 {expr1}) (name2 {expr2} name3) {expr3})
*
* where () bracket a list with elements separated by spaces, and {expr} is a
* PNK_LC unary node with expr as its kid.
* PNK_XMLCURLYEXPR unary node with expr as its kid.
*
* Thus, the attribute name/value pairs occupy successive odd and even list
* locations, where pn_head is the PNK_XMLNAME node at list location 0. The

View File

@ -261,7 +261,7 @@ GenerateBlockIdForStmtNode(ParseNode *pn, TreeContext *tc)
{
JS_ASSERT(tc->topStmt);
JS_ASSERT(STMT_MAYBE_SCOPE(tc->topStmt));
JS_ASSERT(pn->isKind(PNK_LC) || pn->isKind(PNK_LEXICALSCOPE));
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST) || pn->isKind(PNK_LEXICALSCOPE));
if (!GenerateBlockId(tc, tc->topStmt->blockid))
return false;
pn->pn_blockid = tc->topStmt->blockid;
@ -321,7 +321,7 @@ HasFinalReturn(ParseNode *pn)
uintN rv, rv2, hasDefault;
switch (pn->getKind()) {
case PNK_LC:
case PNK_STATEMENTLIST:
if (!pn->pn_head)
return ENDS_IN_OTHER;
return HasFinalReturn(pn->last());
@ -368,7 +368,7 @@ HasFinalReturn(ParseNode *pn)
if (pn2->isKind(PNK_DEFAULT))
hasDefault = ENDS_IN_RETURN;
pn3 = pn2->pn_right;
JS_ASSERT(pn3->isKind(PNK_LC));
JS_ASSERT(pn3->isKind(PNK_STATEMENTLIST));
if (pn3->pn_head) {
rv2 = HasFinalReturn(pn3->last());
if (rv2 == ENDS_IN_OTHER && pn2->pn_next)
@ -1771,7 +1771,7 @@ Parser::statements()
JS_CHECK_RECURSION(context, return NULL);
ParseNode *pn = ListNode::create(PNK_LC, tc);
ParseNode *pn = ListNode::create(PNK_STATEMENTLIST, tc);
if (!pn)
return NULL;
pn->makeEmpty();
@ -2951,7 +2951,7 @@ Parser::switchStatement()
PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
/* pn2 is a list of case nodes. The default case has pn_left == NULL */
ParseNode *pn2 = ListNode::create(PNK_LC, tc);
ParseNode *pn2 = ListNode::create(PNK_STATEMENTLIST, tc);
if (!pn2)
return NULL;
pn2->makeEmpty();
@ -3003,7 +3003,7 @@ Parser::switchStatement()
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
ParseNode *pn4 = ListNode::create(PNK_LC, tc);
ParseNode *pn4 = ListNode::create(PNK_STATEMENTLIST, tc);
if (!pn4)
return NULL;
pn4->makeEmpty();
@ -3757,7 +3757,7 @@ Parser::expressionStatement()
/* Normalize empty statement to empty block for the decompiler. */
if (pn->isKind(PNK_SEMI) && !pn->pn_kid) {
pn->setKind(PNK_LC);
pn->setKind(PNK_STATEMENTLIST);
pn->setArity(PN_LIST);
pn->makeEmpty();
}
@ -6038,7 +6038,7 @@ Parser::xmlExpr(JSBool inTag)
JS_ASSERT(!tc->inStrictMode());
JS_ASSERT(tokenStream.currentToken().type == TOK_LC);
ParseNode *pn = UnaryNode::create(PNK_LC, tc);
ParseNode *pn = UnaryNode::create(PNK_XMLCURLYEXPR, tc);
if (!pn)
return NULL;
@ -6083,7 +6083,7 @@ Parser::atomNode(ParseNodeKind kind, JSOp op)
* Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
* a list of names and/or expressions, a single expression, or a single name.
* If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME. Otherwise if
* PN_UNARY, getKind() will be PNK_LC.
* PN_UNARY, getKind() will be PNK_XMLCURLYEXPR.
*/
ParseNode *
Parser::xmlNameExpr()
@ -6135,7 +6135,7 @@ Parser::xmlNameExpr()
*/
#define XML_FOLDABLE(pn) ((pn)->isArity(PN_LIST) \
? ((pn)->pn_xflags & PNX_CANTFOLD) == 0 \
: !(pn)->isKind(PNK_LC))
: !(pn)->isKind(PNK_XMLCURLYEXPR))
/*
* Parse the productions:
@ -6152,7 +6152,7 @@ Parser::xmlNameExpr()
* If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME for the case where
* XMLTagContent: XMLNameExpr. If getKind() is not PNK_XMLNAME but getArity()
* is PN_LIST, getKind() will be tagkind. If PN_UNARY, getKind() will be
* PNK_LC and we parsed exactly one expression.
* PNK_XMLCURLYEXPR and we parsed exactly one expression.
*/
ParseNode *
Parser::xmlTagContent(ParseNodeKind tagkind, JSAtom **namep)
@ -6333,7 +6333,7 @@ Parser::xmlElementOrList(JSBool allowList)
freeTree(pn);
pn = pn2;
} else {
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_LC));
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR));
pn->initList(pn2);
if (!XML_FOLDABLE(pn2))
pn->pn_xflags |= PNX_CANTFOLD;
@ -6395,7 +6395,7 @@ Parser::xmlElementOrList(JSBool allowList)
}
/* Make a TOK_XMLETAGO list with pn2 as its single child. */
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_LC));
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR));
list = ListNode::create(PNK_XMLETAGO, tc);
if (!list)
return NULL;

View File

@ -533,7 +533,7 @@ ConsiderUnbranding(FunctionBox *funbox)
pn2 = pn2->pn_tree;
if (pn2->isKind(PNK_ARGSBODY))
pn2 = pn2->last();
if (!pn2->isKind(PNK_LC))
if (!pn2->isKind(PNK_STATEMENTLIST))
returnsExpr = true;
}
#endif

View File

@ -1810,7 +1810,8 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op)
bool
ASTSerializer::statements(ParseNode *pn, NodeVector &elts)
{
JS_ASSERT(pn->isKind(PNK_LC) && pn->isArity(PN_LIST));
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
JS_ASSERT(pn->isArity(PN_LIST));
if (!elts.reserve(pn->pn_count))
return false;
@ -1860,7 +1861,7 @@ ASTSerializer::xmls(ParseNode *pn, NodeVector &elts)
bool
ASTSerializer::blockStatement(ParseNode *pn, Value *dst)
{
JS_ASSERT(pn->isKind(PNK_LC));
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
NodeVector stmts(cx);
return statements(pn, stmts) &&
@ -2111,11 +2112,11 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
builder.letStatement(dtors, stmt, &pn->pn_pos, dst);
}
if (!pn->isKind(PNK_LC))
if (!pn->isKind(PNK_STATEMENTLIST))
return statement(pn, dst);
/* FALL THROUGH */
case PNK_LC:
case PNK_STATEMENTLIST:
return blockStatement(pn, dst);
case PNK_IF:
@ -2337,7 +2338,7 @@ ASTSerializer::comprehension(ParseNode *pn, Value *dst)
if (!optExpression(next->pn_kid1, &filter))
return false;
next = next->pn_kid2;
} else if (next->isKind(PNK_LC) && next->pn_count == 0) {
} else if (next->isKind(PNK_STATEMENTLIST) && next->pn_count == 0) {
/* FoldConstants optimized away the push. */
NodeVector empty(cx);
return builder.arrayExpression(empty, &pn->pn_pos, dst);
@ -2714,7 +2715,7 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
JS_CHECK_RECURSION(cx, return false);
switch (pn->getKind()) {
#ifdef JS_HAS_XML_SUPPORT
case PNK_LC:
case PNK_XMLCURLYEXPR:
{
Value expr;
return expression(pn->pn_kid, &expr) &&
@ -3049,7 +3050,7 @@ ASTSerializer::functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body)
expression(pnstart->pn_kid, body);
}
case PNK_LC: /* statement closure */
case PNK_STATEMENTLIST: /* statement closure */
{
ParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT)
? pnbody->pn_head->pn_next