Disable global name analysis with var declarations inside with (bug 585524, r=dmandelin).
authorDavid Anderson <danderson@mozilla.com>
Tue, 23 Nov 2010 18:00:39 -0800
changeset 58291 eedeb03352c7880a35d1069917f0c2c3c3302c39
parent 58290 e5c6b0151c7be64f5ad9937e2cf1e3c320b9283f
child 58292 a4f8e9da4f951a02b7ef32e599544104e6ad9610
push id17228
push userrsayre@mozilla.com
push dateFri, 26 Nov 2010 20:51:05 +0000
treeherdermozilla-central@f3c6fbb5bc95 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmandelin
bugs585524
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Disable global name analysis with var declarations inside with (bug 585524, r=dmandelin).
js/src/jit-test/tests/basic/bug585542.js
js/src/jsemit.cpp
js/src/jsemit.h
js/src/jsparse.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug585542.js
@@ -0,0 +1,11 @@
+function f() { return 2; }
+function g(o) {
+  with (o) {
+      var f = function() { return 4; }
+  }
+  return f();
+}
+
+assertEq(g({}), 4);
+
+
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -2268,17 +2268,17 @@ BindNameToSlot(JSContext *cx, JSCodeGene
         return JS_TRUE;
     }
 
     if (dn->pn_dflags & PND_GVAR) {
         /*
          * JSOP_DEFFUN could introduce a shadowing definition, so if it
          * is present, we can't optimize to JSOP_GETGLOBAL.
          */
-        if (cg->hasDefFun())
+        if (cg->mightAliasLocals())
             return JS_TRUE;
 
         switch (op) {
           case JSOP_NAME:     op = JSOP_GETGLOBAL; break;
           case JSOP_SETNAME:  op = JSOP_SETGLOBAL; break;
           case JSOP_INCNAME:  op = JSOP_INCGLOBAL; break;
           case JSOP_NAMEINC:  op = JSOP_GLOBALINC; break;
           case JSOP_DECNAME:  op = JSOP_DECGLOBAL; break;
--- a/js/src/jsemit.h
+++ b/js/src/jsemit.h
@@ -247,19 +247,22 @@ struct JSStmtInfo {
 #define TCF_FUN_MUTATES_PARAMETER 0x1000000
 
 /*
  * Compiling an eval() script.
  */
 #define TCF_COMPILE_FOR_EVAL     0x2000000
 
 /*
- * The function contains a JSOP_DEFFUN bytecode.
+ * The function has broken or incorrect def-use information, and it cannot
+ * safely optimize free variables to global names. This can happen because
+ * of a named function statement not at the top level (emitting a DEFFUN),
+ * or a variable declaration inside a "with".
  */
-#define TCF_FUN_HAS_DEFFUN       0x4000000
+#define TCF_FUN_MIGHT_ALIAS_LOCALS  0x4000000
 
 /*
  * Flags to check for return; vs. return expr; in a function.
  */
 #define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)
 
 /*
  * Sticky deoptimization flags to propagate from FunctionBody.
@@ -267,17 +270,17 @@ struct JSStmtInfo {
 #define TCF_FUN_FLAGS           (TCF_FUN_SETS_OUTER_NAME |                    \
                                  TCF_FUN_USES_ARGUMENTS  |                    \
                                  TCF_FUN_PARAM_ARGUMENTS |                    \
                                  TCF_FUN_HEAVYWEIGHT     |                    \
                                  TCF_FUN_IS_GENERATOR    |                    \
                                  TCF_FUN_USES_OWN_NAME   |                    \
                                  TCF_HAS_SHARPS          |                    \
                                  TCF_FUN_CALLS_EVAL      |                    \
-                                 TCF_FUN_HAS_DEFFUN      |                    \
+                                 TCF_FUN_MIGHT_ALIAS_LOCALS |                 \
                                  TCF_FUN_MUTATES_PARAMETER |                  \
                                  TCF_STRICT_MODE_CODE)
 
 struct JSTreeContext {              /* tree context for semantic checks */
     uint32          flags;          /* statement state flags, see above */
     uint32          bodyid;         /* block number of program/function body */
     uint32          blockidGen;     /* preincremented block number generator */
     JSStmtInfo      *topStmt;       /* top of statement info stack */
@@ -398,22 +401,22 @@ struct JSTreeContext {              /* t
     void noteCallsEval() {
         flags |= TCF_FUN_CALLS_EVAL;
     }
 
     bool callsEval() const {
         return flags & TCF_FUN_CALLS_EVAL;
     }
 
-    void noteHasDefFun() {
-        flags |= TCF_FUN_HAS_DEFFUN;
+    void noteMightAliasLocals() {
+        flags |= TCF_FUN_MIGHT_ALIAS_LOCALS;
     }
 
-    bool hasDefFun() const {
-        return flags & TCF_FUN_HAS_DEFFUN;
+    bool mightAliasLocals() const {
+        return flags & TCF_FUN_MIGHT_ALIAS_LOCALS;
     }
 
     void noteParameterMutation() {
         JS_ASSERT(inFunction());
         flags |= TCF_FUN_MUTATES_PARAMETER;
     }
 
     bool mutatesParameter() const {
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -3138,17 +3138,17 @@ Parser::functionDef(JSAtom *funAtom, Fun
     } else if (!topLevel) {
         /*
          * ECMA ed. 3 extension: a function expression statement not at the
          * top level, e.g., in a compound statement such as the "then" part
          * of an "if" statement, binds a closure only if control reaches that
          * sub-statement.
          */
         op = JSOP_DEFFUN;
-        outertc->noteHasDefFun();
+        outertc->noteMightAliasLocals();
     }
 
     funbox->kids = funtc.functionList;
 
     pn->pn_funbox = funbox;
     pn->pn_op = op;
     if (pn->pn_body) {
         pn->pn_body->append(body);
@@ -3603,16 +3603,17 @@ BindVarOrConst(JSContext *cx, BindData *
     if (!CheckStrictBinding(cx, tc, atom, pn))
         return false;
 
     JSStmtInfo *stmt = js_LexicalLookup(tc, atom, NULL);
 
     if (stmt && stmt->type == STMT_WITH) {
         data->fresh = false;
         pn->pn_dflags |= PND_DEOPTIMIZED;
+        tc->noteMightAliasLocals();
         return true;
     }
 
     JSAtomListElement *ale = tc->decls.lookup(atom);
     JSOp op = data->op;
 
     if (stmt || ale) {
         JSDefinition *dn = ale ? ALE_DEFN(ale) : NULL;