Backed out 3 changesets (bug 1760334) for causing SM bustages in ScopeBindingCache.h CLOSED TREE

Backed out changeset 5a4374cfd962 (bug 1760334)
Backed out changeset bbd5d4b8e2eb (bug 1760334)
Backed out changeset 998204890aed (bug 1760334)
This commit is contained in:
Noemi Erli 2023-06-02 15:39:26 +03:00
parent 1be0689607
commit 7dd99b8a08
5 changed files with 14 additions and 210 deletions

View File

@ -64,12 +64,6 @@ class ScriptStencilIterable;
struct InputName;
class ScopeBindingCache;
// When delazifying modules' inner functions, the actual global scope is used.
// However, when doing a delazification the global scope is not available. We
// use this dummy type to be a placeholder to be used as part of the InputScope
// variants to mimic what the Global scope would be used for.
struct FakeStencilGlobalScope {};
// Reference to a Scope within a CompilationStencil.
struct ScopeStencilRef {
const CompilationStencil& context_;
@ -86,17 +80,13 @@ struct ScopeStencilRef {
// scope, such as the enclosingScope at the end of a scope chain. See `isNull`
// helper.
class InputScope {
using InputScopeStorage =
mozilla::Variant<Scope*, ScopeStencilRef, FakeStencilGlobalScope>;
using InputScopeStorage = mozilla::Variant<Scope*, ScopeStencilRef>;
InputScopeStorage scope_;
public:
// Create an InputScope given an instantiated scope.
explicit InputScope(Scope* ptr) : scope_(ptr) {}
// Create an InputScope for a global.
explicit InputScope(FakeStencilGlobalScope global) : scope_(global) {}
// Create an InputScope given a CompilationStencil and the ScopeIndex which is
// an offset within the same CompilationStencil given as argument.
InputScope(const CompilationStencil& context, ScopeIndex scopeIndex)
@ -135,24 +125,19 @@ class InputScope {
bool isNull() const {
return scope_.match(
[](const Scope* ptr) { return !ptr; },
[](const ScopeStencilRef& ref) { return !ref.scopeIndex_.isValid(); },
[](const FakeStencilGlobalScope&) { return false; });
[](const ScopeStencilRef& ref) { return !ref.scopeIndex_.isValid(); });
}
ScopeKind kind() const {
return scope_.match(
[](const Scope* ptr) { return ptr->kind(); },
[](const ScopeStencilRef& ref) { return ref.scope().kind(); },
[](const FakeStencilGlobalScope&) { return ScopeKind::Global; });
[](const ScopeStencilRef& ref) { return ref.scope().kind(); });
};
bool hasEnvironment() const {
return scope_.match(
[](const Scope* ptr) { return ptr->hasEnvironment(); },
[](const ScopeStencilRef& ref) { return ref.scope().hasEnvironment(); },
[](const FakeStencilGlobalScope&) {
// See Scope::hasEnvironment
return true;
});
return scope_.match([](const Scope* ptr) { return ptr->hasEnvironment(); },
[](const ScopeStencilRef& ref) {
return ref.scope().hasEnvironment();
});
};
inline InputScope enclosing() const;
bool hasOnChain(ScopeKind kind) const {
@ -165,19 +150,12 @@ class InputScope {
if (scope.kind() == kind) {
return true;
}
if (scope.kind() == ScopeKind::Module &&
kind == ScopeKind::Global) {
return true;
}
if (!scope.hasEnclosing()) {
break;
}
new (&it) ScopeStencilRef{ref.context_, scope.enclosing()};
}
return false;
},
[=](const FakeStencilGlobalScope&) {
return kind == ScopeKind::Global;
});
}
uint32_t environmentChainLength() const {
@ -192,32 +170,16 @@ class InputScope {
scope.kind() != ScopeKind::NonSyntactic) {
length++;
}
if (scope.kind() == ScopeKind::Module) {
// Stencil do not encode the Global scope, as it used to be
// assumed to already exists. As moving delazification off-thread,
// we need to materialize a fake-stencil version of the Global
// Scope.
MOZ_ASSERT(!scope.hasEnclosing());
length += js::ModuleScope::EnclosingEnvironmentChainLength;
}
if (!scope.hasEnclosing()) {
break;
}
new (&it) ScopeStencilRef{ref.context_, scope.enclosing()};
}
return length;
},
[=](const FakeStencilGlobalScope&) {
// Stencil-based delazification needs to calculate
// environmentChainLength where the global is not available.
//
// The FakeStencilGlobalScope is used to represent what the global
// would be if we had access to it while delazifying.
return uint32_t(js::ModuleScope::EnclosingEnvironmentChainLength);
});
}
void trace(JSTracer* trc);
bool isStencil() const { return !scope_.is<Scope*>(); };
bool isStencil() const { return scope_.is<ScopeStencilRef>(); };
// Various accessors which are valid only when the InputScope is a
// FunctionScope. Some of these accessors are returning values associated with
@ -396,10 +358,6 @@ struct InputName {
InputName(const ScriptStencilRef& script, TaggedParserAtomIndex index)
: variant_(NameStencilRef{script.context_, index}) {}
// Dummy for empty global.
InputName(const FakeStencilGlobalScope&, TaggedParserAtomIndex)
: variant_(static_cast<JSAtom*>(nullptr)) {}
// The InputName is either from an instantiated name, or from another
// CompilationStencil. This method interns the current name in the parser atom
// table of a CompilationState, which has a corresponding CompilationInput.
@ -1824,15 +1782,8 @@ InputScope InputScope::enclosing() const {
if (ref.scope().hasEnclosing()) {
return InputScope(ref.context_, ref.scope().enclosing());
}
// The global scope is not known by the Stencil, while parsing inner
// functions from Stencils where they are known at the execution using
// the GlobalScope.
if (ref.scope().kind() == ScopeKind::Module) {
return InputScope(FakeStencilGlobalScope{});
}
return InputScope(nullptr);
},
[](const FakeStencilGlobalScope&) { return InputScope(nullptr); });
});
}
FunctionFlags InputScope::functionFlags() const {
@ -1846,9 +1797,6 @@ FunctionFlags InputScope::functionFlags() const {
ScriptIndex scriptIndex = ref.scope().functionIndex();
ScriptStencil& data = ref.context_.scriptData[scriptIndex];
return data.functionFlags;
},
[](const FakeStencilGlobalScope&) -> FunctionFlags {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("No functionFlags on global.");
});
}
@ -1863,9 +1811,6 @@ ImmutableScriptFlags InputScope::immutableFlags() const {
ScriptIndex scriptIndex = ref.scope().functionIndex();
ScriptStencilExtra& extra = ref.context_.scriptExtra[scriptIndex];
return extra.immutableFlags;
},
[](const FakeStencilGlobalScope&) -> ImmutableScriptFlags {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("No immutableFlags on global.");
});
}
@ -1880,10 +1825,6 @@ MemberInitializers InputScope::getMemberInitializers() const {
ScriptIndex scriptIndex = ref.scope().functionIndex();
ScriptStencilExtra& extra = ref.context_.scriptExtra[scriptIndex];
return extra.memberInitializers();
},
[](const FakeStencilGlobalScope&) -> MemberInitializers {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
"No getMemberInitializers on global.");
});
}

View File

@ -26,7 +26,6 @@ namespace frontend {
struct CompilationAtomCache;
struct CompilationStencil;
struct ScopeStencilRef;
struct FakeStencilGlobalScope;
struct CompilationStencilMerger;
// Generic atom wrapper which provides a way to interpret any Atom given
@ -82,10 +81,6 @@ struct GenericAtom {
// already compiled script.
GenericAtom(const CompilationStencil& context, TaggedParserAtomIndex index);
GenericAtom(ScopeStencilRef& scope, TaggedParserAtomIndex index);
GenericAtom(const FakeStencilGlobalScope& scope, TaggedParserAtomIndex index)
: ref((JSAtom*)nullptr) {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE();
}
// Constructor for atoms managed by the Garbage Collector, while providing
// contextual scope information when delazifying functions on the main thread.
@ -110,10 +105,6 @@ struct BindingHasher<TaggedParserAtomIndex> {
GenericAtom other;
Lookup(ScopeStencilRef& scope_ref, const GenericAtom& other);
Lookup(const FakeStencilGlobalScope& scope_ref, const GenericAtom& other)
: keyStencil(*(const CompilationStencil*)nullptr), other(other) {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE();
}
};
static HashNumber hash(const Lookup& aLookup) { return aLookup.other.hash; }
@ -186,15 +177,12 @@ class ScopeBindingCache {
// of scope given as arguments.
virtual bool canCacheFor(Scope* ptr);
virtual bool canCacheFor(ScopeStencilRef ref);
virtual bool canCacheFor(const FakeStencilGlobalScope& ref);
// Create a new BindingMap cache for a given scope. This cache should then be
// filled with all names which might be looked up.
virtual BindingMap<JSAtom*>* createCacheFor(Scope* ptr);
virtual BindingMap<TaggedParserAtomIndex>* createCacheFor(
ScopeStencilRef ref);
virtual BindingMap<TaggedParserAtomIndex>* createCacheFor(
const FakeStencilGlobalScope& ref);
// Return the BindingMap created for the associated scope, unless the
// generation value does not match the one stored internally, in which case a
@ -202,8 +190,6 @@ class ScopeBindingCache {
virtual BindingMap<JSAtom*>* lookupScope(Scope* ptr, CacheGeneration gen);
virtual BindingMap<TaggedParserAtomIndex>* lookupScope(ScopeStencilRef ref,
CacheGeneration gen);
virtual BindingMap<TaggedParserAtomIndex>* lookupScope(
const FakeStencilGlobalScope& ref, CacheGeneration gen);
};
// NoScopeBindingCache is a no-op which does not implement a ScopeBindingCache.
@ -216,7 +202,6 @@ class NoScopeBindingCache final : public ScopeBindingCache {
bool canCacheFor(Scope* ptr) override;
bool canCacheFor(ScopeStencilRef ref) override;
bool canCacheFor(const FakeStencilGlobalScope& ref) override;
};
// StencilScopeBindingCache provides an interface to cache the bindings provided
@ -248,17 +233,10 @@ class MOZ_STACK_CLASS StencilScopeBindingCache final
CacheGeneration getCurrentGeneration() const override { return 1; }
bool canCacheFor(ScopeStencilRef ref) override;
bool canCacheFor(const FakeStencilGlobalScope& ref) override;
BindingMap<TaggedParserAtomIndex>* createCacheFor(
ScopeStencilRef ref) override;
BindingMap<TaggedParserAtomIndex>* createCacheFor(
const FakeStencilGlobalScope& ref) override;
BindingMap<TaggedParserAtomIndex>* lookupScope(ScopeStencilRef ref,
CacheGeneration gen) override;
BindingMap<TaggedParserAtomIndex>* lookupScope(
const FakeStencilGlobalScope& ref, CacheGeneration gen) override;
};
// RuntimeScopeBindingCache is used to hold the binding map for each scope which

View File

@ -86,10 +86,6 @@ static ParserBindingIter InputBindingIter(const ScopeStencilRef& ref) {
return ParserBindingIter(ref);
}
static ParserBindingIter InputBindingIter(const FakeStencilGlobalScope&) {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("No bindings on empty global.");
}
InputName InputScript::displayAtom() const {
return script_.match(
[](BaseScript* ptr) {
@ -269,10 +265,6 @@ bool ScopeBindingCache::canCacheFor(ScopeStencilRef ref) {
MOZ_CRASH("Unexpected scope chain type: ScopeStencilRef");
}
bool ScopeBindingCache::canCacheFor(const FakeStencilGlobalScope& ref) {
MOZ_CRASH("Unexpected scope chain type: FakeStencilGlobalScope");
}
BindingMap<JSAtom*>* ScopeBindingCache::createCacheFor(Scope* ptr) {
MOZ_CRASH("Unexpected scope chain type: Scope*");
}
@ -292,24 +284,10 @@ BindingMap<TaggedParserAtomIndex>* ScopeBindingCache::lookupScope(
MOZ_CRASH("Unexpected scope chain type: ScopeStencilRef");
}
BindingMap<TaggedParserAtomIndex>* ScopeBindingCache::createCacheFor(
const FakeStencilGlobalScope& ref) {
MOZ_CRASH("Unexpected scope chain type: FakeStencilGlobalScope");
}
BindingMap<TaggedParserAtomIndex>* ScopeBindingCache::lookupScope(
const FakeStencilGlobalScope& ref, CacheGeneration gen) {
MOZ_CRASH("Unexpected scope chain type: FakeStencilGlobalScope");
}
bool NoScopeBindingCache::canCacheFor(Scope* ptr) { return false; }
bool NoScopeBindingCache::canCacheFor(ScopeStencilRef ref) { return false; }
bool NoScopeBindingCache::canCacheFor(const FakeStencilGlobalScope& ref) {
return false;
}
bool RuntimeScopeBindingCache::canCacheFor(Scope* ptr) { return true; }
BindingMap<JSAtom*>* RuntimeScopeBindingCache::createCacheFor(Scope* ptr) {
@ -362,34 +340,6 @@ BindingMap<TaggedParserAtomIndex>* StencilScopeBindingCache::lookupScope(
return &ptr->value();
}
static AbstractBaseScopeData<TaggedParserAtomIndex>
moduleGlobalAbstractScopeData;
bool StencilScopeBindingCache::canCacheFor(const FakeStencilGlobalScope& ref) {
return true;
}
BindingMap<TaggedParserAtomIndex>* StencilScopeBindingCache::createCacheFor(
const FakeStencilGlobalScope& ref) {
auto* dataPtr = &moduleGlobalAbstractScopeData;
BindingMap<TaggedParserAtomIndex> bindingCache;
if (!scopeMap.putNew(dataPtr, std::move(bindingCache))) {
return nullptr;
}
return lookupScope(ref, 1);
}
BindingMap<TaggedParserAtomIndex>* StencilScopeBindingCache::lookupScope(
const FakeStencilGlobalScope& ref, CacheGeneration gen) {
auto* dataPtr = &moduleGlobalAbstractScopeData;
auto ptr = scopeMap.lookup(dataPtr);
if (!ptr) {
return nullptr;
}
return &ptr->value();
}
bool ScopeContext::init(FrontendContext* fc, CompilationInput& input,
ParserAtomsTable& parserAtoms,
ScopeBindingCache* scopeCache, InheritThis inheritThis,
@ -949,11 +899,6 @@ static bool IsPrivateField(ScopeStencilRef& scope, TaggedParserAtomIndex atom) {
return false;
}
static bool IsPrivateField(const FakeStencilGlobalScope&,
TaggedParserAtomIndex) {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("No private fields on empty global.");
}
bool ScopeContext::cachePrivateFieldsForEval(FrontendContext* fc,
CompilationInput& input,
JSObject* enclosingEnvironment,
@ -1017,12 +962,6 @@ static bool NameIsOnEnvironment(FrontendContext* fc,
InputScope& scope, TaggedParserAtomIndex name) {
JSAtom* jsname = nullptr;
return scope.match([&](auto& scope_ref) {
if (std::is_same_v<decltype(scope_ref), FakeStencilGlobalScope&>) {
// This condition is added to handle the FakeStencilGlobalScope which is
// used to emulate the global object when delazifying while executing, and
// which is not provided by the Stencil.
return true;
}
for (auto bi = InputBindingIter(scope_ref); bi; bi++) {
// If found, the name must already be on the environment or an import,
// or else there is a bug in the closed-over name analysis in the

View File

@ -1,35 +0,0 @@
// |jit-test| skip-if: helperThreadCount() === 0 || isLcovEnabled()
const eagerOptions = {
fileName: "certViewer.js",
lineNumber: 1,
eagerDelazificationStrategy: "OnDemandOnly",
};
const concurrentOptions = {
fileName: "certViewer.js",
lineNumber: 1,
eagerDelazificationStrategy: "ConcurrentDepthFirst",
};
// Check that `undefined` is properly resolved to the global scope.
let script = `
function certDecoderInitializer() {
return undefined;
}
let result = certDecoderInitializer();
export { result };
`;
function evalModule(source, opts) {
let job = offThreadCompileModuleToStencil(source, opts);
let stencil = finishOffThreadStencil(job);
let m = instantiateModuleStencil(stencil);
moduleLink(m);
moduleEvaluate(m)
return m.result;
}
assertEq(evalModule(script, eagerOptions), undefined);
assertEq(evalModule(script, concurrentOptions), undefined);

View File

@ -5877,12 +5877,10 @@ static bool OffThreadCompileModuleToStencil(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "offThreadCompileModuleToStencil", 1)) {
return false;
}
if (!args[0].isString()) {
const char* typeName = InformalValueTypeName(args[0]);
JS_ReportErrorASCII(cx, "expected string to parse, got %s", typeName);
if (args.length() != 1 || !args[0].isString()) {
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr,
JSSMSG_INVALID_ARGS,
"offThreadCompileModuleToStencil");
return false;
}
@ -5890,23 +5888,6 @@ static bool OffThreadCompileModuleToStencil(JSContext* cx, unsigned argc,
CompileOptions options(cx);
options.setIntroductionType("js shell offThreadCompileModuleToStencil")
.setFileAndLine("<string>", 1);
if (args.length() >= 2) {
if (!args[1].isObject()) {
JS_ReportErrorASCII(cx,
"offThreadCompileModuleToStencil: The 2nd argument "
"must be an object");
return false;
}
// Offthread compilation requires that the debug metadata be set when the
// script is collected from offthread, rather than when compiled.
RootedObject opts(cx, &args[1].toObject());
if (!js::ParseCompileOptions(cx, options, opts, &fileNameBytes)) {
return false;
}
}
options.setIsRunOnce(true).setSourceIsLazy(false);
options.forceAsync = true;
@ -8989,7 +8970,7 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
" Check the syntax of a string, returning success value"),
JS_FN_HELP("offThreadCompileModuleToStencil", OffThreadCompileModuleToStencil, 1, 0,
"offThreadCompileModuleToStencil(code[, options])",
"offThreadCompileModuleToStencil(code)",
" Compile |code| on a helper thread, returning a job ID. To wait for the\n"
" compilation to finish and and get the module stencil object call\n"
" |finishOffThreadStencil| passing the job ID."),