Don't build cross-eval upvars for heavyweight functions (bug 616762, r=brendan, a=CLOSED TREE). FENNEC_4_0b3_BUILD1
authorDavid Anderson <danderson@mozilla.com>
Tue, 14 Dec 2010 11:50:20 -0800
changeset 59184 abe8842594814d9758eef43c67a4004378920556
parent 59183 a272338eb57a623106e8032905009813d91e8e28
child 59185 d78f9cb65e919a47fa23c597f724387f87561fc1
child 59188 f11f7ed625ba5f0ff8e20e4367c89d135d924428
push idunknown
push userunknown
push dateunknown
reviewersbrendan, CLOSED
bugs616762
milestone2.0b8pre
Don't build cross-eval upvars for heavyweight functions (bug 616762, r=brendan, a=CLOSED TREE).
js/src/jsemit.cpp
js/src/trace-test/tests/basic/bug616762.js
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -2236,16 +2236,37 @@ BindNameToSlot(JSContext *cx, JSCodeGene
              * and the scope chain matches the function's variable object.
              * Optimize access to function's arguments and variable and the
              * arguments object.
              */
             if (op != JSOP_NAME)
                 return JS_TRUE;
 
             /*
+             * It is illegal to add upvars to heavyweight functions (and
+             * unnecessary, since the optimization avoids creating call
+             * objects). Take the following code as an eval string:
+             *
+             *   (function () {
+             *       $(init);
+             *       function init() {
+             *           $();
+             *       }
+             *    })();
+             *
+             * The first instance of "$" cannot be an upvar, because the
+             * outermost lambda is on "init"'s scope chain, which escapes.
+             *
+             * A similar restriction exists for upvars which do not cross
+             * eval (see the end of BindNameToSlot and bug 616762).
+             */
+            if (cg->flags & TCF_FUN_HEAVYWEIGHT)
+                return JS_TRUE;
+
+            /*
              * Generator functions may be resumed from any call stack, which
              * defeats the display optimization to static link searching used
              * by JSOP_{GET,CALL}UPVAR.
              */
             JSFunction *fun = cg->parser->callerFrame->fun();
             JS_ASSERT(cg->staticLevel >= fun->u.i.script->staticLevel);
             unsigned skip = cg->staticLevel - fun->u.i.script->staticLevel;
             if (cg->skipSpansGenerator(skip))
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/bug616762.js
@@ -0,0 +1,26 @@
+// vim: set ts=4 sw=4 tw=99 et:
+document = {
+    ready: function (x) {
+        this.exec = x;
+    }
+};
+
+var $ = function (x) {
+    return document;
+};
+
+(function ($) {
+    eval("(function(){\n" +
+         "  var Private={};\n" +
+         "  $(document).ready(function(){\n" +
+         "      init()\n" +
+         "  });\n" +
+         "  function init(){\n" +
+         "      $(Private)\n" +
+         "  };\n" +
+         "})();");
+})($);
+document.exec();
+
+// Don't crash or assert.
+