summaryrefslogtreecommitdiff
path: root/js/src/vm/SelfHosting.cpp
diff options
context:
space:
mode:
authorMartok <martok@martoks-place.de>2023-07-13 02:47:15 +0200
committerMartok <martok@martoks-place.de>2023-07-13 13:57:43 +0200
commit3c37b8857d906942a06ec926dbc52f3a4a428d3e (patch)
tree10db62e356df40688ecdd50792ce39d27e64057d /js/src/vm/SelfHosting.cpp
parent1eccb6f42ad7ee5ef887079d0a8a16e8f1ff9d50 (diff)
downloaduxp-3c37b8857d906942a06ec926dbc52f3a4a428d3e.tar.gz
Issue #2271 - Use declared names of self-hosted functions for cloning
Ensure that cloning a self-hosted function always has access to the declared name from the source and that it doesn't get lost on successive clones. This is done by storing the declared name in an extended slot on rename, and cloning it with the function. Based-on: m-c 1546232
Diffstat (limited to 'js/src/vm/SelfHosting.cpp')
-rw-r--r--js/src/vm/SelfHosting.cpp69
1 files changed, 44 insertions, 25 deletions
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
index c1276f5a43..de497d02e1 100644
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -903,6 +903,22 @@ intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc, Value* vp)
return true;
}
+JSAtom*
+js::GetSelfHostedFunctionName(JSFunction* fun)
+{
+ Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
+ if (!name.isString()) {
+ return nullptr;
+ }
+ return &name.toString()->asAtom();
+}
+
+static void
+SetSelfHostedFunctionName(JSFunction* fun, JSAtom* name)
+{
+ fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(name));
+}
+
static bool
intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
{
@@ -915,10 +931,18 @@ intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
if (!atom)
return false;
+ // _SetCanonicalName can only be called on top-level function declarations.
+ MOZ_ASSERT(fun->kind() == JSFunction::NormalFunction);
+ MOZ_ASSERT(!fun->isLambda());
+
+ // It's an error to call _SetCanonicalName multiple times.
+ MOZ_ASSERT(!GetSelfHostedFunctionName(fun));
+
+ // Set the lazy function name so we can later retrieve the script from the
+ // self-hosting global.
+ SetSelfHostedFunctionName(fun, fun->explicitName());
fun->setAtom(atom);
-#ifdef DEBUG
- fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(true));
-#endif
+
args.rval().setUndefined();
return true;
}
@@ -2910,13 +2934,11 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
if (selfHostedObject->is<JSFunction>()) {
RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>());
if (selfHostedFunction->isInterpreted()) {
- bool hasName = selfHostedFunction->explicitName() != nullptr;
-
// Arrow functions use the first extended slot for their lexical |this| value.
- MOZ_ASSERT(!selfHostedFunction->isArrow());
- js::gc::AllocKind kind = hasName
- ? gc::AllocKind::FUNCTION_EXTENDED
- : selfHostedFunction->getAllocKind();
+ // And methods use the first extended slot for their home-object.
+ // We only expect to see normal functions here.
+ MOZ_ASSERT(selfHostedFunction->kind() == JSFunction::NormalFunction);
+ js::gc::AllocKind kind = selfHostedFunction->getAllocKind();
Handle<GlobalObject*> global = cx->global();
Rooted<LexicalEnvironmentObject*> globalLexical(cx, &global->lexicalEnvironment());
@@ -2925,10 +2947,16 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
clone = CloneFunctionAndScript(cx, selfHostedFunction, globalLexical, emptyGlobalScope,
kind);
// To be able to re-lazify the cloned function, its name in the
- // self-hosting compartment has to be stored on the clone.
- if (clone && hasName) {
- clone->as<JSFunction>().setExtendedSlot(LAZY_FUNCTION_NAME_SLOT,
- StringValue(selfHostedFunction->explicitName()));
+ // self-hosting compartment has to be stored on the clone. Re-lazification
+ // is only possible if this isn't a function expression.
+ if (clone && !selfHostedFunction->isLambda()) {
+ // If |_SetCanonicalName| was called on the function, the self-hosted
+ // name is stored in the extended slot.
+ JSAtom* name = GetSelfHostedFunctionName(selfHostedFunction);
+ if (!name) {
+ name = selfHostedFunction->explicitName();
+ }
+ SetSelfHostedFunctionName(&clone->as<JSFunction>(), name);
}
} else {
clone = CloneSelfHostingIntrinsic(cx, selfHostedFunction);
@@ -3016,7 +3044,7 @@ JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName s
if (!selfHostedFun->isClassConstructor() && !selfHostedFun->hasGuessedAtom() &&
selfHostedFun->explicitName() != selfHostedName)
{
- MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
+ MOZ_ASSERT(GetSelfHostedFunctionName(selfHostedFun) == selfHostedName);
funName = selfHostedFun->explicitName();
}
@@ -3025,7 +3053,7 @@ JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName s
if (!fun)
return false;
fun->setIsSelfHostedBuiltin();
- fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
+ SetSelfHostedFunctionName(fun, selfHostedName);
return true;
}
@@ -3111,7 +3139,7 @@ JSRuntime::assertSelfHostedFunctionHasCanonicalName(JSContext* cx, HandlePropert
#ifdef DEBUG
JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, name);
MOZ_ASSERT(selfHostedFun);
- MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
+ MOZ_ASSERT(GetSelfHostedFunctionName(selfHostedFun) == name);
#endif
}
@@ -3133,15 +3161,6 @@ js::IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name)
return fun->isSelfHostedBuiltin() && GetSelfHostedFunctionName(fun) == name;
}
-JSAtom*
-js::GetSelfHostedFunctionName(JSFunction* fun)
-{
- Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
- if (!name.isString())
- return nullptr;
- return &name.toString()->asAtom();
-}
-
static_assert(JSString::MAX_LENGTH <= INT32_MAX,
"StringIteratorNext in builtin/String.js assumes the stored index "
"into the string is an Int32Value");