From 35a64c3f7e01a605db382d5e982f259c674f3960 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 21 Dec 2011 18:43:20 -0500 Subject: [PATCH] Bug 713755 - Convert all |a.| parsing to use constructors that don't examine the token stream. r=jorendorff --HG-- extra : rebase_source : c64a37e810c201df6fa2e5124f115ecc9c2e9b43 --- js/src/frontend/ParseNode.h | 79 +++++++++++++++++++++ js/src/frontend/Parser.cpp | 135 +++++++++++++++++------------------- 2 files changed, 144 insertions(+), 70 deletions(-) diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index e0dbe6a29b1..36ba5892991 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -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 * CloneLeftHandSide(ParseNode *opn, TreeContext *tc); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 203253e9d88..badbca65d9d 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -5732,39 +5732,36 @@ Parser::memberExpr(JSBool allowCallSyntax) } while ((tt = tokenStream.getToken()) > TOK_EOF) { - ParseNode *pn2; + ParseNode *nextMember; if (tt == TOK_DOT) { - pn2 = NameNode::create(PNK_DOT, NULL, tc); - if (!pn2) - return NULL; - tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME); if (tt == TOK_ERROR) return NULL; if (tt == TOK_NAME) { #if JS_HAS_XML_SUPPORT if (!tc->inStrictMode() && tokenStream.peekToken() == TOK_DBLCOLON) { - ParseNode *pn3 = propertyQualifiedIdentifier(); - if (!pn3) + ParseNode *propertyId = propertyQualifiedIdentifier(); + if (!propertyId) return NULL; - JS_ASSERT(pn3->isKind(PNK_DBLCOLON)); - pn2->setKind(PNK_LB); - pn2->setOp(JSOP_GETELEM); - pn2->setArity(PN_BINARY); - pn2->pn_left = lhs; - pn2->pn_right = pn3; + nextMember = new_(lhs, propertyId, + lhs->pn_pos.begin, + tokenStream.currentToken().pos.end); + if (!nextMember) + return NULL; } else #endif { - pn2->setOp(JSOP_GETPROP); - pn2->pn_expr = lhs; - pn2->pn_atom = tokenStream.currentToken().name(); + nextMember = new_(lhs, tokenStream.currentToken().name(), + lhs->pn_pos.begin, + tokenStream.currentToken().pos.end); + if (!nextMember) + return NULL; } } #if JS_HAS_XML_SUPPORT else if (!tc->inStrictMode()) { - ParseNode *pn3; + TokenPtr begin = lhs->pn_pos.begin; if (tt == TOK_LP) { /* Filters are effectively 'with', so deoptimize names. */ tc->flags |= TCF_FUN_HEAVYWEIGHT; @@ -5774,40 +5771,38 @@ Parser::memberExpr(JSBool allowCallSyntax) tc->innermostWith = lhs; PushStatement(tc, &stmtInfo, STMT_WITH, -1); - pn3 = bracketedExpr(); - if (!pn3) + ParseNode *filter = bracketedExpr(); + if (!filter) return NULL; - pn3->setInParens(true); + filter->setInParens(true); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN); tc->innermostWith = oldWith; PopStatement(tc); - pn2->setKind(PNK_FILTER); - pn2->setOp(JSOP_FILTER); - } else if (tt == TOK_AT || tt == TOK_STAR) { - pn3 = starOrAtPropertyIdentifier(tt); - if (!pn3) + nextMember = + new_(lhs, filter, + begin, tokenStream.currentToken().pos.end); + if (!nextMember) + return NULL; + } else if (tt == TOK_AT || tt == TOK_STAR) { + ParseNode *propertyId = starOrAtPropertyIdentifier(tt); + if (!propertyId) + return NULL; + nextMember = new_(lhs, propertyId, + begin, tokenStream.currentToken().pos.end); + if (!nextMember) return NULL; - pn2->setKind(PNK_LB); - pn2->setOp(JSOP_GETELEM); } else { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT); return NULL; } - - pn2->setArity(PN_BINARY); - pn2->pn_left = lhs; - pn2->pn_right = pn3; } #endif else { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT); return NULL; } - - pn2->pn_pos.begin = lhs->pn_pos.begin; - pn2->pn_pos.end = tokenStream.currentToken().pos.end; #if JS_HAS_XML_SUPPORT } else if (tt == TOK_DBLDOT) { if (tc->inStrictMode()) { @@ -5815,8 +5810,8 @@ Parser::memberExpr(JSBool allowCallSyntax) return NULL; } - pn2 = BinaryNode::create(PNK_DBLDOT, tc); - if (!pn2) + nextMember = BinaryNode::create(PNK_DBLDOT, tc); + if (!nextMember) return NULL; tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME); ParseNode *pn3 = primaryExpr(tt, JS_TRUE); @@ -5830,62 +5825,62 @@ Parser::memberExpr(JSBool allowCallSyntax) reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT); return NULL; } - pn2->setOp(JSOP_DESCENDANTS); - pn2->pn_left = lhs; - pn2->pn_right = pn3; - pn2->pn_pos.begin = lhs->pn_pos.begin; - pn2->pn_pos.end = tokenStream.currentToken().pos.end; + nextMember->setOp(JSOP_DESCENDANTS); + nextMember->pn_left = lhs; + nextMember->pn_right = pn3; + nextMember->pn_pos.begin = lhs->pn_pos.begin; + nextMember->pn_pos.end = tokenStream.currentToken().pos.end; #endif } else if (tt == TOK_LB) { - pn2 = BinaryNode::create(PNK_LB, tc); - if (!pn2) + nextMember = BinaryNode::create(PNK_LB, tc); + if (!nextMember) return NULL; ParseNode *pn3 = expr(); if (!pn3) return NULL; MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); - pn2->pn_pos.begin = lhs->pn_pos.begin; - pn2->pn_pos.end = tokenStream.currentToken().pos.end; + nextMember->pn_pos.begin = lhs->pn_pos.begin; + nextMember->pn_pos.end = tokenStream.currentToken().pos.end; /* - * Optimize o['p'] to o.p by rewriting pn2, but avoid rewriting - * o['0'] to use JSOP_GETPROP, to keep fast indexing disjoint in - * the interpreter from fast property access. However, if the - * bracketed string is a uint32, we rewrite pn3 to be a number - * instead of a string. + * Optimize o['p'] to o.p by rewriting nextMember, but don't + * rewrite o['0'] to use JSOP_GETPROP, to keep fast indexing + * disjoint in the interpreter from fast property access. However, + * if the bracketed string is a uint32_t, we rewrite pn3 to be a + * number instead of a string. */ do { if (pn3->isKind(PNK_STRING)) { jsuint index; if (!js_IdIsIndex(ATOM_TO_JSID(pn3->pn_atom), &index)) { - pn2->setKind(PNK_DOT); - pn2->setOp(JSOP_GETPROP); - pn2->setArity(PN_NAME); - pn2->pn_expr = lhs; - pn2->pn_atom = pn3->pn_atom; + nextMember->setKind(PNK_DOT); + nextMember->setOp(JSOP_GETPROP); + nextMember->setArity(PN_NAME); + nextMember->pn_expr = lhs; + nextMember->pn_atom = pn3->pn_atom; break; } pn3->setKind(PNK_NUMBER); pn3->setOp(JSOP_DOUBLE); pn3->pn_dval = index; } - pn2->setOp(JSOP_GETELEM); - pn2->pn_left = lhs; - pn2->pn_right = pn3; + nextMember->setOp(JSOP_GETELEM); + nextMember->pn_left = lhs; + nextMember->pn_right = pn3; } while (0); } else if (allowCallSyntax && tt == TOK_LP) { - pn2 = ListNode::create(PNK_LP, tc); - if (!pn2) + nextMember = ListNode::create(PNK_LP, tc); + if (!nextMember) return NULL; - pn2->setOp(JSOP_CALL); + nextMember->setOp(JSOP_CALL); lhs = CheckForImmediatelyAppliedLambda(lhs); if (lhs->isOp(JSOP_NAME)) { if (lhs->pn_atom == context->runtime->atomState.evalAtom) { /* Select JSOP_EVAL and flag tc as heavyweight. */ - pn2->setOp(JSOP_EVAL); + nextMember->setOp(JSOP_EVAL); tc->noteCallsEval(); tc->flags |= TCF_FUN_HEAVYWEIGHT; /* @@ -5898,28 +5893,28 @@ Parser::memberExpr(JSBool allowCallSyntax) } else if (lhs->isOp(JSOP_GETPROP)) { /* Select JSOP_FUNAPPLY given foo.apply(...). */ 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) - pn2->setOp(JSOP_FUNCALL); + nextMember->setOp(JSOP_FUNCALL); } - pn2->initList(lhs); - pn2->pn_pos.begin = lhs->pn_pos.begin; + nextMember->initList(lhs); + nextMember->pn_pos.begin = lhs->pn_pos.begin; - if (!argumentList(pn2)) + if (!argumentList(nextMember)) return NULL; - if (pn2->pn_count > ARGC_LIMIT) { + if (nextMember->pn_count > ARGC_LIMIT) { JS_ReportErrorNumber(context, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_FUN_ARGS); return NULL; } - pn2->pn_pos.end = tokenStream.currentToken().pos.end; + nextMember->pn_pos.end = tokenStream.currentToken().pos.end; } else { tokenStream.ungetToken(); return lhs; } - lhs = pn2; + lhs = nextMember; } if (tt == TOK_ERROR) return NULL;