mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1365387 - Optimize FinishBoundFunctionInit by delaying atomizing the function name. r=till
This commit is contained in:
parent
274de19ad9
commit
f2ef984519
@ -540,9 +540,12 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
||||
if (fun->hasResolvedName())
|
||||
return true;
|
||||
|
||||
RootedAtom name(cx);
|
||||
if (!JSFunction::getUnresolvedName(cx, fun, &name))
|
||||
return false;
|
||||
|
||||
// Don't define an own .name property for unnamed functions.
|
||||
JSAtom* name = fun->getUnresolvedName(cx);
|
||||
if (name == nullptr)
|
||||
if (!name)
|
||||
return true;
|
||||
|
||||
v.setString(name);
|
||||
@ -1044,7 +1047,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto AppendPrelude = [&out, &fun]() {
|
||||
auto AppendPrelude = [cx, &out, &fun]() {
|
||||
if (fun->isAsync()) {
|
||||
if (!out.append("async "))
|
||||
return false;
|
||||
@ -1063,6 +1066,10 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
|
||||
if (fun->explicitName()) {
|
||||
if (!out.append(' '))
|
||||
return false;
|
||||
if (fun->isBoundFunction()) {
|
||||
if (!out.append(cx->names().boundWithSpace))
|
||||
return false;
|
||||
}
|
||||
if (!out.append(fun->explicitName()))
|
||||
return false;
|
||||
}
|
||||
@ -1365,23 +1372,42 @@ JSFunction::getUnresolvedLength(JSContext* cx, HandleFunction fun, MutableHandle
|
||||
return true;
|
||||
}
|
||||
|
||||
JSAtom*
|
||||
JSFunction::getUnresolvedName(JSContext* cx)
|
||||
/* static */ bool
|
||||
JSFunction::getUnresolvedName(JSContext* cx, HandleFunction fun, MutableHandleAtom v)
|
||||
{
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(*this));
|
||||
MOZ_ASSERT(!hasResolvedName());
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(*fun));
|
||||
MOZ_ASSERT(!fun->hasResolvedName());
|
||||
|
||||
if (isClassConstructor()) {
|
||||
JSAtom* name = fun->explicitOrCompileTimeName();
|
||||
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(explicitOrCompileTimeName() != cx->names().empty);
|
||||
MOZ_ASSERT(name != cx->names().empty);
|
||||
|
||||
// Unnamed class expressions should not get a .name property at all.
|
||||
return explicitOrCompileTimeName();
|
||||
if (name)
|
||||
v.set(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
return explicitOrCompileTimeName() != nullptr ? explicitOrCompileTimeName()
|
||||
: cx->names().empty;
|
||||
if (fun->isBoundFunction()) {
|
||||
// Bound functions are never unnamed.
|
||||
MOZ_ASSERT(name);
|
||||
|
||||
StringBuffer sb(cx);
|
||||
if (!sb.append(cx->names().boundWithSpace) || !sb.append(name))
|
||||
return false;
|
||||
|
||||
JSAtom* boundName = sb.finishAtom();
|
||||
if (!boundName)
|
||||
return false;
|
||||
|
||||
v.set(boundName);
|
||||
return true;
|
||||
}
|
||||
|
||||
v.set(name != nullptr ? name : cx->names().empty);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const js::Value&
|
||||
|
@ -312,7 +312,8 @@ class JSFunction : public js::NativeObject
|
||||
static bool getUnresolvedLength(JSContext* cx, js::HandleFunction fun,
|
||||
js::MutableHandleValue v);
|
||||
|
||||
JSAtom* getUnresolvedName(JSContext* cx);
|
||||
static bool getUnresolvedName(JSContext* cx, js::HandleFunction fun,
|
||||
js::MutableHandleAtom v);
|
||||
|
||||
JSAtom* explicitName() const {
|
||||
return (hasCompileTimeName() || hasGuessedAtom()) ? nullptr : atom_.get();
|
||||
|
@ -503,39 +503,31 @@ intrinsic_FinishBoundFunctionInit(JSContext* cx, unsigned argc, Value* vp)
|
||||
bound->setExtendedSlot(BOUND_FUN_LENGTH_SLOT, NumberValue(length));
|
||||
|
||||
// Try to avoid invoking the resolve hook.
|
||||
JSAtom* name = nullptr;
|
||||
if (targetObj->is<JSFunction>() && !targetObj->as<JSFunction>().hasResolvedName())
|
||||
name = targetObj->as<JSFunction>().getUnresolvedName(cx);
|
||||
RootedAtom name(cx);
|
||||
if (targetObj->is<JSFunction>() && !targetObj->as<JSFunction>().hasResolvedName()) {
|
||||
if (!JSFunction::getUnresolvedName(cx, targetObj.as<JSFunction>(), &name))
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedString rootedName(cx);
|
||||
if (name) {
|
||||
rootedName = name;
|
||||
} else {
|
||||
// 19.2.3.2 Function.prototype.bind, steps 9-11.
|
||||
if (!name) {
|
||||
// 19.2.3.2 Function.prototype.bind, step 9.
|
||||
RootedValue targetName(cx);
|
||||
if (!GetProperty(cx, targetObj, targetObj, cx->names().name, &targetName))
|
||||
return false;
|
||||
|
||||
// 19.2.3.2 Function.prototype.bind, step 10.
|
||||
if (targetName.isString())
|
||||
rootedName = targetName.toString();
|
||||
if (targetName.isString() && !targetName.toString()->empty()) {
|
||||
name = AtomizeString(cx, targetName.toString());
|
||||
if (!name)
|
||||
return false;
|
||||
} else {
|
||||
name = cx->names().empty;
|
||||
}
|
||||
}
|
||||
|
||||
// 19.2.3.2 Function.prototype.bind, step 11 (Inlined SetFunctionName).
|
||||
MOZ_ASSERT(!bound->hasGuessedAtom());
|
||||
if (rootedName && !rootedName->empty()) {
|
||||
StringBuffer sb(cx);
|
||||
if (!sb.append(cx->names().boundWithSpace) || !sb.append(rootedName))
|
||||
return false;
|
||||
|
||||
RootedAtom nameAtom(cx, sb.finishAtom());
|
||||
if (!nameAtom)
|
||||
return false;
|
||||
|
||||
bound->setAtom(nameAtom);
|
||||
} else {
|
||||
bound->setAtom(cx->names().boundWithSpace);
|
||||
}
|
||||
bound->setAtom(name);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user