Bug 1371591 - Part 3: Store dynamic function names into the name atom instead of a property. r=jorendorff

--HG--
extra : rebase_source : 35f52619df56eb432a5dc3413c30eeae4324ada3
This commit is contained in:
André Bargull 2018-03-21 07:27:24 -07:00
parent 9fff6441bc
commit 129ae0e65a
8 changed files with 38 additions and 35 deletions

View File

@ -5493,18 +5493,18 @@ BytecodeEmitter::setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name,
// Single node can be emitted multiple times if it appears in
// array destructuring default. If function already has a name,
// just return.
if (fun->hasCompileTimeName()) {
if (fun->hasInferredName()) {
#ifdef DEBUG
RootedFunction rootedFun(cx, fun);
JSAtom* funName = NameToFunctionName(cx, name, prefixKind);
if (!funName)
return false;
MOZ_ASSERT(funName == rootedFun->compileTimeName());
MOZ_ASSERT(funName == rootedFun->inferredName());
#endif
return true;
}
fun->setCompileTimeName(name);
fun->setInferredName(name);
return true;
}

View File

@ -278,7 +278,11 @@ class NameResolver
retAtom.set(buf.finishAtom());
if (!retAtom)
return false;
fun->setGuessedAtom(retAtom);
// Skip assigning the guessed name if the function has a (dynamically)
// computed inferred name.
if (!pn->isDirectRHSAnonFunction())
fun->setGuessedAtom(retAtom);
return true;
}

View File

@ -130,7 +130,7 @@ assertName(z[0], 'z<');
odeURIL:(function(){})
a = { 1: function () {} };
assertName(a[1], 'a[1]');
assertName(a[1], '1');
a = {
"embedded spaces": function(){},

View File

@ -138,8 +138,8 @@ js::WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleOb
if (!wrapped)
return nullptr;
if (unwrapped->hasCompileTimeName())
wrapped->setCompileTimeName(unwrapped->compileTimeName());
if (unwrapped->hasInferredName())
wrapped->setInferredName(unwrapped->inferredName());
// Link them to each other to make GetWrappedAsyncFunction and
// GetUnwrappedAsyncFunction work.

View File

@ -83,8 +83,8 @@ js::WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleO
if (!wrapped)
return nullptr;
if (unwrapped->hasCompileTimeName())
wrapped->setCompileTimeName(unwrapped->compileTimeName());
if (unwrapped->hasInferredName())
wrapped->setInferredName(unwrapped->inferredName());
// Link them to each other to make GetWrappedAsyncGenerator and
// GetUnwrappedAsyncGenerator work.

View File

@ -590,7 +590,7 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
if (!fun->isInterpreted())
return xdr->fail(JS::TranscodeResult_Failure_NotInterpretedFun);
if (fun->explicitName() || fun->hasCompileTimeName() || fun->hasGuessedAtom())
if (fun->explicitName() || fun->hasInferredName() || fun->hasGuessedAtom())
firstword |= HasAtom;
if (fun->isGenerator() || fun->isAsync())
@ -1327,12 +1327,8 @@ JSFunction::getUnresolvedName(JSContext* cx, HandleFunction fun, MutableHandleAt
MOZ_ASSERT(!IsInternalFunctionObject(*fun));
MOZ_ASSERT(!fun->hasResolvedName());
JSAtom* name = fun->explicitOrCompileTimeName();
JSAtom* name = fun->explicitOrInferredName();
if (fun->isClassConstructor()) {
// It's impossible to have an empty named class expression. We use
// empty as a sentinel when creating default class constructors.
MOZ_ASSERT(name != cx->names().empty);
// Unnamed class expressions should not get a .name property at all.
if (name)
v.set(name);
@ -2307,9 +2303,8 @@ js::SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue na
if (!funNameAtom)
return false;
RootedValue funNameVal(cx, StringValue(funNameAtom));
if (!NativeDefineDataProperty(cx, fun, cx->names().name, funNameVal, JSPROP_READONLY))
return false;
MOZ_ASSERT(!fun->hasResolvedName());
fun->setInferredName(funNameAtom);
return true;
}

View File

@ -70,9 +70,9 @@ class JSFunction : public js::NativeObject
function-statement) */
SELF_HOSTED = 0x0080, /* function is self-hosted builtin and must not be
decompilable nor constructible. */
HAS_COMPILE_TIME_NAME = 0x0100, /* function had no explicit name, but a
name was set by SetFunctionName
at compile time */
HAS_INFERRED_NAME = 0x0100, /* function had no explicit name, but a name was
set by SetFunctionName at compile time or
SetFunctionNameIfNoOwnName at runtime. */
INTERPRETED_LAZY = 0x0200, /* function is interpreted but doesn't have a script yet */
RESOLVED_LENGTH = 0x0400, /* f.length has been resolved (see fun_resolve). */
RESOLVED_NAME = 0x0800, /* f.name has been resolved (see fun_resolve). */
@ -106,8 +106,7 @@ class JSFunction : public js::NativeObject
INTERPRETED_GENERATOR_OR_ASYNC = INTERPRETED,
NO_XDR_FLAGS = RESOLVED_LENGTH | RESOLVED_NAME,
STABLE_ACROSS_CLONES = CONSTRUCTOR | LAMBDA | SELF_HOSTED | HAS_COMPILE_TIME_NAME |
FUNCTION_KIND_MASK
STABLE_ACROSS_CLONES = CONSTRUCTOR | LAMBDA | SELF_HOSTED | FUNCTION_KIND_MASK
};
static_assert((INTERPRETED | INTERPRETED_LAZY) == js::JS_FUNCTION_INTERPRETED_BITS,
@ -205,7 +204,7 @@ class JSFunction : public js::NativeObject
/* Possible attributes of an interpreted function: */
bool isBoundFunction() const { return flags() & BOUND_FUN; }
bool hasCompileTimeName() const { return flags() & HAS_COMPILE_TIME_NAME; }
bool hasInferredName() const { return flags() & HAS_INFERRED_NAME; }
bool hasGuessedAtom() const {
static_assert(HAS_GUESSED_ATOM == HAS_BOUND_FUNCTION_NAME_PREFIX,
"HAS_GUESSED_ATOM is unused for bound functions");
@ -259,7 +258,7 @@ class JSFunction : public js::NativeObject
}
bool isNamedLambda() const {
return isLambda() && displayAtom() && !hasCompileTimeName() && !hasGuessedAtom();
return isLambda() && displayAtom() && !hasInferredName() && !hasGuessedAtom();
}
bool hasLexicalThis() const {
@ -346,9 +345,9 @@ class JSFunction : public js::NativeObject
js::MutableHandleAtom v);
JSAtom* explicitName() const {
return (hasCompileTimeName() || hasGuessedAtom()) ? nullptr : atom_.get();
return (hasInferredName() || hasGuessedAtom()) ? nullptr : atom_.get();
}
JSAtom* explicitOrCompileTimeName() const {
JSAtom* explicitOrInferredName() const {
return hasGuessedAtom() ? nullptr : atom_.get();
}
@ -366,16 +365,21 @@ class JSFunction : public js::NativeObject
return atom_;
}
void setCompileTimeName(JSAtom* atom) {
void setInferredName(JSAtom* atom) {
MOZ_ASSERT(!atom_);
MOZ_ASSERT(atom);
MOZ_ASSERT(!hasGuessedAtom());
MOZ_ASSERT(!isClassConstructor());
setAtom(atom);
flags_ |= HAS_COMPILE_TIME_NAME;
flags_ |= HAS_INFERRED_NAME;
}
JSAtom* compileTimeName() const {
MOZ_ASSERT(hasCompileTimeName());
void clearInferredName() {
MOZ_ASSERT(hasInferredName());
MOZ_ASSERT(atom_);
setAtom(nullptr);
flags_ &= ~HAS_INFERRED_NAME;
}
JSAtom* inferredName() const {
MOZ_ASSERT(hasInferredName());
MOZ_ASSERT(atom_);
return atom_;
}
@ -383,7 +387,7 @@ class JSFunction : public js::NativeObject
void setGuessedAtom(JSAtom* atom) {
MOZ_ASSERT(!atom_);
MOZ_ASSERT(atom);
MOZ_ASSERT(!hasCompileTimeName());
MOZ_ASSERT(!hasInferredName());
MOZ_ASSERT(!hasGuessedAtom());
MOZ_ASSERT(!isBoundFunction());
setAtom(atom);

View File

@ -480,10 +480,10 @@ intrinsic_MakeDefaultConstructor(JSContext* cx, unsigned argc, Value* vp)
// Because self-hosting code does not allow top-level lexicals,
// class constructors are class expressions in top-level vars.
// Because of this, we give them a guessed atom. Since they
// Because of this, we give them an inferred atom. Since they
// will always be cloned, and given an explicit atom, instead
// overrule that.
ctor->clearGuessedAtom();
ctor->clearInferredName();
args.rval().setUndefined();
return true;