Bug 784608 (part 7) - Change the form and meaning of ParseContext::innermostWith, and do follow-up simplifications. r=luke.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 23 Aug 2012 16:50:25 -0700
changeset 105543 660d18ddffcd0c150fe58200e5c041df1e73f3e4
parent 105542 878eb7f978b676c9e2887355e2ee41057358953f
child 105544 d178a49c979c576e8b47e0d8517f38ce91975410
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersluke
bugs784608
milestone17.0a1
Bug 784608 (part 7) - Change the form and meaning of ParseContext::innermostWith, and do follow-up simplifications. r=luke.
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/Parser-inl.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1681,20 +1681,18 @@ BytecodeEmitter::checkSingletonContext()
 
 bool
 BytecodeEmitter::needsImplicitThis()
 {
     if (!script->compileAndGo)
         return true;
 
     if (sc->inFunction()) {
-        for (const FunctionBox *funbox = this->sc->funbox(); funbox; funbox = funbox->parent) {
-            if (funbox->inWith)
-                return true;
-        }
+        if (sc->funbox()->inWith)
+            return true;
     } else {
         JSObject *scope = sc->scopeChain();
         while (scope) {
             if (scope->isWith())
                 return true;
             scope = scope->enclosingScope();
         }
     }
--- a/js/src/frontend/Parser-inl.h
+++ b/js/src/frontend/Parser-inl.h
@@ -41,21 +41,21 @@ ParseContext::ParseContext(Parser *prs, 
     args_(prs->context),
     vars_(prs->context),
     yieldNode(NULL),
     functionList(NULL),
     queuedStrictModeError(NULL),
     parserPC(&prs->pc),
     lexdeps(prs->context),
     parent(prs->pc),
-    innermostWith(NULL),
     funcStmts(NULL),
     funHasReturnExpr(false),
     funHasReturnVoid(false),
     parsingForInit(false),
+    parsingWith(prs->pc ? prs->pc->parsingWith : false), // inherit from parent context
     inDeclDestructuring(false)
 {
     prs->pc = this;
 }
 
 inline bool
 ParseContext::init()
 {
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -393,17 +393,17 @@ FunctionBox::FunctionBox(ObjectBox* trac
     siblings(outerpc->functionList),
     kids(NULL),
     parent(outerpc->sc->inFunction() ? outerpc->sc->funbox() : NULL),
     bindings(),
     bufStart(0),
     bufEnd(0),
     ndefaults(0),
     strictModeState(sms),
-    inWith(!!outerpc->innermostWith),
+    inWith(outerpc->parsingWith),
     inGenexpLambda(false),
     cxFlags(outerpc->sc->context)     // the cxFlags are set in LeaveFunction
 {
     isFunctionBox = true;
     if (!outerpc->sc->inFunction()) {
         JSObject *scope = outerpc->sc->scopeChain();
         while (scope) {
             if (scope->isWith())
@@ -1146,17 +1146,17 @@ LeaveFunction(ParseNode *fn, Parser *par
 
             Definition *outer_dn = pc->decls().lookupFirst(atom);
 
             /*
              * Make sure to deoptimize lexical dependencies that are polluted
              * by eval and function statements (which both flag the function as
              * having an extensible scope) or any enclosing 'with'.
              */
-            if (funpc->sc->funHasExtensibleScope() || pc->innermostWith)
+            if (funpc->sc->funHasExtensibleScope() || pc->parsingWith)
                 DeoptimizeUsesWithin(dn, fn->pn_pos);
 
             if (!outer_dn) {
                 AtomDefnAddPtr p = pc->lexdeps->lookupForAdd(atom);
                 if (p) {
                     outer_dn = p.value();
                 } else {
                     /*
@@ -3477,31 +3477,31 @@ Parser::withStatement()
         return NULL;
     MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
     ParseNode *pn2 = parenExpr();
     if (!pn2)
         return NULL;
     MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
     pn->pn_left = pn2;
 
-    ParseNode *oldWith = pc->innermostWith;
-    pc->innermostWith = pn;
+    bool oldParsingWith = pc->parsingWith;
+    pc->parsingWith = true;
 
     StmtInfoPC stmtInfo(context);
     PushStatementPC(pc, &stmtInfo, STMT_WITH);
     pn2 = statement();
     if (!pn2)
         return NULL;
     PopStatementPC(context, pc);
 
     pn->pn_pos.end = pn2->pn_pos.end;
     pn->pn_right = pn2;
 
     pc->sc->setBindingsAccessedDynamically();
-    pc->innermostWith = oldWith;
+    pc->parsingWith = oldParsingWith;
 
     /*
      * Make sure to deoptimize lexical dependencies inside the |with|
      * to safely optimize binding globals (see bug 561923).
      */
     for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
         Definition *defn = r.front().value();
         Definition *lexdep = defn->resolve();
@@ -5518,27 +5518,27 @@ Parser::memberExpr(bool allowCallSyntax)
 #if JS_HAS_XML_SUPPORT
             else if (allowsXML()) {
                 TokenPtr begin = lhs->pn_pos.begin;
                 if (tt == TOK_LP) {
                     /* Filters are effectively 'with', so deoptimize names. */
                     pc->sc->setBindingsAccessedDynamically();
 
                     StmtInfoPC stmtInfo(context);
-                    ParseNode *oldWith = pc->innermostWith;
-                    pc->innermostWith = lhs;
+                    bool oldParsingWith = pc->parsingWith;
+                    pc->parsingWith = true;
                     PushStatementPC(pc, &stmtInfo, STMT_WITH);
 
                     ParseNode *filter = bracketedExpr();
                     if (!filter)
                         return NULL;
                     filter->setInParens(true);
                     MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
 
-                    pc->innermostWith = oldWith;
+                    pc->parsingWith = oldParsingWith;
                     PopStatementPC(context, pc);
 
                     nextMember =
                         new_<XMLFilterExpression>(lhs, filter,
                                                   begin, tokenStream.currentToken().pos.end);
                     if (!nextMember)
                         return NULL;
                 } else if (tt == TOK_AT || tt == TOK_STAR) {
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -169,31 +169,32 @@ struct ParseContext                 /* t
                                        and holds either |this| or one of
                                        |this|'s descendents */
 
   public:
     OwnedAtomDefnMapPtr lexdeps;    /* unresolved lexical name dependencies */
 
     ParseContext     *parent;       /* Enclosing function or global context.  */
 
-    ParseNode       *innermostWith; /* innermost WITH parse node */
-
     FuncStmtSet     *funcStmts;     /* Set of (non-top-level) function statements
                                        that will alias any top-level bindings with
                                        the same name. */
 
     // The following flags are set when a particular code feature is detected
     // in a function.
     bool            funHasReturnExpr:1; /* function has 'return <expr>;' */
     bool            funHasReturnVoid:1; /* function has 'return;' */
 
     // The following flags are set when parsing enters a particular region of
     // source code, and cleared when that region is exited.
     bool            parsingForInit:1;   /* true while parsing init expr of for;
                                            exclude 'in' */
+    bool            parsingWith:1;  /* true while we are within a
+                                       with-statement or E4X filter-expression
+                                       in the current ParseContext chain */
 
     // Set when parsing a declaration-like destructuring pattern.  This flag
     // causes PrimaryExpr to create PN_NAME parse nodes for variable references
     // which are not hooked into any definition's use chain, added to any tree
     // context's AtomList, etc. etc.  CheckDestructuring will do that work
     // later.
     //
     // The comments atop CheckDestructuring explain the distinction between