Bug 1913114 - wasm: Rename lazy tiering prefs and add pref that enables lazy tiering only for wasm-gc. r=yury

- Remove the experimental part of these flags.
 - Rename the overall flag to just talk about lazy_tiering.
 - Add a lazy_tiering_for_gc which enables this feature only for wasm-gc modules.

Differential Revision: https://phabricator.services.mozilla.com/D225124
This commit is contained in:
Ryan Hunt 2024-10-14 15:41:34 +00:00
parent eee7d68bcd
commit f98aa22df0
17 changed files with 76 additions and 43 deletions

View File

@ -189,15 +189,6 @@
/* flag force enable */ false, \
/* flag fuzz enable */ false, \
/* preference name */ test_serialization) \
FEATURE( \
/* capitalized name */ ExperimentalCompilePipeline, \
/* lower case name */ experimentalCompilePipeline, \
/* compile predicate */ true, \
/* compiler predicate */ true, \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* flag fuzz enable */ false, \
/* preference name */ experimental_compile_pipeline) \
FEATURE( \
/* capitalized name */ BranchHinting, \
/* lower case name */ branchHinting, \

View File

@ -1 +1 @@
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=-P wasm_experimental_compile_pipeline; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); include:wasm.js
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=-P wasm_lazy_tiering; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); include:wasm.js

View File

@ -1 +1 @@
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=-P wasm_experimental_compile_pipeline; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); test-also=--setpref=wasm_test_serialization=true; test-also=--wasm-compiler=optimizing --no-avx; skip-variant-if: --wasm-compiler=optimizing --no-avx, !getBuildConfiguration("x86") && !getBuildConfiguration("x64") || getBuildConfiguration("simulator"); include:wasm.js
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=-P wasm_lazy_tiering; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); test-also=--setpref=wasm_test_serialization=true; test-also=--wasm-compiler=optimizing --no-avx; skip-variant-if: --wasm-compiler=optimizing --no-avx, !getBuildConfiguration("x86") && !getBuildConfiguration("x64") || getBuildConfiguration("simulator"); include:wasm.js

View File

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled() || !wasmExperimentalCompilePipelineEnabled(); test-also=-P wasm_experimental_compile_pipeline;
// |jit-test| skip-if: !wasmGcEnabled() || !wasmExperimentalCompilePipelineEnabled(); test-also=-P wasm_lazy_tiering;
// Needs to be at least 13500 in order for test functions to tier up.
// See Instance::computeInitialHotnessCounter.

View File

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmExperimentalCompilePipelineEnabled() || !getBuildConfiguration("x64") || !hasDisassembler() || getBuildConfiguration("simulator"); test-also=-P wasm_experimental_compile_pipeline; include:codegen-x64-test.js
// |jit-test| skip-if: !wasmExperimentalCompilePipelineEnabled() || !getBuildConfiguration("x64") || !hasDisassembler() || getBuildConfiguration("simulator"); test-also=-P wasm_lazy_tiering; include:codegen-x64-test.js
assertEq(hasDisassembler(), true);

View File

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled(); test-also=-P wasm_experimental_compile_pipeline;
// |jit-test| skip-if: !wasmGcEnabled(); test-also=-P wasm_lazy_tiering;
let {a} = wasmEvalText(`(module
(type $t (func))

View File

@ -1 +1 @@
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=-P wasm_experimental_compile_pipeline; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); include:wasm.js
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=-P wasm_lazy_tiering; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); include:wasm.js

View File

@ -251,9 +251,8 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
// is open.
bool debug = cx->realm() && cx->realm()->debuggerObservesWasm();
bool forceTiering = cx->options().testWasmAwaitTier2() ||
JitOptions.wasmDelayTier2 ||
wasm::ExperimentalCompilePipelineAvailable(cx);
bool forceTiering =
cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2;
// The <Compiler>Available() predicates should ensure no failure here, but
// when we're fuzzing we allow inconsistent switches and the check may thus
@ -769,7 +768,7 @@ void CompilerEnvironment::computeParameters() {
state_ = Computed;
}
void CompilerEnvironment::computeParameters(Decoder& d) {
void CompilerEnvironment::computeParameters(const ModuleMetadata& moduleMeta) {
MOZ_ASSERT(!isComputed());
if (state_ == InitialWithModeTierDebug) {
@ -789,19 +788,18 @@ void CompilerEnvironment::computeParameters(Decoder& d) {
// Various constraints in various places should prevent failure here.
MOZ_RELEASE_ASSERT(baselineEnabled || ionEnabled);
uint32_t codeSectionSize = 0;
bool isGcModule = moduleMeta.codeMeta->types->hasGcType();
uint32_t codeSectionSize = moduleMeta.codeMeta->codeSectionSize();
SectionRange range;
if (StartsCodeSection(d.begin(), d.end(), &range)) {
codeSectionSize = range.size;
}
// We use lazy tiering if the 'for-all' pref is enabled, or the 'gc-only'
// pref is enabled and we're compiling a GC module.
bool lazyTiering = JS::Prefs::wasm_lazy_tiering() ||
(JS::Prefs::wasm_lazy_tiering_for_gc() && isGcModule);
if (baselineEnabled && hasSecondTier &&
(TieringBeneficial(codeSectionSize) || forceTiering) &&
(TieringBeneficial(codeSectionSize) || forceTiering || lazyTiering) &&
PlatformCanTier()) {
mode_ = args_->features.experimentalCompilePipeline
? CompileMode::LazyTiering
: CompileMode::EagerTiering;
mode_ = lazyTiering ? CompileMode::LazyTiering : CompileMode::EagerTiering;
tier_ = Tier::Baseline;
} else {
mode_ = CompileMode::Once;
@ -888,7 +886,7 @@ SharedModule wasm::CompileBuffer(const CompileArgs& args,
return nullptr;
}
CompilerEnvironment compilerEnv(args);
compilerEnv.computeParameters(d);
compilerEnv.computeParameters(*moduleMeta);
if (!moduleMeta->prepareForCompile(compilerEnv.mode())) {
return nullptr;
}
@ -1064,7 +1062,7 @@ SharedModule wasm::CompileStreaming(
if (!DecodeModuleEnvironment(d, &codeMeta, moduleMeta)) {
return nullptr;
}
compilerEnv.computeParameters(d);
compilerEnv.computeParameters(*moduleMeta);
if (!codeMeta.codeSection) {
d.fail("unknown section before code section");

View File

@ -300,7 +300,7 @@ struct CompilerEnvironment {
CompilerEnvironment(CompileMode mode, Tier tier, DebugEnabled debugEnabled);
// Compute any remaining compilation parameters.
void computeParameters(Decoder& d);
void computeParameters(const ModuleMetadata& moduleMeta);
// Compute any remaining compilation parameters. Only use this method if
// the CompilerEnvironment was created with values for mode, tier, and

View File

@ -303,8 +303,8 @@ bool wasm::CodeCachingAvailable(JSContext* cx) {
return false;
#else
// We temporarily don't support caching with our new compile pipeline
if (ExperimentalCompilePipelineAvailable(cx)) {
// TODO(bug 1913109): lazy tiering doesn't support serialization
if (JS::Prefs::wasm_lazy_tiering() || JS::Prefs::wasm_lazy_tiering_for_gc()) {
return false;
}

View File

@ -1394,8 +1394,7 @@ SharedModule ModuleGenerator::finishModule(
// Perform storeOptimizedEncoding here instead of below so we don't have to
// re-serialize the module.
if (maybeCompleteTier2Listener &&
codeMeta_->features().builtinModules.hasNone()) {
if (maybeCompleteTier2Listener && module->canSerialize()) {
maybeCompleteTier2Listener->storeOptimizedEncoding(
serializedBytes.begin(), serializedBytes.length());
maybeCompleteTier2Listener = nullptr;
@ -1405,7 +1404,7 @@ SharedModule ModuleGenerator::finishModule(
if (compileState_ == CompileState::EagerTier1) {
module->startTier2(bytecode, maybeCompleteTier2Listener);
} else if (tier() == Tier::Serialized && maybeCompleteTier2Listener &&
codeMeta_->features().builtinModules.hasNone()) {
module->canSerialize()) {
Bytes bytes;
if (module->serialize(&bytes)) {
maybeCompleteTier2Listener->storeOptimizedEncoding(bytes.begin(),

View File

@ -349,6 +349,13 @@ struct CodeMetadata : public ShareableBase<CodeMetadata> {
callRefHints[callRefIndex] = hint.toRepr();
}
size_t codeSectionSize() const {
if (codeSection) {
return codeSection->size;
}
return 0;
}
// This gets names for wasm only.
// For asm.js, see CodeMetadataForAsmJS::getFuncNameForAsmJS.
bool getFuncNameForWasm(NameContext ctx, uint32_t funcIndex,

View File

@ -184,8 +184,7 @@ bool Module::finishTier2(UniqueCodeBlock tier2CodeBlock,
// purposes so that wasmHasTier2CompilationCompleted() only returns true
// after tier-2 has been fully cached.
if (completeTier2Listener_ &&
code_->codeMeta().features().builtinModules.hasNone()) {
if (completeTier2Listener_ && canSerialize()) {
Bytes bytes;
if (serialize(&bytes)) {
completeTier2Listener_->storeOptimizedEncoding(bytes.begin(),

View File

@ -182,6 +182,7 @@ class Module : public JS::WasmModule {
// Code caching support.
bool canSerialize() const;
[[nodiscard]] bool serialize(Bytes* bytes) const;
static RefPtr<Module> deserialize(const uint8_t* begin, size_t size);
bool loggingDeserialized() const { return loggingDeserialized_; }

View File

@ -1479,6 +1479,14 @@ CoderResult CodeModule(Coder<mode>& coder, CoderArg<mode, Module> item) {
} // namespace wasm
} // namespace js
bool Module::canSerialize() const {
// TODO(bug 1903131): JS string builtins don't support serialization
// TODO(bug 1913109): lazy tiering doesn't support serialization
return code_->mode() != CompileMode::LazyTiering &&
codeMeta().features().builtinModules.hasNone() &&
!codeMeta().debugEnabled;
}
static bool GetSerializedSize(const Module& module, size_t* size) {
Coder<MODE_SIZE> coder(module.codeMeta().types.get());
auto result = CodeModule(coder, &module);
@ -1490,7 +1498,7 @@ static bool GetSerializedSize(const Module& module, size_t* size) {
}
bool Module::serialize(Bytes* bytes) const {
MOZ_RELEASE_ASSERT(!codeMeta().debugEnabled);
MOZ_RELEASE_ASSERT(canSerialize());
MOZ_RELEASE_ASSERT(code_->hasCompleteTier(Tier::Serialized));
size_t serializedSize;

View File

@ -701,6 +701,8 @@ class TypeDef {
bool isArrayType() const { return kind_ == TypeDefKind::Array; }
bool isGcType() const { return isStructType() || isArrayType(); }
const FuncType& funcType() const {
MOZ_ASSERT(isFuncType());
return funcType_;
@ -1052,6 +1054,16 @@ class RecGroup : public AtomicRefCounted<RecGroup> {
return (uint32_t)groupTypeIndex;
}
bool hasGcType() const {
for (uint32_t groupTypeIndex = 0; groupTypeIndex < numTypes();
groupTypeIndex++) {
if (type(groupTypeIndex).isGcType()) {
return true;
}
}
return false;
}
HashNumber hash() const {
HashNumber hn = 0;
for (uint32_t i = 0; i < numTypes(); i++) {
@ -1188,8 +1200,7 @@ class TypeContext : public AtomicRefCounted<TypeContext> {
return true;
}
// Finish creation of a recursion group after type definitions have been
// initialized. This must be paired with `startGroup`.
// Add a pre-existing recursion group to this type context.
[[nodiscard]] bool addRecGroup(SharedRecGroup recGroup) {
// We must not have a pending group
MOZ_ASSERT(!pendingRecGroup_);
@ -1236,6 +1247,15 @@ class TypeContext : public AtomicRefCounted<TypeContext> {
const SharedRecGroupVector& groups() const { return recGroups_; }
bool hasGcType() const {
for (const SharedRecGroup& recGroup : groups()) {
if (recGroup->hasGcType()) {
return true;
}
}
return false;
}
// Map from type definition to index
uint32_t indexOf(const TypeDef& typeDef) const {

View File

@ -8368,11 +8368,21 @@
mirror: always
set_spidermonkey_pref: always
- name: javascript.options.wasm_experimental_compile_pipeline
# Enables lazy tiering for wasm modules that have a GC type defined in them.
# Use wasm_lazy_tiering to enable it for any module.
- name: javascript.options.wasm_lazy_tiering_for_gc
type: bool
value: false
mirror: always
set_spidermonkey_pref: startup
set_spidermonkey_pref: always
# Enables lazy tiering for all modules. Use wasm_lazy_tiering_for_gc to only
# enable this for GC modules.
- name: javascript.options.wasm_lazy_tiering
type: bool
value: false
mirror: always
set_spidermonkey_pref: always
- name: javascript.options.wasm_experimental_inline_call_ref_threshold
type: uint32_t