Bug 1122833 - Don't relazify scripts with direct eval. (r=till)

This commit is contained in:
Shu-yu Guo 2015-01-17 11:40:18 -08:00
parent 893a36c12b
commit 9fc692492a
5 changed files with 35 additions and 10 deletions

View File

@ -1977,10 +1977,12 @@ template <class T, class U>
static inline void
PropagateTransitiveParseFlags(const T *inner, U *outer)
{
if (inner->bindingsAccessedDynamically())
outer->setBindingsAccessedDynamically();
if (inner->hasDebuggerStatement())
outer->setHasDebuggerStatement();
if (inner->bindingsAccessedDynamically())
outer->setBindingsAccessedDynamically();
if (inner->hasDebuggerStatement())
outer->setHasDebuggerStatement();
if (inner->hasDirectEval())
outer->setHasDirectEval();
}
template <typename ParseHandler>
@ -7586,6 +7588,7 @@ Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
/* Select JSOP_EVAL and flag pc as heavyweight. */
op = pc->sc->strict ? JSOP_STRICTEVAL : JSOP_EVAL;
pc->sc->setBindingsAccessedDynamically();
pc->sc->setHasDirectEval();
/*
* In non-strict mode code, direct calls to eval can add

View File

@ -58,11 +58,15 @@ class AnyContextFlags
// scope chain.
bool hasDebuggerStatement:1;
// A direct eval occurs in the body of the script.
bool hasDirectEval:1;
public:
AnyContextFlags()
: hasExplicitUseStrict(false),
bindingsAccessedDynamically(false),
hasDebuggerStatement(false)
hasDebuggerStatement(false),
hasDirectEval(false)
{ }
};
@ -195,10 +199,12 @@ class SharedContext
bool hasExplicitUseStrict() const { return anyCxFlags.hasExplicitUseStrict; }
bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
bool hasDebuggerStatement() const { return anyCxFlags.hasDebuggerStatement; }
bool hasDirectEval() const { return anyCxFlags.hasDirectEval; }
void setExplicitUseStrict() { anyCxFlags.hasExplicitUseStrict = true; }
void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
void setHasDebuggerStatement() { anyCxFlags.hasDebuggerStatement = true; }
void setHasDirectEval() { anyCxFlags.hasDirectEval = true; }
inline bool allLocalsAliased();

View File

@ -1422,12 +1422,19 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
RootedScript script(cx, lazy->maybeScript());
// Only functions without inner functions or direct eval are
// re-lazified. Functions with either of those are on the static scope
// chain of their inner functions, or in the case of eval, possibly
// eval'd inner functions. This prohibits re-lazification as
// StaticScopeIter queries isHeavyweight of those functions, which
// requires a non-lazy script.
bool canRelazify = !lazy->numInnerFunctions() && !lazy->hasDirectEval();
if (script) {
fun->setUnlazifiedScript(script);
// Remember the lazy script on the compiled script, so it can be
// stored on the function again in case of re-lazification.
// Only functions without inner functions are re-lazified.
if (!lazy->numInnerFunctions())
if (canRelazify)
script->setLazyScript(lazy);
return true;
}
@ -1451,7 +1458,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
// Additionally, the lazy script cache is not used during incremental
// GCs, to avoid resurrecting dead scripts after incremental sweeping
// has started.
if (!lazy->numInnerFunctions() && !JS::IsIncrementalGCInProgress(cx->runtime())) {
if (canRelazify && !JS::IsIncrementalGCInProgress(cx->runtime())) {
LazyScriptCache::Lookup lookup(cx, lazy);
cx->runtime()->lazyScriptCache.lookup(lookup, script.address());
}
@ -1496,7 +1503,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
lazy->initScript(script);
// Try to insert the newly compiled script into the lazy script cache.
if (!lazy->numInnerFunctions()) {
if (canRelazify) {
// A script's starting column isn't set by the bytecode emitter, so
// specify this from the lazy script so that if an identical lazy
// script is encountered later a match can be determined.

View File

@ -3789,6 +3789,7 @@ LazyScript::CreateRaw(ExclusiveContext *cx, HandleFunction fun,
p.strict = false;
p.bindingsAccessedDynamically = false;
p.hasDebuggerStatement = false;
p.hasDirectEval = false;
p.directlyInsideEval = false;
p.usesArgumentsApplyAndThis = false;

View File

@ -1882,7 +1882,7 @@ class LazyScript : public gc::TenuredCell
uint32_t version : 8;
uint32_t numFreeVariables : 24;
uint32_t numInnerFunctions : 23;
uint32_t numInnerFunctions : 22;
uint32_t generatorKindBits : 2;
@ -1890,6 +1890,7 @@ class LazyScript : public gc::TenuredCell
uint32_t strict : 1;
uint32_t bindingsAccessedDynamically : 1;
uint32_t hasDebuggerStatement : 1;
uint32_t hasDirectEval : 1;
uint32_t directlyInsideEval : 1;
uint32_t usesArgumentsApplyAndThis : 1;
uint32_t hasBeenCloned : 1;
@ -2015,6 +2016,13 @@ class LazyScript : public gc::TenuredCell
p_.hasDebuggerStatement = true;
}
bool hasDirectEval() const {
return p_.hasDirectEval;
}
void setHasDirectEval() {
p_.hasDirectEval = true;
}
bool directlyInsideEval() const {
return p_.directlyInsideEval;
}