diff --git a/js/src/frontend/BinASTParserPerTokenizer.cpp b/js/src/frontend/BinASTParserPerTokenizer.cpp index fbdb4e5c6fa3..f42c85b39f86 100644 --- a/js/src/frontend/BinASTParserPerTokenizer.cpp +++ b/js/src/frontend/BinASTParserPerTokenizer.cpp @@ -261,10 +261,15 @@ JS::Result BinASTParserPerTokenizer::buildFunctionBox( // Allocate the function before walking down the tree. RootedFunction fun(cx_); - BINJS_TRY_VAR(fun, !pc_ ? lazyScript_->functionNonDelazifying() - : AllocNewFunction(cx_, atom, syntax, generatorKind, - functionAsyncKind)); - MOZ_ASSERT_IF(pc_, fun->explicitName() == atom); + if (pc_) { + Rooted fcd( + cx_, GenerateFunctionCreationData(atom, syntax, generatorKind, + functionAsyncKind)); + BINJS_TRY_VAR(fun, AllocNewFunction(cx_, fcd)); + MOZ_ASSERT(fun->explicitName() == atom); + } else { + BINJS_TRY_VAR(fun, lazyScript_->functionNonDelazifying()); + } mozilla::Maybe directives; if (pc_) { diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 08a66ae35c81..bec7290dde1e 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1966,21 +1966,10 @@ GeneralParser::functionBody(InHandling inHandling, return finishLexicalScope(pc_->varScope(), body, ScopeKind::FunctionLexical); } -JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom, - FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - bool isSelfHosting /* = false */, - bool inFunctionBox /* = false */) { - MOZ_ASSERT_IF(kind == FunctionSyntaxKind::Statement, atom != nullptr); - - RootedObject proto(cx); - if (!GetFunctionPrototype(cx, generatorKind, asyncKind, &proto)) { - return nullptr; - } - - RootedFunction fun(cx); - +FunctionCreationData GenerateFunctionCreationData( + HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, bool isSelfHosting /* = false */, + bool inFunctionBox /* = false */) { gc::AllocKind allocKind = gc::AllocKind::FUNCTION; FunctionFlags flags; bool isExtendedUnclonedSelfHostedFunctionName = @@ -2026,12 +2015,35 @@ JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom, : FunctionFlags::INTERPRETED_GENERATOR_OR_ASYNC); } - fun = NewFunctionWithProto(cx, nullptr, 0, flags, nullptr, atom, proto, - allocKind, TenuredObject); + return FunctionCreationData{atom, kind, generatorKind, asyncKind, + allocKind, flags, isSelfHosting}; +} + +HandleAtom FunctionCreationData::getAtom(JSContext* cx) const { + // We can create a handle here because atoms are traced + // by FunctionCreationData. + return HandleAtom::fromMarkedLocation(&atom); +} + +JSFunction* AllocNewFunction(JSContext* cx, + Handle dataHandle) { + // FunctionCreationData don't move, so it is safe to grab a reference + // out of the handle. + const FunctionCreationData& data = dataHandle.get(); + + RootedObject proto(cx); + if (!GetFunctionPrototype(cx, data.generatorKind, data.asyncKind, &proto)) { + return nullptr; + } + RootedFunction fun(cx); + + + fun = NewFunctionWithProto(cx, nullptr, 0, data.flags, nullptr, data.getAtom(cx), proto, + data.allocKind, TenuredObject); if (!fun) { return nullptr; } - if (isSelfHosting) { + if (data.isSelfHosting) { fun->setIsSelfHostedBuiltin(); MOZ_ASSERT(!fun->isInterpretedLazy()); } @@ -2041,8 +2053,11 @@ JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom, JSFunction* ParserBase::newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind) { - return AllocNewFunction(cx_, atom, kind, generatorKind, asyncKind, - options().selfHostingMode, pc_->isFunctionBox()); + Rooted fcd( + cx_, GenerateFunctionCreationData(atom, kind, generatorKind, asyncKind, + options().selfHostingMode, + pc_->isFunctionBox())); + return AllocNewFunction(cx_, fcd); } template diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 233631d3e46b..d48db0a3c7e0 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1895,12 +1895,32 @@ mozilla::Maybe NewLexicalScopeData( JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc, ParseContext* pc); -JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom, - FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - bool isSelfHosting = false, - bool inFunctionBox = false); +struct FunctionCreationData { + // The Parser uses KeepAtoms to prevent GC from collecting atoms + JSAtom* atom = nullptr; + FunctionSyntaxKind kind = FunctionSyntaxKind::Expression; + GeneratorKind generatorKind = GeneratorKind::NotGenerator; + FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; + + gc::AllocKind allocKind = gc::AllocKind::FUNCTION; + FunctionFlags flags = {}; + + bool isSelfHosting = false; + + HandleAtom getAtom(JSContext* cx) const; + + void trace(JSTracer* trc) { + TraceRoot(trc, &atom, "FunctionCreationData atom"); + } +}; + +FunctionCreationData GenerateFunctionCreationData( + HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, bool isSelfHosting = false, + bool inFunctionBox = false); + +JSFunction* AllocNewFunction(JSContext* cx, + Handle dataHandle); } /* namespace frontend */ } /* namespace js */