Bug 713755 - Convert all |a.<stuff>| parsing to use constructors that don't examine the token stream. r=jorendorff

--HG--
extra : rebase_source : c64a37e810c201df6fa2e5124f115ecc9c2e9b43
This commit is contained in:
Jeff Walden 2011-12-21 18:43:20 -05:00
parent be9a24ff19
commit 35a64c3f7e
2 changed files with 144 additions and 70 deletions

View File

@ -1215,6 +1215,85 @@ class BooleanLiteral : public ParseNode {
{ } { }
}; };
class PropertyAccess : public ParseNode {
public:
PropertyAccess(ParseNode *lhs, PropertyName *name,
const TokenPtr &begin, const TokenPtr &end)
: ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos::make(begin, end))
{
JS_ASSERT(lhs != NULL);
JS_ASSERT(name != NULL);
pn_u.name.expr = lhs;
pn_u.name.atom = name;
}
ParseNode &expression() const {
return *pn_u.name.expr;
}
PropertyName &name() const {
return *pn_u.name.atom->asPropertyName();
}
};
class XMLDoubleColonProperty : public ParseNode {
public:
XMLDoubleColonProperty(ParseNode *lhs, ParseNode *rhs,
const TokenPtr &begin, const TokenPtr &end)
: ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
{
JS_ASSERT(rhs->isKind(PNK_DBLCOLON));
pn_u.binary.left = lhs;
pn_u.binary.right = rhs;
}
ParseNode &left() const {
return *pn_u.binary.left;
}
ParseNode &right() const {
return *pn_u.binary.right;
}
};
class XMLFilterExpression : public ParseNode {
public:
XMLFilterExpression(ParseNode *lhs, ParseNode *filterExpr,
const TokenPtr &begin, const TokenPtr &end)
: ParseNode(PNK_FILTER, JSOP_FILTER, PN_BINARY, TokenPos::make(begin, end))
{
pn_u.binary.left = lhs;
pn_u.binary.right = filterExpr;
}
ParseNode &left() const {
return *pn_u.binary.left;
}
ParseNode &filter() const {
return *pn_u.binary.right;
}
};
class XMLProperty : public ParseNode {
public:
XMLProperty(ParseNode *lhs, ParseNode *propertyId,
const TokenPtr &begin, const TokenPtr &end)
: ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
{
pn_u.binary.left = lhs;
pn_u.binary.right = propertyId;
}
ParseNode &left() const {
return *pn_u.binary.left;
}
ParseNode &right() const {
return *pn_u.binary.right;
}
};
ParseNode * ParseNode *
CloneLeftHandSide(ParseNode *opn, TreeContext *tc); CloneLeftHandSide(ParseNode *opn, TreeContext *tc);

View File

@ -5732,39 +5732,36 @@ Parser::memberExpr(JSBool allowCallSyntax)
} }
while ((tt = tokenStream.getToken()) > TOK_EOF) { while ((tt = tokenStream.getToken()) > TOK_EOF) {
ParseNode *pn2; ParseNode *nextMember;
if (tt == TOK_DOT) { if (tt == TOK_DOT) {
pn2 = NameNode::create(PNK_DOT, NULL, tc);
if (!pn2)
return NULL;
tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME); tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
if (tt == TOK_ERROR) if (tt == TOK_ERROR)
return NULL; return NULL;
if (tt == TOK_NAME) { if (tt == TOK_NAME) {
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
if (!tc->inStrictMode() && tokenStream.peekToken() == TOK_DBLCOLON) { if (!tc->inStrictMode() && tokenStream.peekToken() == TOK_DBLCOLON) {
ParseNode *pn3 = propertyQualifiedIdentifier(); ParseNode *propertyId = propertyQualifiedIdentifier();
if (!pn3) if (!propertyId)
return NULL; return NULL;
JS_ASSERT(pn3->isKind(PNK_DBLCOLON)); nextMember = new_<XMLDoubleColonProperty>(lhs, propertyId,
pn2->setKind(PNK_LB); lhs->pn_pos.begin,
pn2->setOp(JSOP_GETELEM); tokenStream.currentToken().pos.end);
pn2->setArity(PN_BINARY); if (!nextMember)
pn2->pn_left = lhs; return NULL;
pn2->pn_right = pn3;
} else } else
#endif #endif
{ {
pn2->setOp(JSOP_GETPROP); nextMember = new_<PropertyAccess>(lhs, tokenStream.currentToken().name(),
pn2->pn_expr = lhs; lhs->pn_pos.begin,
pn2->pn_atom = tokenStream.currentToken().name(); tokenStream.currentToken().pos.end);
if (!nextMember)
return NULL;
} }
} }
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
else if (!tc->inStrictMode()) { else if (!tc->inStrictMode()) {
ParseNode *pn3; TokenPtr begin = lhs->pn_pos.begin;
if (tt == TOK_LP) { if (tt == TOK_LP) {
/* Filters are effectively 'with', so deoptimize names. */ /* Filters are effectively 'with', so deoptimize names. */
tc->flags |= TCF_FUN_HEAVYWEIGHT; tc->flags |= TCF_FUN_HEAVYWEIGHT;
@ -5774,40 +5771,38 @@ Parser::memberExpr(JSBool allowCallSyntax)
tc->innermostWith = lhs; tc->innermostWith = lhs;
PushStatement(tc, &stmtInfo, STMT_WITH, -1); PushStatement(tc, &stmtInfo, STMT_WITH, -1);
pn3 = bracketedExpr(); ParseNode *filter = bracketedExpr();
if (!pn3) if (!filter)
return NULL; return NULL;
pn3->setInParens(true); filter->setInParens(true);
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
tc->innermostWith = oldWith; tc->innermostWith = oldWith;
PopStatement(tc); PopStatement(tc);
pn2->setKind(PNK_FILTER); nextMember =
pn2->setOp(JSOP_FILTER); new_<XMLFilterExpression>(lhs, filter,
} else if (tt == TOK_AT || tt == TOK_STAR) { begin, tokenStream.currentToken().pos.end);
pn3 = starOrAtPropertyIdentifier(tt); if (!nextMember)
if (!pn3) return NULL;
} else if (tt == TOK_AT || tt == TOK_STAR) {
ParseNode *propertyId = starOrAtPropertyIdentifier(tt);
if (!propertyId)
return NULL;
nextMember = new_<XMLProperty>(lhs, propertyId,
begin, tokenStream.currentToken().pos.end);
if (!nextMember)
return NULL; return NULL;
pn2->setKind(PNK_LB);
pn2->setOp(JSOP_GETELEM);
} else { } else {
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT); reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT);
return NULL; return NULL;
} }
pn2->setArity(PN_BINARY);
pn2->pn_left = lhs;
pn2->pn_right = pn3;
} }
#endif #endif
else { else {
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT); reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT);
return NULL; return NULL;
} }
pn2->pn_pos.begin = lhs->pn_pos.begin;
pn2->pn_pos.end = tokenStream.currentToken().pos.end;
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
} else if (tt == TOK_DBLDOT) { } else if (tt == TOK_DBLDOT) {
if (tc->inStrictMode()) { if (tc->inStrictMode()) {
@ -5815,8 +5810,8 @@ Parser::memberExpr(JSBool allowCallSyntax)
return NULL; return NULL;
} }
pn2 = BinaryNode::create(PNK_DBLDOT, tc); nextMember = BinaryNode::create(PNK_DBLDOT, tc);
if (!pn2) if (!nextMember)
return NULL; return NULL;
tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME); tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
ParseNode *pn3 = primaryExpr(tt, JS_TRUE); ParseNode *pn3 = primaryExpr(tt, JS_TRUE);
@ -5830,62 +5825,62 @@ Parser::memberExpr(JSBool allowCallSyntax)
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT); reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT);
return NULL; return NULL;
} }
pn2->setOp(JSOP_DESCENDANTS); nextMember->setOp(JSOP_DESCENDANTS);
pn2->pn_left = lhs; nextMember->pn_left = lhs;
pn2->pn_right = pn3; nextMember->pn_right = pn3;
pn2->pn_pos.begin = lhs->pn_pos.begin; nextMember->pn_pos.begin = lhs->pn_pos.begin;
pn2->pn_pos.end = tokenStream.currentToken().pos.end; nextMember->pn_pos.end = tokenStream.currentToken().pos.end;
#endif #endif
} else if (tt == TOK_LB) { } else if (tt == TOK_LB) {
pn2 = BinaryNode::create(PNK_LB, tc); nextMember = BinaryNode::create(PNK_LB, tc);
if (!pn2) if (!nextMember)
return NULL; return NULL;
ParseNode *pn3 = expr(); ParseNode *pn3 = expr();
if (!pn3) if (!pn3)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
pn2->pn_pos.begin = lhs->pn_pos.begin; nextMember->pn_pos.begin = lhs->pn_pos.begin;
pn2->pn_pos.end = tokenStream.currentToken().pos.end; nextMember->pn_pos.end = tokenStream.currentToken().pos.end;
/* /*
* Optimize o['p'] to o.p by rewriting pn2, but avoid rewriting * Optimize o['p'] to o.p by rewriting nextMember, but don't
* o['0'] to use JSOP_GETPROP, to keep fast indexing disjoint in * rewrite o['0'] to use JSOP_GETPROP, to keep fast indexing
* the interpreter from fast property access. However, if the * disjoint in the interpreter from fast property access. However,
* bracketed string is a uint32, we rewrite pn3 to be a number * if the bracketed string is a uint32_t, we rewrite pn3 to be a
* instead of a string. * number instead of a string.
*/ */
do { do {
if (pn3->isKind(PNK_STRING)) { if (pn3->isKind(PNK_STRING)) {
jsuint index; jsuint index;
if (!js_IdIsIndex(ATOM_TO_JSID(pn3->pn_atom), &index)) { if (!js_IdIsIndex(ATOM_TO_JSID(pn3->pn_atom), &index)) {
pn2->setKind(PNK_DOT); nextMember->setKind(PNK_DOT);
pn2->setOp(JSOP_GETPROP); nextMember->setOp(JSOP_GETPROP);
pn2->setArity(PN_NAME); nextMember->setArity(PN_NAME);
pn2->pn_expr = lhs; nextMember->pn_expr = lhs;
pn2->pn_atom = pn3->pn_atom; nextMember->pn_atom = pn3->pn_atom;
break; break;
} }
pn3->setKind(PNK_NUMBER); pn3->setKind(PNK_NUMBER);
pn3->setOp(JSOP_DOUBLE); pn3->setOp(JSOP_DOUBLE);
pn3->pn_dval = index; pn3->pn_dval = index;
} }
pn2->setOp(JSOP_GETELEM); nextMember->setOp(JSOP_GETELEM);
pn2->pn_left = lhs; nextMember->pn_left = lhs;
pn2->pn_right = pn3; nextMember->pn_right = pn3;
} while (0); } while (0);
} else if (allowCallSyntax && tt == TOK_LP) { } else if (allowCallSyntax && tt == TOK_LP) {
pn2 = ListNode::create(PNK_LP, tc); nextMember = ListNode::create(PNK_LP, tc);
if (!pn2) if (!nextMember)
return NULL; return NULL;
pn2->setOp(JSOP_CALL); nextMember->setOp(JSOP_CALL);
lhs = CheckForImmediatelyAppliedLambda(lhs); lhs = CheckForImmediatelyAppliedLambda(lhs);
if (lhs->isOp(JSOP_NAME)) { if (lhs->isOp(JSOP_NAME)) {
if (lhs->pn_atom == context->runtime->atomState.evalAtom) { if (lhs->pn_atom == context->runtime->atomState.evalAtom) {
/* Select JSOP_EVAL and flag tc as heavyweight. */ /* Select JSOP_EVAL and flag tc as heavyweight. */
pn2->setOp(JSOP_EVAL); nextMember->setOp(JSOP_EVAL);
tc->noteCallsEval(); tc->noteCallsEval();
tc->flags |= TCF_FUN_HEAVYWEIGHT; tc->flags |= TCF_FUN_HEAVYWEIGHT;
/* /*
@ -5898,28 +5893,28 @@ Parser::memberExpr(JSBool allowCallSyntax)
} else if (lhs->isOp(JSOP_GETPROP)) { } else if (lhs->isOp(JSOP_GETPROP)) {
/* Select JSOP_FUNAPPLY given foo.apply(...). */ /* Select JSOP_FUNAPPLY given foo.apply(...). */
if (lhs->pn_atom == context->runtime->atomState.applyAtom) if (lhs->pn_atom == context->runtime->atomState.applyAtom)
pn2->setOp(JSOP_FUNAPPLY); nextMember->setOp(JSOP_FUNAPPLY);
else if (lhs->pn_atom == context->runtime->atomState.callAtom) else if (lhs->pn_atom == context->runtime->atomState.callAtom)
pn2->setOp(JSOP_FUNCALL); nextMember->setOp(JSOP_FUNCALL);
} }
pn2->initList(lhs); nextMember->initList(lhs);
pn2->pn_pos.begin = lhs->pn_pos.begin; nextMember->pn_pos.begin = lhs->pn_pos.begin;
if (!argumentList(pn2)) if (!argumentList(nextMember))
return NULL; return NULL;
if (pn2->pn_count > ARGC_LIMIT) { if (nextMember->pn_count > ARGC_LIMIT) {
JS_ReportErrorNumber(context, js_GetErrorMessage, NULL, JS_ReportErrorNumber(context, js_GetErrorMessage, NULL,
JSMSG_TOO_MANY_FUN_ARGS); JSMSG_TOO_MANY_FUN_ARGS);
return NULL; return NULL;
} }
pn2->pn_pos.end = tokenStream.currentToken().pos.end; nextMember->pn_pos.end = tokenStream.currentToken().pos.end;
} else { } else {
tokenStream.ungetToken(); tokenStream.ungetToken();
return lhs; return lhs;
} }
lhs = pn2; lhs = nextMember;
} }
if (tt == TOK_ERROR) if (tt == TOK_ERROR)
return NULL; return NULL;