Fix non-escaping closure optimization to cope with 'with' and eval (558720, r=jorendorff).

This commit is contained in:
Brendan Eich 2010-04-13 19:05:26 -07:00
parent 8b637950c5
commit 937d447d0e
4 changed files with 57 additions and 1 deletions

View File

@ -2232,8 +2232,18 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return JS_TRUE;
if (level >= JS_DISPLAY_SIZE)
return JS_TRUE;
/* FIXME: bug 545575 will make this all better. */
if (cg->flags & TCF_FUN_HEAVYWEIGHT)
return JS_TRUE;
{
JSTreeContext *tc = cg;
do {
tc = tc->parent;
if (tc->flags & TCF_FUN_HEAVYWEIGHT)
return JS_TRUE;
} while (tc->staticLevel != level);
}
if (FUN_FLAT_CLOSURE(cg->fun)) {
op = JSOP_GETDSLOT;

View File

@ -2235,7 +2235,28 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32& tcflags)
JSDefinition *lexdep = ALE_DEFN(ale)->resolve();
if (!lexdep->isFreeVar()) {
JS_ASSERT(lexdep->frameLevel() <= funbox->level);
uintN lexdepLevel = lexdep->frameLevel();
JS_ASSERT(lexdepLevel <= funbox->level);
/* FIXME: bug 545575 will make this all better. */
JSFunctionBox *afunbox = funbox;
do {
/*
* NB: (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) was
* checked first thing, so here we need only check
* after each step up the funbox->parent chain.
*
* As usual if we run out of funboxes we must use
* tcflags to handle the Function constructor case.
*/
if ((afunbox->parent ? afunbox->parent->tcflags : tcflags)
& TCF_FUN_HEAVYWEIGHT) {
nupvars = 0;
goto break2;
}
afunbox = afunbox->parent;
} while (afunbox && afunbox->level != lexdepLevel);
++nupvars;
if (lexdep->isAssigned())
break;
@ -2244,6 +2265,7 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32& tcflags)
if (!ale)
mutation = false;
break2:
if (nupvars == 0) {
FUN_METER(onlyfreevar);
FUN_SET_KIND(fun, JSFUN_NULL_CLOSURE);

View File

@ -9,6 +9,7 @@ script regress-137181.js
script regress-193555.js
script regress-313570.js
script regress-49286.js
script regress-558720.js
script regress-58274.js
script regress-85880.js
script regress-94506.js

View File

@ -0,0 +1,23 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = 'regress-558720.js';
var BUGNUMBER = 558720;
var summary = 'bad closure optimization inside "with"';
var actual;
var expect;
printBugNumber(BUGNUMBER);
printStatus(summary);
var a = new Function("a","b","with(a){return(function(){return b})()}");
var actual = a({b:"green"}) || "red";
eval("function a(a,b){with(a){return(function(){return b})()}}");
var expect = a({b:"green"}) || "red";
reportCompare(expect, actual, summary);
printStatus("All tests passed!");