Bug 762473 - Don't apply non-reentrant-closure optimization when the scope is extensible (r=dvander)

--HG--
extra : rebase_source : e20cc5157607b72d8ecdd1fc4560373e0ad7060a
This commit is contained in:
Luke Wagner 2012-06-07 20:03:18 -07:00
Родитель 20cc12b099
Коммит 2271b34bbd
6 изменённых файлов: 67 добавлений и 1 удалений

Просмотреть файл

@ -34,6 +34,13 @@ MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script_)
JSScript *outer = worklist.back(); JSScript *outer = worklist.back();
worklist.popBack(); worklist.popBack();
/*
* If outer has an extensible scope, its slots may be resized which
* will invalidate nesting->varArray/argArray.
*/
if (outer->funHasExtensibleScope)
continue;
if (outer->hasObjects()) { if (outer->hasObjects()) {
ObjectArray *arr = outer->objects(); ObjectArray *arr = outer->objects();

Просмотреть файл

@ -0,0 +1,49 @@
function f(i) {
var a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a16,a17;
var b = true;
if (b)
function f1() {}
if (b)
function f2() {}
if (b)
function f3() {}
if (b)
function f4() {}
if (b)
function f5() {}
if (b)
function f6() {}
if (b)
function f7() {}
if (b)
function f8() {}
if (b)
function f9() {}
if (b)
function f10() {}
if (b)
function f11() {}
if (b)
function f12() {}
if (b)
function f13() {}
if (b)
function f14() {}
if (b)
function f15() {}
if (b)
function f16() {}
if (b)
function f17() {}
a1 = i;
function f() {
return a1;
}
return f();
}
for (var i = 0; i < 100; ++i)
assertEq(f(i), i);

Просмотреть файл

@ -5259,6 +5259,8 @@ NestingPrologue(JSContext *cx, StackFrame *fp)
MarkTypeObjectFlags(cx, fp->fun(), OBJECT_FLAG_REENTRANT_FUNCTION); MarkTypeObjectFlags(cx, fp->fun(), OBJECT_FLAG_REENTRANT_FUNCTION);
} }
/* Extensibility guards in the frontend guarantee the slots won't move. */
JS_ASSERT(!script->funHasExtensibleScope);
nesting->activeCall = &fp->callObj(); nesting->activeCall = &fp->callObj();
nesting->argArray = Valueify(nesting->activeCall->argArray()); nesting->argArray = Valueify(nesting->activeCall->argArray());
nesting->varArray = Valueify(nesting->activeCall->varArray()); nesting->varArray = Valueify(nesting->activeCall->varArray());

Просмотреть файл

@ -374,6 +374,7 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
SavedCallerFun, SavedCallerFun,
StrictModeCode, StrictModeCode,
ContainsDynamicNameAccess, ContainsDynamicNameAccess,
FunHasExtensibleScope,
ArgumentsHasLocalBinding, ArgumentsHasLocalBinding,
NeedsArgsObj, NeedsArgsObj,
OwnFilename, OwnFilename,
@ -529,6 +530,8 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
scriptBits |= (1 << StrictModeCode); scriptBits |= (1 << StrictModeCode);
if (script->bindingsAccessedDynamically) if (script->bindingsAccessedDynamically)
scriptBits |= (1 << ContainsDynamicNameAccess); scriptBits |= (1 << ContainsDynamicNameAccess);
if (script->funHasExtensibleScope)
scriptBits |= (1 << FunHasExtensibleScope);
if (script->argumentsHasLocalBinding()) if (script->argumentsHasLocalBinding())
scriptBits |= (1 << ArgumentsHasLocalBinding); scriptBits |= (1 << ArgumentsHasLocalBinding);
if (script->analyzedArgsUsage() && script->needsArgsObj()) if (script->analyzedArgsUsage() && script->needsArgsObj())
@ -602,6 +605,8 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
script->strictModeCode = true; script->strictModeCode = true;
if (scriptBits & (1 << ContainsDynamicNameAccess)) if (scriptBits & (1 << ContainsDynamicNameAccess))
script->bindingsAccessedDynamically = true; script->bindingsAccessedDynamically = true;
if (scriptBits & (1 << FunHasExtensibleScope))
script->funHasExtensibleScope = true;
if (scriptBits & (1 << ArgumentsHasLocalBinding)) { if (scriptBits & (1 << ArgumentsHasLocalBinding)) {
PropertyName *arguments = cx->runtime->atomState.argumentsAtom; PropertyName *arguments = cx->runtime->atomState.argumentsAtom;
unsigned local; unsigned local;
@ -1313,6 +1318,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
script->savedCallerFun = true; script->savedCallerFun = true;
} }
script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically(); script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically();
script->funHasExtensibleScope = bce->sc->funHasExtensibleScope();
script->hasSingletons = bce->hasSingletons; script->hasSingletons = bce->hasSingletons;
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
if (cx->compartment->debugMode()) if (cx->compartment->debugMode())
@ -1820,6 +1826,7 @@ js::CloneScript(JSContext *cx, HandleScript src)
dst->strictModeCode = src->strictModeCode; dst->strictModeCode = src->strictModeCode;
dst->compileAndGo = src->compileAndGo; dst->compileAndGo = src->compileAndGo;
dst->bindingsAccessedDynamically = src->bindingsAccessedDynamically; dst->bindingsAccessedDynamically = src->bindingsAccessedDynamically;
dst->funHasExtensibleScope = src->funHasExtensibleScope;
dst->hasSingletons = src->hasSingletons; dst->hasSingletons = src->hasSingletons;
dst->isGenerator = src->isGenerator; dst->isGenerator = src->isGenerator;

Просмотреть файл

@ -526,6 +526,7 @@ struct JSScript : public js::gc::Cell
bool strictModeCode:1; /* code is in strict mode */ bool strictModeCode:1; /* code is in strict mode */
bool compileAndGo:1; /* see Parser::compileAndGo */ bool compileAndGo:1; /* see Parser::compileAndGo */
bool bindingsAccessedDynamically:1; /* see ContextFlags' field of the same name */ bool bindingsAccessedDynamically:1; /* see ContextFlags' field of the same name */
bool funHasExtensibleScope:1; /* see ContextFlags' field of the same name */
bool warnedAboutTwoArgumentEval:1; /* have warned about use of bool warnedAboutTwoArgumentEval:1; /* have warned about use of
obsolete eval(s, o) in obsolete eval(s, o) in
this script */ this script */

Просмотреть файл

@ -25,7 +25,7 @@ namespace js {
* and saved versions. If deserialization fails, the data should be * and saved versions. If deserialization fails, the data should be
* invalidated if possible. * invalidated if possible.
*/ */
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 117); static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 118);
class XDRBuffer { class XDRBuffer {
public: public: