mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 21:05:36 +00:00
Bug 1193606 - Clean up LazyFunction case of tryConvertFreeName and remove directlyInEval. (r=bhackett)
This commit is contained in:
parent
9cbf164447
commit
df4b17486d
@ -87,7 +87,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
bool maybeSetSourceMapFromOptions();
|
||||
bool emitFinalReturn();
|
||||
bool initGlobalBindings(ParseContext<FullParseHandler>& pc);
|
||||
void markFunctionsWithinEvalScript();
|
||||
bool maybeCompleteCompressSource();
|
||||
|
||||
AutoCompilationTraceLogger traceLogger;
|
||||
@ -519,29 +518,6 @@ BytecodeCompiler::initGlobalBindings(ParseContext<FullParseHandler>& pc)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BytecodeCompiler::markFunctionsWithinEvalScript()
|
||||
{
|
||||
// Mark top level functions in an eval script as being within an eval.
|
||||
|
||||
if (!script->hasObjects())
|
||||
return;
|
||||
|
||||
ObjectArray* objects = script->objects();
|
||||
size_t start = script->innerObjectsStart();
|
||||
|
||||
for (size_t i = start; i < objects->length; i++) {
|
||||
JSObject* obj = objects->vector[i];
|
||||
if (obj->is<JSFunction>()) {
|
||||
JSFunction* fun = &obj->as<JSFunction>();
|
||||
if (fun->hasScript())
|
||||
fun->nonLazyScript()->setDirectlyInsideEval();
|
||||
else if (fun->isInterpretedLazy())
|
||||
fun->lazyScript()->setDirectlyInsideEval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::maybeCompleteCompressSource()
|
||||
{
|
||||
@ -621,12 +597,6 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Note that this marking must happen before we tell Debugger
|
||||
// about the new script, in case Debugger delazifies the script's
|
||||
// inner functions.
|
||||
if (options.forEval)
|
||||
markFunctionsWithinEvalScript();
|
||||
|
||||
emitter->tellDebuggerAboutCompiledScript(cx);
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
@ -790,8 +760,6 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
||||
|
||||
script->bindings = pn->pn_funbox->bindings;
|
||||
|
||||
if (lazy->directlyInsideEval())
|
||||
script->setDirectlyInsideEval();
|
||||
if (lazy->usesArgumentsApplyAndThis())
|
||||
script->setUsesArgumentsApplyAndThis();
|
||||
if (lazy->hasBeenCloned())
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
@ -48,6 +49,8 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::frontend;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::Some;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::NumberIsInt32;
|
||||
using mozilla::PodCopy;
|
||||
@ -1502,57 +1505,65 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t hops = 0;
|
||||
// Walk the static scope chain and look for an aliased binding with
|
||||
// the name pn->pn_atom.
|
||||
uint32_t hops = 0;
|
||||
Maybe<uint32_t> slot;
|
||||
FunctionBox* funbox = sc->asFunctionBox();
|
||||
if (funbox->hasExtensibleScope())
|
||||
return false;
|
||||
if (funbox->function()->isNamedLambda() && funbox->function()->atom() == pn->pn_atom)
|
||||
return false;
|
||||
if (funbox->isHeavyweight()) {
|
||||
hops++;
|
||||
if (funbox->function()->isNamedLambda())
|
||||
hops++;
|
||||
}
|
||||
if (script->directlyInsideEval())
|
||||
return false;
|
||||
RootedObject outerScope(cx, script->enclosingStaticScope());
|
||||
for (StaticScopeIter<CanGC> ssi(cx, outerScope); !ssi.done(); ssi++) {
|
||||
if (ssi.type() != StaticScopeIter<CanGC>::Function) {
|
||||
if (ssi.type() == StaticScopeIter<CanGC>::Block) {
|
||||
// Use generic ops if a catch block is encountered.
|
||||
return false;
|
||||
}
|
||||
if (ssi.hasSyntacticDynamicScopeObject())
|
||||
hops++;
|
||||
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;
|
||||
|
||||
if (!ssi.hasSyntacticDynamicScopeObject())
|
||||
continue;
|
||||
}
|
||||
RootedScript script(cx, ssi.funScript());
|
||||
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
|
||||
return false;
|
||||
if (ssi.hasSyntacticDynamicScopeObject()) {
|
||||
uint32_t slot;
|
||||
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
|
||||
default: return false;
|
||||
|
||||
// Look up for name in function and block scopes.
|
||||
if (ssi.type() == StaticScopeIter<NoGC>::Function) {
|
||||
RootedScript funScript(cx, ssi.funScript());
|
||||
if (funScript->funHasExtensibleScope() || ssi.fun().atom() == pn->pn_atom)
|
||||
return false;
|
||||
|
||||
// Skip the current function, since we're trying to convert a
|
||||
// free name.
|
||||
if (script != funScript) {
|
||||
uint32_t slot_;
|
||||
if (lookupAliasedName(funScript, name, &slot_, pn)) {
|
||||
slot = Some(slot_);
|
||||
break;
|
||||
}
|
||||
|
||||
pn->setOp(op);
|
||||
MOZ_ALWAYS_TRUE(pn->pn_scopecoord.set(parser->tokenStream, hops, slot));
|
||||
return true;
|
||||
}
|
||||
hops++;
|
||||
} else if (ssi.type() == StaticScopeIter<NoGC>::Block) {
|
||||
RootedShape shape(cx, ssi.block().lookupAliasedName(name));
|
||||
if (shape) {
|
||||
// Don't optimize setting a 'const' binding. Let the slow
|
||||
// path do the error checking.
|
||||
if (!shape->writable() && pn->getOp() == JSOP_SETNAME)
|
||||
return false;
|
||||
slot = Some(shape->slot());
|
||||
pn->pn_dflags |= PND_LEXICAL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(ssi.type() != StaticScopeIter<NoGC>::With);
|
||||
}
|
||||
|
||||
// If this walk up and check for directlyInsideEval is ever removed,
|
||||
// we'll need to adjust CompileLazyFunction to better communicate
|
||||
// whether we're inside eval to the BytecodeEmitter. For now, this
|
||||
// walk is why CompileLazyFunction can claim that it's never inside
|
||||
// eval.
|
||||
if (script->funHasExtensibleScope() || script->directlyInsideEval())
|
||||
return false;
|
||||
hops++;
|
||||
}
|
||||
|
||||
// If we found a scope binding name, convert the name op to an aliased
|
||||
// var op.
|
||||
if (slot.isSome()) {
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
|
||||
default: return false;
|
||||
}
|
||||
pn->setOp(op);
|
||||
MOZ_ALWAYS_TRUE(pn->pn_scopecoord.set(parser->tokenStream, hops, *slot));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3968,7 +3968,6 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
|
||||
p.bindingsAccessedDynamically = false;
|
||||
p.hasDebuggerStatement = false;
|
||||
p.hasDirectEval = false;
|
||||
p.directlyInsideEval = false;
|
||||
p.usesArgumentsApplyAndThis = false;
|
||||
p.isDerivedClassConstructor = false;
|
||||
|
||||
|
@ -1098,9 +1098,6 @@ class JSScript : public js::gc::TenuredCell
|
||||
// Script came from eval(), and is in eval cache.
|
||||
bool isCachedEval_:1;
|
||||
|
||||
// Set for functions defined at the top level within an 'eval' script.
|
||||
bool directlyInsideEval_:1;
|
||||
|
||||
// 'this', 'arguments' and f.apply() are used. This is likely to be a wrapper.
|
||||
bool usesArgumentsApplyAndThis_:1;
|
||||
|
||||
@ -1334,7 +1331,6 @@ class JSScript : public js::gc::TenuredCell
|
||||
|
||||
bool isActiveEval() const { return isActiveEval_; }
|
||||
bool isCachedEval() const { return isCachedEval_; }
|
||||
bool directlyInsideEval() const { return directlyInsideEval_; }
|
||||
|
||||
void cacheForEval() {
|
||||
MOZ_ASSERT(isActiveEval() && !isCachedEval());
|
||||
@ -1353,7 +1349,6 @@ class JSScript : public js::gc::TenuredCell
|
||||
}
|
||||
|
||||
void setActiveEval() { isActiveEval_ = true; }
|
||||
void setDirectlyInsideEval() { directlyInsideEval_ = true; }
|
||||
|
||||
bool usesArgumentsApplyAndThis() const {
|
||||
return usesArgumentsApplyAndThis_;
|
||||
@ -2064,7 +2059,6 @@ class LazyScript : public gc::TenuredCell
|
||||
uint32_t bindingsAccessedDynamically : 1;
|
||||
uint32_t hasDebuggerStatement : 1;
|
||||
uint32_t hasDirectEval : 1;
|
||||
uint32_t directlyInsideEval : 1;
|
||||
uint32_t usesArgumentsApplyAndThis : 1;
|
||||
uint32_t hasBeenCloned : 1;
|
||||
uint32_t treatAsRunOnce : 1;
|
||||
@ -2213,13 +2207,6 @@ class LazyScript : public gc::TenuredCell
|
||||
p_.hasDirectEval = true;
|
||||
}
|
||||
|
||||
bool directlyInsideEval() const {
|
||||
return p_.directlyInsideEval;
|
||||
}
|
||||
void setDirectlyInsideEval() {
|
||||
p_.directlyInsideEval = true;
|
||||
}
|
||||
|
||||
bool usesArgumentsApplyAndThis() const {
|
||||
return p_.usesArgumentsApplyAndThis;
|
||||
}
|
||||
|
@ -70,13 +70,6 @@ CallObject::initAliasedLexicalsToThrowOnTouch(JSScript* script)
|
||||
initRemainingSlotsToUninitializedLexicals(script->bindings.aliasedBodyLevelLexicalBegin());
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
inline bool
|
||||
StaticScopeIter<allowGC>::done() const
|
||||
{
|
||||
return !obj;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
inline void
|
||||
StaticScopeIter<allowGC>::operator++(int)
|
||||
|
@ -687,6 +687,19 @@ StaticBlockObject::create(ExclusiveContext* cx)
|
||||
return NewObjectWithNullTaggedProto<StaticBlockObject>(cx, TenuredObject, BaseShape::DELEGATE);
|
||||
}
|
||||
|
||||
Shape*
|
||||
StaticBlockObject::lookupAliasedName(PropertyName* name)
|
||||
{
|
||||
Shape::Range<NoGC> r(lastProperty());
|
||||
while (!r.empty()) {
|
||||
jsid id = r.front().propidRaw();
|
||||
if (JSID_TO_ATOM(id)->asPropertyName() == name && isAliased(shapeToIndex(r.front())))
|
||||
return &r.front();
|
||||
r.popFront();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ Shape*
|
||||
StaticBlockObject::addVar(ExclusiveContext* cx, Handle<StaticBlockObject*> block, HandleId id,
|
||||
bool constant, unsigned index, bool* redeclared)
|
||||
|
@ -114,7 +114,7 @@ class StaticScopeIter
|
||||
"used in NoGC code");
|
||||
}
|
||||
|
||||
bool done() const;
|
||||
bool done() const { return !obj; }
|
||||
void operator++(int);
|
||||
|
||||
JSObject* staticScope() const { MOZ_ASSERT(!done()); return obj; }
|
||||
@ -653,6 +653,9 @@ class StaticBlockObject : public BlockObject
|
||||
return slotValue(i).isTrue();
|
||||
}
|
||||
|
||||
// Look up if the block has an aliased binding named |name|.
|
||||
Shape* lookupAliasedName(PropertyName* name);
|
||||
|
||||
/*
|
||||
* A static block object is cloned (when entering the block) iff some
|
||||
* variable of the block isAliased.
|
||||
|
Loading…
Reference in New Issue
Block a user