зеркало из https://github.com/mozilla/gecko-dev.git
Bug 589199 - Fix eval static scope to play with the global lexical scope. (r=efaust)
This commit is contained in:
Родитель
e168c18e3b
Коммит
df3a5245f4
|
@ -229,7 +229,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||
{
|
||||
MOZ_ASSERT((evalType == INDIRECT_EVAL) == !caller);
|
||||
MOZ_ASSERT((evalType == INDIRECT_EVAL) == !pc);
|
||||
MOZ_ASSERT_IF(evalType == INDIRECT_EVAL, scopeobj->is<GlobalObject>());
|
||||
MOZ_ASSERT_IF(evalType == INDIRECT_EVAL, IsGlobalLexicalScope(scopeobj));
|
||||
AssertInnerizedScopeChain(cx, *scopeobj);
|
||||
|
||||
Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global());
|
||||
|
@ -271,7 +271,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||
return false;
|
||||
thisv = caller.thisValue();
|
||||
} else {
|
||||
MOZ_ASSERT(args.callee().global() == *scopeobj);
|
||||
MOZ_ASSERT(args.callee().global() == scopeobj->as<ClonedBlockObject>().global());
|
||||
|
||||
// Use the global as 'this', modulo outerization.
|
||||
JSObject* thisobj = GetThisObject(cx, scopeobj);
|
||||
|
@ -313,6 +313,8 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||
RootedObject enclosing(cx);
|
||||
if (evalType == DIRECT_EVAL)
|
||||
enclosing = callerScript->innermostStaticScope(pc);
|
||||
else
|
||||
enclosing = &cx->global()->lexicalScope().staticBlock();
|
||||
Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosing));
|
||||
if (!staticScope)
|
||||
return false;
|
||||
|
@ -454,7 +456,8 @@ js::IndirectEval(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
Rooted<GlobalObject*> global(cx, &args.callee().global());
|
||||
return EvalKernel(cx, args, INDIRECT_EVAL, NullFramePtr(), global, nullptr);
|
||||
RootedObject globalLexical(cx, &global->lexicalScope());
|
||||
return EvalKernel(cx, args, INDIRECT_EVAL, NullFramePtr(), globalLexical, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -287,8 +287,11 @@ BytecodeCompiler::isEvalCompilationUnit()
|
|||
bool
|
||||
BytecodeCompiler::isNonGlobalEvalCompilationUnit()
|
||||
{
|
||||
return isEvalCompilationUnit() &&
|
||||
enclosingStaticScope->as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
|
||||
if (!isEvalCompilationUnit())
|
||||
return false;
|
||||
StaticEvalObject& eval = enclosingStaticScope->as<StaticEvalObject>();
|
||||
JSObject* enclosing = eval.enclosingScopeForStaticScopeIter();
|
||||
return !IsStaticGlobalLexicalScope(enclosing);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -1537,9 +1537,14 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
|||
FunctionBox* funbox = sc->asFunctionBox();
|
||||
PropertyName* name = pn->pn_atom->asPropertyName();
|
||||
for (StaticScopeIter<NoGC> ssi(funbox->staticScope()); !ssi.done(); ssi++) {
|
||||
// Don't optimize names through eval.
|
||||
if (ssi.type() == StaticScopeIter<NoGC>::Eval)
|
||||
return false;
|
||||
// Don't optimize names through non-global eval. For global eval
|
||||
// we can use GNAME ops.
|
||||
if (ssi.type() == StaticScopeIter<NoGC>::Eval) {
|
||||
if (ssi.eval().isNonGlobal())
|
||||
return false;
|
||||
MOZ_ASSERT(!slot.isSome());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ssi.hasSyntacticDynamicScopeObject())
|
||||
continue;
|
||||
|
|
|
@ -50,16 +50,14 @@ setLazyParsingDisabled(false);
|
|||
eval("function h() { assertEq(x, 'inner');} h()");
|
||||
eval("function h2() { (function nest() { assertEq(x, 'inner'); })(); } h2()");
|
||||
}
|
||||
// It sure would be nice if we could run the h3/h4 tests below, but it turns out
|
||||
// that lazy functions and eval don't play together all that well. See bug
|
||||
// 1146080. For now, assert we have no gname, so people will notice if they
|
||||
// accidentally fix it and adjust this test accordingly.
|
||||
|
||||
// GNAME optimizations should work through lazy parsing.
|
||||
eval(`
|
||||
function h3() {
|
||||
assertEq(x, 'outer');
|
||||
}
|
||||
h3();
|
||||
hasGname(h3, 'x', false);
|
||||
hasGname(h3, 'x', true);
|
||||
`);
|
||||
eval(`
|
||||
function h4() {
|
||||
|
@ -67,7 +65,7 @@ eval(`
|
|||
nest();
|
||||
return nest;
|
||||
}
|
||||
hasGname(h4(), 'x', false);
|
||||
hasGname(h4(), 'x', true);
|
||||
`);
|
||||
|
||||
setLazyParsingDisabled(true);
|
||||
|
|
|
@ -88,10 +88,10 @@ BaselineFrame::trace(JSTracer* trc, JitFrameIterator& frameIterator)
|
|||
}
|
||||
|
||||
bool
|
||||
BaselineFrame::isDirectEvalFrame() const
|
||||
BaselineFrame::isNonGlobalEvalFrame() const
|
||||
{
|
||||
return isEvalFrame() &&
|
||||
script()->enclosingStaticScope()->as<StaticEvalObject>().isDirect();
|
||||
script()->enclosingStaticScope()->as<StaticEvalObject>().isNonGlobal();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -408,9 +408,9 @@ class BaselineFrame
|
|||
bool isNonStrictEvalFrame() const {
|
||||
return isEvalFrame() && !script()->strict();
|
||||
}
|
||||
bool isDirectEvalFrame() const;
|
||||
bool isNonGlobalEvalFrame() const;
|
||||
bool isNonStrictDirectEvalFrame() const {
|
||||
return isNonStrictEvalFrame() && isDirectEvalFrame();
|
||||
return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
|
||||
}
|
||||
bool isNonEvalFunctionFrame() const {
|
||||
return isFunctionFrame() && !isEvalFrame();
|
||||
|
|
|
@ -3486,7 +3486,7 @@ IsFunctionCloneable(HandleFunction fun)
|
|||
// If the script is an indirect eval that is immediately scoped
|
||||
// under the global, we can clone it.
|
||||
if (enclosing->is<StaticEvalObject>())
|
||||
return !enclosing->as<StaticEvalObject>().isDirect();
|
||||
return !enclosing->as<StaticEvalObject>().isNonGlobal();
|
||||
|
||||
// If the script already deals with a non-syntactic scope, we can
|
||||
// clone it.
|
||||
|
|
|
@ -3309,7 +3309,8 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
|||
RootedObject enclosingScope(cx);
|
||||
if (NestedScopeObject* enclosingBlock = innerBlock->enclosingNestedScope()) {
|
||||
if (IsStaticGlobalLexicalScope(enclosingBlock)) {
|
||||
MOZ_ASSERT(IsStaticGlobalLexicalScope(scriptStaticScope));
|
||||
MOZ_ASSERT(IsStaticGlobalLexicalScope(scriptStaticScope) ||
|
||||
scriptStaticScope->is<StaticNonSyntacticScopeObjects>());
|
||||
enclosingScope = scriptStaticScope;
|
||||
} else {
|
||||
enclosingScope = objects[FindScopeObjectIndex(src, *enclosingBlock)];
|
||||
|
|
|
@ -456,12 +456,7 @@ class StaticEvalObject : public ScopeObject
|
|||
return getReservedSlot(STRICT_SLOT).isTrue();
|
||||
}
|
||||
|
||||
// Indirect evals terminate in the global at run time, and has no static
|
||||
// enclosing scope.
|
||||
bool isDirect() const {
|
||||
MOZ_ASSERT_IF(!getReservedSlot(SCOPE_CHAIN_SLOT).isObject(), !isStrict());
|
||||
return getReservedSlot(SCOPE_CHAIN_SLOT).isObject();
|
||||
}
|
||||
inline bool isNonGlobal() const;
|
||||
};
|
||||
|
||||
// Static scope objects that stand in for one or more "polluting global"
|
||||
|
@ -1215,6 +1210,14 @@ NestedScopeObject::enclosingNestedScope() const
|
|||
return obj && obj->is<NestedScopeObject>() ? &obj->as<NestedScopeObject>() : nullptr;
|
||||
}
|
||||
|
||||
inline bool
|
||||
StaticEvalObject::isNonGlobal() const
|
||||
{
|
||||
if (isStrict())
|
||||
return true;
|
||||
return !IsStaticGlobalLexicalScope(&getReservedSlot(SCOPE_CHAIN_SLOT).toObject());
|
||||
}
|
||||
|
||||
inline bool
|
||||
ScopeIter::done() const
|
||||
{
|
||||
|
|
|
@ -109,10 +109,10 @@ InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script, AbstractF
|
|||
}
|
||||
|
||||
bool
|
||||
InterpreterFrame::isDirectEvalFrame() const
|
||||
InterpreterFrame::isNonGlobalEvalFrame() const
|
||||
{
|
||||
return isEvalFrame() &&
|
||||
script()->enclosingStaticScope()->as<StaticEvalObject>().isDirect();
|
||||
script()->enclosingStaticScope()->as<StaticEvalObject>().isNonGlobal();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -259,7 +259,7 @@ InterpreterFrame::epilogue(JSContext* cx)
|
|||
MOZ_ASSERT_IF(hasCallObj(), scopeChain()->as<CallObject>().isForEval());
|
||||
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
|
||||
DebugScopes::onPopStrictEvalScope(this);
|
||||
} else if (isDirectEvalFrame()) {
|
||||
} else if (isNonGlobalEvalFrame()) {
|
||||
MOZ_ASSERT_IF(isDebuggerEvalFrame(), !IsSyntacticScope(scopeChain()));
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -515,10 +515,10 @@ class InterpreterFrame
|
|||
return isEvalFrame() && !script()->strict();
|
||||
}
|
||||
|
||||
bool isDirectEvalFrame() const;
|
||||
bool isNonGlobalEvalFrame() const;
|
||||
|
||||
bool isNonStrictDirectEvalFrame() const {
|
||||
return isNonStrictEvalFrame() && isDirectEvalFrame();
|
||||
return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче