Bug 1566427 - Improved compiler availability computation. r=bbouvier

This patch cleans up wasm compiler selection and a few related things
with as few semantic changes as possible.  The intent is to centralize
compiler availability computation so that all parts of the system stay
in sync and it is easy to change compiler selection policy.

First, we introduce new predicates <Compiler>Available(cx) to test for
the actual availability of a compiler.  These predicates take into
account whether a compiler is compiled into the executable, whether it
supports the hardware, whether it is (currently) selected by
options/switches, and whether it can be used as a result of the
runtime environment (for example, Ion and Cranelift are not available
if the debugger is observing the page or if the GC feature is enabled;
Cranelift is not available if shared memory and atomics are enabled).
We switch to using these predicates almost everywhere that used
<Compiler>CanCompile() or cx->options().wasm<Compiler>(), since those
don't tell the full story.

Second, we implement a priority order of the optimizing compilers and
make it easy to change this order (see comments in code).  At the
moment, Cranelift is prioritized over Ion since Ion is enabled by
default and Cranelift is not; thus the desire of somebody flipping the
pref for Cranelift is to deselect Ion.  The priority order may change
in the future or may become platform-dependent.  The default compiler
selection in both browser and shell remains Baseline+Ion.

Third, we rename HasCompilerSupport() as HasPlatformSupport(), since
the predicate does not test whether compilers are available, only
whether they are present in the executable and support the hardware.
And to make that more sensible, <Compiler>CanCompile() is renamed
as <Compiler>PlatformSupport().

Fourth, we remove some redundant testing predicates (we don't need
both wasmDebugSupport and wasmDebuggingIsSupported, nor do we need
wasmUsesCranelift because wasmCompileMode is more reliable).

Fifth, we introduce a few new test cases that try to ensure that
compiler selection works as it should.  These are white-box and may
need to change if the compiler priority order changes.

Sixth, we rename the internal wasm::Has<Feature>Support() predicates
as wasm::<Feature>Available(), since they all actually test for
compiler availability.

Differential Revision: https://phabricator.services.mozilla.com/D64946

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Lars T Hansen 2020-03-11 15:03:45 +00:00
Родитель 07bea826cd
Коммит edf764eeec
34 изменённых файлов: 485 добавлений и 258 удалений

Просмотреть файл

@ -474,6 +474,9 @@ set_define('MOZ_RUST_SIMD', rust_simd)
# Experimental support for wasm code generation with Cranelift
#
# Note, you may have to disable features not supported by Cranelift
# (multi-value, threads) to make Cranelift actually available
# ==============================================================
js_option('--enable-cranelift',
@ -590,6 +593,7 @@ set_define('WASM_PRIVATE_REFTYPES', depends_if('--enable-wasm-private-reftypes')
# Support for the WebAssembly multi-value proposal.
# Do not remove until Cranelift supports multi-value.
# =====================================================
@depends(milestone.is_nightly, building_js)
@ -604,6 +608,27 @@ js_option('--enable-wasm-multi-value',
set_config('ENABLE_WASM_MULTI_VALUE', depends_if('--enable-wasm-multi-value')(lambda x: True))
set_define('ENABLE_WASM_MULTI_VALUE', depends_if('--enable-wasm-multi-value')(lambda x: True))
# Support for WebAssembly shared memory and atomics.
#
# This affects the JS shell only and here to allow the use of
# Cranelift in the shell. Once Cranelift supports shared memory
# and atomics it can go away.
# =====================================================
@depends(milestone.is_nightly)
def default_wasm_threads(is_nightly):
return is_nightly
js_option('--enable-wasm-threads',
default=default_wasm_threads,
help='{Enable|Disable} WebAssembly shared memory and atomics')
set_config('ENABLE_WASM_THREADS', depends_if('--enable-wasm-threads')(lambda x: True))
set_define('ENABLE_WASM_THREADS', depends_if('--enable-wasm-threads')(lambda x: True))
# Initial support for new regexp engine
# ==================================================

Просмотреть файл

@ -85,7 +85,9 @@
#include "vm/TraceLogging.h"
#include "wasm/AsmJS.h"
#include "wasm/WasmBaselineCompile.h"
#include "wasm/WasmCraneliftCompile.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmIonCompile.h"
#include "wasm/WasmJS.h"
#include "wasm/WasmModule.h"
#include "wasm/WasmSignalHandlers.h"
@ -718,25 +720,25 @@ static bool WasmIsSupported(JSContext* cx, unsigned argc, Value* vp) {
static bool WasmIsSupportedByHardware(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasCompilerSupport(cx));
args.rval().setBoolean(wasm::HasPlatformSupport(cx));
return true;
}
static bool WasmDebuggingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasSupport(cx) && cx->options().wasmBaseline());
args.rval().setBoolean(wasm::HasSupport(cx) && wasm::BaselineAvailable(cx));
return true;
}
static bool WasmStreamingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasStreamingSupport(cx));
args.rval().setBoolean(wasm::StreamingCompilationAvailable(cx));
return true;
}
static bool WasmCachingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasCachingSupport(cx));
args.rval().setBoolean(wasm::CodeCachingAvailable(cx));
return true;
}
@ -750,26 +752,9 @@ static bool WasmHugeMemoryIsSupported(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
static bool WasmUsesCranelift(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
#ifdef ENABLE_WASM_CRANELIFT
bool usesCranelift = cx->options().wasmCranelift();
#else
bool usesCranelift = false;
#endif
args.rval().setBoolean(usesCranelift);
return true;
}
static bool WasmThreadsSupported(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
bool isSupported = wasm::HasSupport(cx);
#ifdef ENABLE_WASM_CRANELIFT
if (cx->options().wasmCranelift()) {
isSupported = false;
}
#endif
args.rval().setBoolean(isSupported);
args.rval().setBoolean(wasm::ThreadsAvailable(cx));
return true;
}
@ -787,47 +772,69 @@ static bool WasmBulkMemSupported(JSContext* cx, unsigned argc, Value* vp) {
static bool WasmReftypesEnabled(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasReftypesSupport(cx));
args.rval().setBoolean(wasm::ReftypesAvailable(cx));
return true;
}
static bool WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasGcSupport(cx));
args.rval().setBoolean(wasm::GcTypesAvailable(cx));
return true;
}
static bool WasmMultiValueEnabled(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasMultiValueSupport(cx));
args.rval().setBoolean(wasm::MultiValuesAvailable(cx));
return true;
}
static bool WasmBigIntEnabled(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasI64BigIntSupport(cx));
args.rval().setBoolean(wasm::I64BigIntConversionAvailable(cx));
return true;
}
static bool WasmDebugSupport(JSContext* cx, unsigned argc, Value* vp) {
static bool WasmCompilersPresent(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(cx->options().wasmBaseline() &&
wasm::BaselineCanCompile());
char buf[256];
*buf = 0;
if (wasm::BaselinePlatformSupport()) {
strcat(buf, "baseline");
}
if (wasm::IonPlatformSupport()) {
if (*buf) {
strcat(buf, ",");
}
strcat(buf, "ion");
}
if (wasm::CraneliftPlatformSupport()) {
if (*buf) {
strcat(buf, ",");
}
strcat(buf, "cranelift");
}
JSString* result = JS_NewStringCopyZ(cx, buf);
if (!result) {
return false;
}
args.rval().setString(result);
return true;
}
static bool WasmCompileMode(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
bool baseline = cx->options().wasmBaseline();
bool ion = cx->options().wasmIon();
#ifdef ENABLE_WASM_CRANELIFT
bool cranelift = cx->options().wasmCranelift();
#else
bool cranelift = false;
#endif
// This triplet of predicates will select zero or one baseline compiler and
// zero or one optimizing compiler.
bool baseline = wasm::BaselineAvailable(cx);
bool ion = wasm::IonAvailable(cx);
bool cranelift = wasm::CraneliftAvailable(cx);
MOZ_ASSERT(!(ion && cranelift));
// We default to ion if nothing is enabled, as does the Wasm compiler.
JSString* result;
if (!wasm::HasSupport(cx)) {
result = JS_NewStringCopyZ(cx, "none");
@ -851,6 +858,45 @@ static bool WasmCompileMode(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
static bool WasmCraneliftDisabledByFeatures(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
bool isDisabled = false;
JSStringBuilder reason(cx);
if (!wasm::CraneliftDisabledByFeatures(cx, &isDisabled, &reason)) {
return false;
}
if (isDisabled) {
JSString* result = reason.finishString();
if (!result) {
return false;
}
args.rval().setString(result);
} else {
args.rval().setBoolean(false);
}
return true;
}
static bool WasmIonDisabledByFeatures(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
bool isDisabled = false;
JSStringBuilder reason(cx);
if (!wasm::IonDisabledByFeatures(cx, &isDisabled, &reason)) {
return false;
}
if (isDisabled) {
JSString* result = reason.finishString();
if (!result) {
return false;
}
args.rval().setString(result);
} else {
args.rval().setBoolean(false);
}
return true;
}
static bool WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject callee(cx, &args.callee());
@ -6629,12 +6675,6 @@ gc::ZealModeHelpText),
" Returns a boolean indicating whether WebAssembly supports using a large"
" virtual memory reservation in order to elide bounds checks on this platform."),
JS_FN_HELP("wasmUsesCranelift", WasmUsesCranelift, 0, 0,
"wasmUsesCranelift()",
" Returns a boolean indicating whether Cranelift is currently enabled for backend\n"
" compilation. This doesn't necessarily mean a module will be compiled with \n"
" Cranelift (e.g. when baseline is also enabled)."),
JS_FN_HELP("wasmThreadsSupported", WasmThreadsSupported, 0, 0,
"wasmThreadsSupported()",
" Returns a boolean indicating whether the WebAssembly threads proposal is\n"
@ -6645,10 +6685,31 @@ gc::ZealModeHelpText),
" Returns a boolean indicating whether the WebAssembly bulk memory proposal is\n"
" supported on the current device."),
JS_FN_HELP("wasmCompilersPresent", WasmCompilersPresent, 0, 0,
"wasmCompilersPresent()",
" Returns a string indicating the present wasm compilers: a comma-separated list\n"
" of 'baseline', 'ion', and 'cranelift'. A compiler is present in the executable\n"
" if it is compiled in and can generate code for the current architecture."),
JS_FN_HELP("wasmCompileMode", WasmCompileMode, 0, 0,
"wasmCompileMode()",
" Returns a string indicating the available compile policy: 'baseline', 'ion',\n"
" 'baseline-or-ion', or 'disabled' (if wasm is not available at all)."),
" Returns a string indicating the available wasm compilers: 'baseline', 'ion',\n"
" 'cranelift', 'baseline+ion', 'baseline+cranelift', or 'none'. A compiler is\n"
" available if it is present in the executable and not disabled by switches\n"
" or runtime conditions. At most one baseline and one optimizing compiler can\n"
" be available."),
JS_FN_HELP("wasmCraneliftDisabledByFeatures", WasmCraneliftDisabledByFeatures, 0, 0,
"wasmCraneliftDisabledByFeatures()",
" If some feature is enabled at compile-time or run-time that prevents Cranelift\n"
" from being used then this returns a truthy string describing the features that\n."
" are disabling it. Otherwise it returns false."),
JS_FN_HELP("wasmIonDisabledByFeatures", WasmIonDisabledByFeatures, 0, 0,
"wasmIonDisabledByFeatures()",
" If some feature is enabled at compile-time or run-time that prevents Ion\n"
" from being used then this returns a truthy string describing the features that\n."
" are disabling it. Otherwise it returns false."),
JS_FN_HELP("wasmTextToBinary", WasmTextToBinary, 1, 0,
"wasmTextToBinary(str)",
@ -6693,10 +6754,6 @@ gc::ZealModeHelpText),
"wasmBigIntEnabled()",
" Returns a boolean indicating whether the WebAssembly I64 to BigInt proposal is enabled."),
JS_FN_HELP("wasmDebugSupport", WasmDebugSupport, 1, 0,
"wasmDebugSupport()",
" Returns a boolean indicating whether the WebAssembly compilers support debugging."),
JS_FN_HELP("isLazyFunction", IsLazyFunction, 1, 0,
"isLazyFunction(fun)",
" True if fun is a lazy JSFunction."),

Просмотреть файл

@ -139,16 +139,20 @@ static int testWasmFuzz(const uint8_t* buf, size_t size) {
// overwritten later on.
uint8_t optByte = (uint8_t)buf[currentIndex];
// Note that IonPlatformSupport() and CraneliftPlatformSupport() do not
// take into account whether those compilers support particular features
// that may have been enabled.
bool enableWasmBaseline = ((optByte & 0xF0) == (1 << 7));
bool enableWasmIon = IonCanCompile() && ((optByte & 0xF0) == (1 << 6));
bool enableWasmIon =
IonPlatformSupport() && ((optByte & 0xF0) == (1 << 6));
bool enableWasmCranelift = false;
#ifdef ENABLE_WASM_CRANELIFT
enableWasmCranelift =
CraneliftCanCompile() && ((optByte & 0xF0) == (1 << 5));
CraneliftPlatformSupport() && ((optByte & 0xF0) == (1 << 5));
#endif
bool enableWasmAwaitTier2 = (IonCanCompile()
bool enableWasmAwaitTier2 = (IonPlatformSupport()
#ifdef ENABLE_WASM_CRANELIFT
|| CraneliftCanCompile()
|| CraneliftPlatformSupport()
#endif
) &&
((optByte & 0xF) == (1 << 3));
@ -158,7 +162,7 @@ static int testWasmFuzz(const uint8_t* buf, size_t size) {
// more platform specific JIT code. However, on some platforms,
// e.g. ARM64, we do not have Ion available, so we need to switch
// to baseline instead.
if (IonCanCompile()) {
if (IonPlatformSupport()) {
enableWasmIon = true;
} else {
enableWasmBaseline = true;

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
// Tests that wasm module scripts has inspectable globals and memory.
load(libdir + "wasm.js");

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
// Tests that JS can be evaluated on wasm module scripts frames.
load(libdir + "wasm.js");

Просмотреть файл

@ -3054,8 +3054,14 @@ const cacheEntry = streamCacheEntry(bytecode);
runBox2d(cacheEntry);
while (!wasmHasTier2CompilationCompleted(cacheEntry.module)) sleep(1);
assertEq(cacheEntry.cached, wasmCachingIsSupported());
while (!wasmHasTier2CompilationCompleted(cacheEntry.module))
sleep(1);
// Cranelift code cannot yet be cached, but cranelift tier2 compilation will
// still populate the cacheEntry.
if (!wasmCompileMode().match("cranelift")) {
assertEq(cacheEntry.cached, wasmCachingIsSupported());
}
runBox2d(cacheEntry);

Просмотреть файл

@ -0,0 +1,3 @@
// |jit-test| skip-if: !wasmCompilersPresent().match("ion") || wasmIonDisabledByFeatures(); --wasm-compiler=ion
assertEq(wasmCompileMode(), "ion");

Просмотреть файл

@ -0,0 +1,3 @@
// |jit-test| skip-if: !wasmCompilersPresent().match("baseline"); --wasm-compiler=baseline
assertEq(wasmCompileMode(), "baseline");

Просмотреть файл

@ -0,0 +1,3 @@
// |jit-test| --wasm-compiler=cranelift; skip-if: !wasmCompilersPresent().match("cranelift") || wasmCraneliftDisabledByFeatures()
assertEq(wasmCompileMode(), "cranelift");

Просмотреть файл

@ -526,7 +526,7 @@ if (wasmBulkMemSupported()) {
// element segment is completely OOB.
assertEq(typeof tbl.get(0), "function");
assertEq(tbl.get(1), null);
} else if (!wasmUsesCranelift()) {
} else if (!wasmCompileMode().match("cranelift")) {
assertEq(tbl.get(0), null);
assertEq(tbl.get(1), null);
}
@ -543,7 +543,7 @@ if (wasmBulkMemSupported()) {
assertEq(typeof tbl.get(0), "function");
assertEq(typeof tbl.get(1), "function");
assertEq(mem8[0], 1);
} else if (!wasmUsesCranelift()) {
} else if (!wasmCompileMode().match("cranelift")) {
assertEq(tbl.get(0), null);
assertEq(tbl.get(1), null);
assertEq(mem8[0], 0);

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
var g = newGlobal({newCompartment: true});
g.parent = this;
g.eval("Debugger(parent).onExceptionUnwind = function () {};");

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
var g = newGlobal({newCompartment: true});
var dbg = new g.Debugger(this);
var dbg = new Debugger;

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
var evalInFrame = (function(global) {
var dbgGlobal = newGlobal({newCompartment: true});
var dbg = new dbgGlobal.Debugger();

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
//
var mod = new WebAssembly.Module(wasmTextToBinary(`
(module

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
g = newGlobal({newCompartment: true});
g.parent = this;
g.eval("(" + function() {

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmDebugSupport()
// |jit-test| skip-if: !wasmDebuggingIsSupported()
g = newGlobal({newCompartment: true});
g.parent = this;
g.eval("(" + function() {

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmIsSupported() || !wasmDebugSupport(); exitstatus:3
// |jit-test| skip-if: !wasmDebuggingIsSupported(); exitstatus:3
function userError() {};

Просмотреть файл

@ -862,7 +862,7 @@ void LIRGenerator::visitWasmCompareExchangeHeap(MWasmCompareExchangeHeap* ins) {
}
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
MOZ_ASSERT(HasLDSTREXBHD(), "by HasCompilerSupport() constraints");
MOZ_ASSERT(HasLDSTREXBHD(), "by HasPlatformSupport() constraints");
LWasmCompareExchangeHeap* lir = new (alloc())
LWasmCompareExchangeHeap(useRegister(base), useRegister(ins->oldValue()),
@ -885,7 +885,7 @@ void LIRGenerator::visitWasmAtomicExchangeHeap(MWasmAtomicExchangeHeap* ins) {
}
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
MOZ_ASSERT(HasLDSTREXBHD(), "by HasCompilerSupport() constraints");
MOZ_ASSERT(HasLDSTREXBHD(), "by HasPlatformSupport() constraints");
const LAllocation base = useRegister(ins->base());
const LAllocation value = useRegister(ins->value());
@ -905,7 +905,7 @@ void LIRGenerator::visitWasmAtomicBinopHeap(MWasmAtomicBinopHeap* ins) {
}
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
MOZ_ASSERT(HasLDSTREXBHD(), "by HasCompilerSupport() constraints");
MOZ_ASSERT(HasLDSTREXBHD(), "by HasPlatformSupport() constraints");
MDefinition* base = ins->base();
MOZ_ASSERT(base->type() == MIRType::Int32);

Просмотреть файл

@ -208,7 +208,11 @@ static const size_t gMaxStackSize = 128 * sizeof(size_t) * 1024;
static const double MAX_TIMEOUT_SECONDS = 1800.0;
// Not necessarily in sync with the browser
#define SHARED_MEMORY_DEFAULT 1
#ifdef ENABLE_WASM_THREADS
# define SHARED_MEMORY_DEFAULT 1
#else
# define SHARED_MEMORY_DEFAULT 0
#endif
// Fuzzing support for JS runtime fuzzing
#ifdef FUZZING_INTERFACES
@ -4657,6 +4661,10 @@ static bool SetJitCompilerOption(JSContext* cx, unsigned argc, Value* vp) {
// Throw if trying to disable all the Wasm compilers. The logic here is that
// if we're trying to disable a compiler that is currently enabled and that is
// the last compiler enabled then we must throw.
//
// Note that this check does not prevent an error from being thrown later.
// Actual compiler availability is dynamic and depends on other conditions,
// such as other options set and whether a debugger is present.
if ((opt == JSJITCOMPILER_WASM_JIT_BASELINE ||
opt == JSJITCOMPILER_WASM_JIT_ION ||
opt == JSJITCOMPILER_WASM_JIT_CRANELIFT) &&
@ -6292,7 +6300,7 @@ static bool CompileAndSerializeInSeparateProcess(JSContext* cx,
}
static bool WasmCompileAndSerialize(JSContext* cx) {
MOZ_ASSERT(wasm::HasCachingSupport(cx));
MOZ_ASSERT(wasm::CodeCachingAvailable(cx));
#ifdef XP_WIN
// See CompileAndSerializeInSeparateProcess for why we've had to smuggle
@ -6342,7 +6350,7 @@ static bool WasmCompileAndSerialize(JSContext* cx) {
static bool WasmCompileInSeparateProcess(JSContext* cx, unsigned argc,
Value* vp) {
if (!wasm::HasCachingSupport(cx)) {
if (!wasm::CodeCachingAvailable(cx)) {
JS_ReportErrorASCII(cx, "WebAssembly caching not supported");
return false;
}

Просмотреть файл

@ -6843,10 +6843,10 @@ static bool TryInstantiate(JSContext* cx, CallArgs args, const Module& module,
HandleValue importVal = args.get(1);
HandleValue bufferVal = args.get(2);
// Re-check HasCompilerSupport(cx) since this varies per-thread and
// Re-check HasPlatformSupport(cx) since this varies per-thread and
// 'module' may have been produced on a parser thread.
if (!HasCompilerSupport(cx)) {
return LinkFail(cx, "no compiler support");
if (!HasPlatformSupport(cx)) {
return LinkFail(cx, "no platform support");
}
Rooted<ImportValues> imports(cx);
@ -7039,7 +7039,7 @@ static bool TypeFailureWarning(frontend::ParserBase& parser, const char* str) {
// asm.js requires Ion to be available on the current hardware/OS and to be
// enabled for wasm, since asm.js compilation goes via wasm.
static bool IsAsmJSCompilerAvailable(JSContext* cx) {
return HasCompilerSupport(cx) && IonCanCompile() && cx->options().wasmIon();
return HasPlatformSupport(cx) && IonAvailable(cx);
}
static bool EstablishPreconditions(JSContext* cx,

Просмотреть файл

@ -12918,7 +12918,7 @@ FuncOffsets BaseCompiler::finish() {
} // namespace wasm
} // namespace js
bool js::wasm::BaselineCanCompile() {
bool js::wasm::BaselinePlatformSupport() {
#if defined(JS_CODEGEN_ARM)
// Simplifying assumption: require SDIV and UDIV.
//

Просмотреть файл

@ -25,8 +25,9 @@ namespace js {
namespace wasm {
// Return whether BaselineCompileFunction can generate code on the current
// device.
bool BaselineCanCompile();
// device. Usually you do *not* want to call this, you want
// BaselineAvailable().
MOZ_MUST_USE bool BaselinePlatformSupport();
// Generate adequate code quickly.
MOZ_MUST_USE bool BaselineCompileFunctions(const ModuleEnvironment& env,

Просмотреть файл

@ -78,25 +78,12 @@ uint32_t wasm::ObservedCPUFeatures() {
SharedCompileArgs CompileArgs::build(JSContext* cx,
ScriptedCaller&& scriptedCaller) {
bool baseline = BaselineCanCompile() && cx->options().wasmBaseline();
bool ion = IonCanCompile() && cx->options().wasmIon();
#ifdef ENABLE_WASM_CRANELIFT
bool cranelift = CraneliftCanCompile() && cx->options().wasmCranelift();
#else
bool cranelift = false;
#endif
bool baseline = BaselineAvailable(cx);
bool ion = IonAvailable(cx);
bool cranelift = CraneliftAvailable(cx);
#ifdef ENABLE_WASM_GC
bool gc = cx->options().wasmGc();
#else
bool gc = false;
#endif
#ifdef ENABLE_WASM_BIGINT
bool bigInt = cx->options().isWasmBigIntEnabled();
#else
bool bigInt = false;
#endif
// At most one optimizing compiler.
MOZ_RELEASE_ASSERT(!(ion && cranelift));
// Debug information such as source view or debug traps will require
// additional memory and permanently stay in baseline code, so we try to
@ -104,39 +91,23 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
// is open.
bool debug = cx->realm()->debuggerObservesAsmJS();
bool sharedMemory =
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
bool forceTiering =
cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2;
if (debug || gc) {
if (!baseline) {
JS_ReportErrorASCII(cx, "can't use wasm debug/gc without baseline");
return nullptr;
}
ion = false;
cranelift = false;
}
// The <Compiler>Available() predicates should ensure this.
MOZ_RELEASE_ASSERT(!(debug && (ion || cranelift)));
if (forceTiering && (!baseline || (!cranelift && !ion))) {
if (forceTiering && !(baseline && (cranelift || ion))) {
// This can happen only in testing, and in this case we don't have a
// proper way to signal the error, so just silently override the default,
// instead of adding a skip-if directive to every test using debug/gc.
forceTiering = false;
}
#ifdef ENABLE_WASM_CRANELIFT
if (!baseline && !ion && !cranelift) {
if (cx->options().wasmCranelift() && !CraneliftCanCompile()) {
// We're forcing to use Cranelift on a platform that doesn't support it.
JS_ReportErrorASCII(cx, "cranelift isn't supported on this platform");
return nullptr;
}
if (!(baseline || ion || cranelift)) {
JS_ReportErrorASCII(cx, "no WebAssembly compiler available");
return nullptr;
}
#endif
// HasCompilerSupport() should prevent failure here.
MOZ_RELEASE_ASSERT(baseline || ion || cranelift);
CompileArgs* target = cx->new_<CompileArgs>(std::move(scriptedCaller));
if (!target) {
@ -147,11 +118,17 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
target->ionEnabled = ion;
target->craneliftEnabled = cranelift;
target->debugEnabled = debug;
target->sharedMemoryEnabled = sharedMemory;
target->sharedMemoryEnabled =
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
target->forceTiering = forceTiering;
target->gcEnabled = gc;
target->gcEnabled = wasm::GcTypesAvailable(cx);
target->hugeMemory = wasm::IsHugeMemoryEnabled();
target->bigIntEnabled = bigInt;
target->bigIntEnabled = wasm::I64BigIntConversionAvailable(cx);
target->multiValuesEnabled = wasm::MultiValuesAvailable(cx);
Log(cx, "available wasm compilers: tier1=%s tier2=%s",
baseline ? "baseline" : "none",
ion ? "ion" : (cranelift ? "cranelift" : "none"));
return target;
}
@ -486,13 +463,15 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
bool forceTiering = args_->forceTiering;
bool hugeMemory = args_->hugeMemory;
bool bigIntEnabled = args_->bigIntEnabled;
bool multiValuesEnabled = args_->multiValuesEnabled;
bool hasSecondTier = ionEnabled || craneliftEnabled;
MOZ_ASSERT_IF(gcEnabled || debugEnabled, baselineEnabled);
MOZ_ASSERT_IF(debugEnabled, baselineEnabled);
MOZ_ASSERT_IF(forceTiering, baselineEnabled && hasSecondTier);
// HasCompilerSupport() should prevent failure here
// Various constraints in various places should prevent failure here.
MOZ_RELEASE_ASSERT(baselineEnabled || ionEnabled || craneliftEnabled);
MOZ_RELEASE_ASSERT(!(ionEnabled && craneliftEnabled));
uint32_t codeSectionSize = 0;
@ -516,13 +495,10 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
debug_ = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
gcTypes_ = gcEnabled;
refTypes_ = true;
#ifdef ENABLE_WASM_MULTI_VALUE
multiValues_ = !craneliftEnabled;
#else
multiValues_ = false;
#endif
multiValues_ = multiValuesEnabled;
hugeMemory_ = hugeMemory;
bigInt_ = bigIntEnabled && !craneliftEnabled;
bigInt_ = bigIntEnabled;
multiValues_ = multiValuesEnabled;
state_ = Computed;
}
@ -627,12 +603,8 @@ void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
#else
bool refTypesConfigured = false;
#endif
#ifdef ENABLE_WASM_MULTI_VALUE
bool multiValueConfigured = !args.craneliftEnabled;
#else
bool multiValueConfigured = false;
#endif
bool bigIntConfigured = args.bigIntEnabled && !args.craneliftEnabled;
bool multiValueConfigured = args.multiValuesEnabled;
bool bigIntConfigured = args.bigIntEnabled;
OptimizedBackend optimizedBackend = args.craneliftEnabled
? OptimizedBackend::Cranelift

Просмотреть файл

@ -59,6 +59,7 @@ struct CompileArgs : ShareableBase<CompileArgs> {
bool gcEnabled;
bool hugeMemory;
bool bigIntEnabled;
bool multiValuesEnabled;
// CompileArgs has two constructors:
//
@ -82,7 +83,8 @@ struct CompileArgs : ShareableBase<CompileArgs> {
forceTiering(false),
gcEnabled(false),
hugeMemory(false),
bigIntEnabled(false) {}
bigIntEnabled(false),
multiValuesEnabled(false) {}
};
// Return the estimated compiled (machine) code size for the given bytecode size

Просмотреть файл

@ -36,7 +36,7 @@ using namespace js;
using namespace js::jit;
using namespace js::wasm;
bool wasm::CraneliftCanCompile() {
bool wasm::CraneliftPlatformSupport() {
#ifdef JS_CODEGEN_X64
return true;
#else
@ -427,7 +427,7 @@ bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
LifoAlloc& lifo,
const FuncCompileInputVector& inputs,
CompiledCode* code, UniqueChars* error) {
MOZ_RELEASE_ASSERT(CraneliftCanCompile());
MOZ_RELEASE_ASSERT(CraneliftPlatformSupport());
MOZ_ASSERT(env.tier() == Tier::Optimized);
MOZ_ASSERT(env.optimizedBackend() == OptimizedBackend::Cranelift);

Просмотреть файл

@ -27,16 +27,25 @@ namespace js {
namespace wasm {
#ifdef ENABLE_WASM_CRANELIFT
MOZ_MUST_USE bool CraneliftCanCompile();
#else
MOZ_MUST_USE inline bool CraneliftCanCompile() { return false; }
#endif
// Return whether CraneliftCompileFunction() can generate code on the current
// device. Usually you do *not* want this, you want CraneliftAvailable().
MOZ_MUST_USE bool CraneliftPlatformSupport();
// Generates code with Cranelift.
MOZ_MUST_USE bool CraneliftCompileFunctions(
const ModuleEnvironment& env, LifoAlloc& lifo,
const FuncCompileInputVector& inputs, CompiledCode* code,
UniqueChars* error);
#else
MOZ_MUST_USE inline bool CraneliftPlatformSupport() { return false; }
MOZ_MUST_USE inline bool CraneliftCompileFunctions(
const ModuleEnvironment& env, LifoAlloc& lifo,
const FuncCompileInputVector& inputs, CompiledCode* code,
UniqueChars* error) {
MOZ_CRASH("Should not happen");
}
#endif
} // namespace wasm
} // namespace js

Просмотреть файл

@ -724,19 +724,19 @@ static bool ExecuteCompileTask(CompileTask* task, UniqueChars* error) {
switch (task->env.tier()) {
case Tier::Optimized:
#ifdef ENABLE_WASM_CRANELIFT
if (task->env.optimizedBackend() == OptimizedBackend::Cranelift) {
if (!CraneliftCompileFunctions(task->env, task->lifo, task->inputs,
&task->output, error)) {
return false;
}
break;
}
#endif
MOZ_ASSERT(task->env.optimizedBackend() == OptimizedBackend::Ion);
if (!IonCompileFunctions(task->env, task->lifo, task->inputs,
&task->output, error)) {
return false;
switch (task->env.optimizedBackend()) {
case OptimizedBackend::Cranelift:
if (!CraneliftCompileFunctions(task->env, task->lifo, task->inputs,
&task->output, error)) {
return false;
}
break;
case OptimizedBackend::Ion:
if (!IonCompileFunctions(task->env, task->lifo, task->inputs,
&task->output, error)) {
return false;
}
break;
}
break;
case Tier::Baseline:

Просмотреть файл

@ -117,7 +117,7 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
return false;
}
if (fi.funcType().hasI64ArgOrRet() && !HasI64BigIntSupport(cx)) {
if (fi.funcType().hasI64ArgOrRet() && !I64BigIntConversionAvailable(cx)) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_WASM_BAD_I64_TYPE);
return false;
@ -132,7 +132,7 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
}
case ValType::I64: {
#ifdef ENABLE_WASM_BIGINT
MOZ_ASSERT(HasI64BigIntSupport(cx));
MOZ_ASSERT(I64BigIntConversionAvailable(cx));
// If bi is manipulated other than test & storing, it would need
// to be rooted here.
BigInt* bi = BigInt::createFromInt64(cx, *(int64_t*)&argv[i]);
@ -1692,7 +1692,7 @@ bool Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args) {
return false;
}
if (funcType->hasI64ArgOrRet() && !HasI64BigIntSupport(cx)) {
if (funcType->hasI64ArgOrRet() && !I64BigIntConversionAvailable(cx)) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_WASM_BAD_I64_TYPE);
return false;
@ -1729,7 +1729,7 @@ bool Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args) {
break;
case ValType::I64: {
#ifdef ENABLE_WASM_BIGINT
MOZ_ASSERT(HasI64BigIntSupport(cx),
MOZ_ASSERT(I64BigIntConversionAvailable(cx),
"unexpected i64 flowing into callExport");
RootedBigInt bigint(cx, ToBigInt(cx, v));
if (!bigint) {
@ -1848,7 +1848,7 @@ bool Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args) {
break;
case ValType::I64: {
#ifdef ENABLE_WASM_BIGINT
MOZ_ASSERT(HasI64BigIntSupport(cx),
MOZ_ASSERT(I64BigIntConversionAvailable(cx),
"unexpected i64 flowing from callExport");
// If bi is manipulated other than test & storing, it would need
// to be rooted here.

Просмотреть файл

@ -4745,7 +4745,7 @@ bool wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,
return code->swap(masm);
}
bool js::wasm::IonCanCompile() {
bool js::wasm::IonPlatformSupport() {
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || \
defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || \
defined(JS_CODEGEN_MIPS64)

Просмотреть файл

@ -27,7 +27,8 @@ namespace js {
namespace wasm {
// Return whether IonCompileFunction() can generate code on the current device.
bool IonCanCompile();
// Usually you do *not* want this, you want IonAvailable().
MOZ_MUST_USE bool IonPlatformSupport();
// Generates very fast code at the expense of compilation time.
MOZ_MUST_USE bool IonCompileFunctions(const ModuleEnvironment& env,

Просмотреть файл

@ -64,33 +64,7 @@ using mozilla::RangedPtr;
extern mozilla::Atomic<bool> fuzzingSafe;
bool wasm::HasReftypesSupport(JSContext* cx) {
#ifdef ENABLE_WASM_REFTYPES
return true;
#else
return false;
#endif
}
bool wasm::HasGcSupport(JSContext* cx) {
#ifdef ENABLE_WASM_CRANELIFT
if (cx->options().wasmCranelift()) {
return false;
}
#endif
#ifdef ENABLE_WASM_GC
return cx->options().wasmGc() && cx->options().wasmBaseline();
#else
return false;
#endif
}
bool wasm::HasMultiValueSupport(JSContext* cx) {
#ifdef ENABLE_WASM_CRANELIFT
if (cx->options().wasmCranelift()) {
return false;
}
#endif
static inline bool WasmMultiValueFlag(JSContext* cx) {
#ifdef ENABLE_WASM_MULTI_VALUE
return true;
#else
@ -98,12 +72,132 @@ bool wasm::HasMultiValueSupport(JSContext* cx) {
#endif
}
bool wasm::HasI64BigIntSupport(JSContext* cx) {
#ifdef ENABLE_WASM_CRANELIFT
if (cx->options().wasmCranelift()) {
// Compiler availability predicates. These must be kept in sync with the
// feature predicates in the next section below.
//
// These can't call the feature predicates since the feature predicates call
// back to these predicates. So there will be a small amount of duplicated
// logic here, but as compilers reach feature parity that duplication will go
// away.
//
// There's a static precedence order between the optimizing compilers. This
// order currently ranks Cranelift over Ion on all platforms because Cranelift
// is disabled by default on all platforms: anyone who has enabled Cranelift
// will wish to use it instead of Ion.
//
// The precedence order is implemented by guards in IonAvailable() and
// CraneliftAvailable(). We expect that it will become more complex as the
// default settings change. But it should remain static.
bool wasm::BaselineAvailable(JSContext* cx) {
// Baseline supports every feature supported by any compiler.
return cx->options().wasmBaseline() && BaselinePlatformSupport();
}
bool wasm::IonAvailable(JSContext* cx) {
if (!cx->options().wasmIon() || !IonPlatformSupport()) {
return false;
}
bool isDisabled = false;
MOZ_ALWAYS_TRUE(IonDisabledByFeatures(cx, &isDisabled));
return !isDisabled && !CraneliftAvailable(cx);
}
template <size_t ArrayLength>
static inline bool Append(JSStringBuilder* reason, const char (&s)[ArrayLength],
char* sep) {
if ((*sep && !reason->append(*sep)) || !reason->append(s)) {
return false;
}
*sep = ',';
return true;
}
bool wasm::IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason) {
// Ion has no debugging support, no gc support.
bool debug = cx->realm() && cx->realm()->debuggerObservesAsmJS();
bool gc = cx->options().wasmGc();
if (reason) {
char sep = 0;
if (debug && !Append(reason, "debug", &sep)) {
return false;
}
if (gc && !Append(reason, "gc", &sep)) {
return false;
}
}
*isDisabled = debug || gc;
return true;
}
bool wasm::CraneliftAvailable(JSContext* cx) {
if (!cx->options().wasmCranelift() || !CraneliftPlatformSupport()) {
return false;
}
bool isDisabled = false;
MOZ_ALWAYS_TRUE(CraneliftDisabledByFeatures(cx, &isDisabled));
return !isDisabled;
}
bool wasm::CraneliftDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason) {
// Cranelift has no debugging support, no gc support, no multi-value support,
// no threads.
bool debug = cx->realm() && cx->realm()->debuggerObservesAsmJS();
bool gc = cx->options().wasmGc();
bool multiValue = WasmMultiValueFlag(cx);
bool threads =
cx->realm() &&
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
if (reason) {
char sep = 0;
if (debug && !Append(reason, "debug", &sep)) {
return false;
}
if (gc && !Append(reason, "gc", &sep)) {
return false;
}
if (multiValue && !Append(reason, "multi-value", &sep)) {
return false;
}
if (threads && !Append(reason, "threads", &sep)) {
return false;
}
}
*isDisabled = debug || gc || multiValue || threads;
return true;
}
// Feature predicates. These must be kept in sync with the predicates in the
// section above.
//
// The meaning of these predicates is tricky: A predicate is true for a feature
// if the feature is enabled and/or compiled-in *and* we have *at least one*
// compiler that can support the feature. Subsequent compiler selection must
// ensure that only compilers that actually support the feature are used.
bool wasm::ReftypesAvailable(JSContext* cx) {
// All compilers support reference types.
#ifdef ENABLE_WASM_REFTYPES
return true;
#else
return false;
#endif
}
bool wasm::GcTypesAvailable(JSContext* cx) {
// Cranelift and Ion do not support GC.
return cx->options().wasmGc() && BaselineAvailable(cx);
}
bool wasm::MultiValuesAvailable(JSContext* cx) {
// Cranelift does not support multi-value.
return WasmMultiValueFlag(cx) && (BaselineAvailable(cx) || IonAvailable(cx));
}
bool wasm::I64BigIntConversionAvailable(JSContext* cx) {
// All compilers support int64<->bigint conversion.
#ifdef ENABLE_WASM_BIGINT
return cx->options().isWasmBigIntEnabled();
#else
@ -111,7 +205,14 @@ bool wasm::HasI64BigIntSupport(JSContext* cx) {
#endif
}
bool wasm::HasCompilerSupport(JSContext* cx) {
bool wasm::ThreadsAvailable(JSContext* cx) {
// Cranelift does not support atomics.
return cx->realm() &&
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled() &&
(BaselineAvailable(cx) || IonAvailable(cx));
}
bool wasm::HasPlatformSupport(JSContext* cx) {
#if !MOZ_LITTLE_ENDIAN() || defined(JS_CODEGEN_NONE)
return false;
#endif
@ -143,22 +244,10 @@ bool wasm::HasCompilerSupport(JSContext* cx) {
}
#endif
return BaselineCanCompile() || IonCanCompile() || CraneliftCanCompile();
}
bool wasm::HasOptimizedCompilerTier(JSContext* cx) {
return (cx->options().wasmIon() && IonCanCompile())
#ifdef ENABLE_WASM_CRANELIFT
|| (cx->options().wasmCranelift() && CraneliftCanCompile())
#endif
;
}
// Return whether wasm compilation is allowed by prefs. This check
// only makes sense if HasCompilerSupport() is true.
static bool HasAvailableCompilerTier(JSContext* cx) {
return (cx->options().wasmBaseline() && BaselineCanCompile()) ||
HasOptimizedCompilerTier(cx);
// Test only whether the compilers are supported on the hardware, not whether
// they are enabled.
return BaselinePlatformSupport() || IonPlatformSupport() ||
CraneliftPlatformSupport();
}
bool wasm::HasSupport(JSContext* cx) {
@ -170,10 +259,11 @@ bool wasm::HasSupport(JSContext* cx) {
cx->realm()->principals() &&
cx->realm()->principals()->isSystemOrAddonPrincipal();
}
return prefEnabled && HasCompilerSupport(cx) && HasAvailableCompilerTier(cx);
return prefEnabled && HasPlatformSupport(cx) &&
(BaselineAvailable(cx) || IonAvailable(cx) || CraneliftAvailable(cx));
}
bool wasm::HasStreamingSupport(JSContext* cx) {
bool wasm::StreamingCompilationAvailable(JSContext* cx) {
// This should match EnsureStreamSupport().
return HasSupport(cx) &&
cx->runtime()->offThreadPromiseState.ref().initialized() &&
@ -181,8 +271,12 @@ bool wasm::HasStreamingSupport(JSContext* cx) {
cx->runtime()->reportStreamErrorCallback;
}
bool wasm::HasCachingSupport(JSContext* cx) {
return HasStreamingSupport(cx) && HasOptimizedCompilerTier(cx);
bool wasm::CodeCachingAvailable(JSContext* cx) {
// At the moment, we require Ion support for code caching. The main reason
// for this is that wasm::CompileAndSerialize() does not have access to
// information about which optimizing compiler it should use. See comments in
// CompileAndSerialize(), below.
return StreamingCompilationAvailable(cx) && IonAvailable(cx);
}
bool wasm::CheckRefType(JSContext* cx, RefType::Kind targetTypeKind,
@ -242,7 +336,7 @@ static bool ToWebAssemblyValue(JSContext* cx, ValType targetType, HandleValue v,
}
case ValType::I64: {
#ifdef ENABLE_WASM_BIGINT
if (HasI64BigIntSupport(cx)) {
if (I64BigIntConversionAvailable(cx)) {
BigInt* bigint = ToBigInt(cx, v);
if (!bigint) {
return false;
@ -289,7 +383,7 @@ static bool ToJSValue(JSContext* cx, const Val& val, MutableHandleValue out) {
return true;
case ValType::I64: {
#ifdef ENABLE_WASM_BIGINT
if (HasI64BigIntSupport(cx)) {
if (I64BigIntConversionAvailable(cx)) {
BigInt* bi = BigInt::createFromInt64(cx, val.i64());
if (!bi) {
return false;
@ -442,7 +536,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module,
obj->val(&val);
} else {
if (IsNumberType(global.type())) {
if (HasI64BigIntSupport(cx)) {
if (I64BigIntConversionAvailable(cx)) {
if (global.type() == ValType::I64 && v.isNumber()) {
return ThrowBadImportType(cx, import.field.get(), "BigInt");
}
@ -591,10 +685,15 @@ bool wasm::CompileAndSerialize(const ShareableBytes& bytecode,
return false;
}
// The caller has ensured HasCachingSupport(). Moreover, we want to ensure
// The caller has ensured CodeCachingAvailable(). Moreover, we want to ensure
// we go straight to tier-2 so that we synchronously call
// JS::OptimizedEncodingListener::storeOptimizedEncoding().
compileArgs->baselineEnabled = false;
// We always pick Ion here, and we depend on CodeCachingAvailable() having
// determined that Ion is available, see comments at CodeCachingAvailable().
// To do better, we need to pass information about which compiler that should
// be used into CompileAndSerialize().
compileArgs->ionEnabled = true;
// The caller must ensure that huge memory support is configured the same in
@ -2277,7 +2376,7 @@ bool WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp) {
#ifdef ENABLE_WASM_REFTYPES
} else if (StringEqualsLiteral(elementLinearStr, "anyref") ||
StringEqualsLiteral(elementLinearStr, "nullref")) {
if (!HasReftypesSupport(cx)) {
if (!ReftypesAvailable(cx)) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_WASM_BAD_ELEMENT);
return false;
@ -2735,18 +2834,18 @@ bool WasmGlobalObject::construct(JSContext* cx, unsigned argc, Value* vp) {
} else if (StringEqualsLiteral(typeLinearStr, "f64")) {
globalType = ValType::F64;
#ifdef ENABLE_WASM_BIGINT
} else if (HasI64BigIntSupport(cx) &&
} else if (I64BigIntConversionAvailable(cx) &&
StringEqualsLiteral(typeLinearStr, "i64")) {
globalType = ValType::I64;
#endif
#ifdef ENABLE_WASM_REFTYPES
} else if (HasReftypesSupport(cx) &&
} else if (ReftypesAvailable(cx) &&
StringEqualsLiteral(typeLinearStr, "funcref")) {
globalType = RefType::func();
} else if (HasReftypesSupport(cx) &&
} else if (ReftypesAvailable(cx) &&
StringEqualsLiteral(typeLinearStr, "anyref")) {
globalType = RefType::any();
} else if (HasReftypesSupport(cx) &&
} else if (ReftypesAvailable(cx) &&
StringEqualsLiteral(typeLinearStr, "nullref")) {
globalType = RefType::null();
#endif
@ -2822,7 +2921,7 @@ bool WasmGlobalObject::valueGetterImpl(JSContext* cx, const CallArgs& args) {
return true;
case ValType::I64:
#ifdef ENABLE_WASM_BIGINT
if (HasI64BigIntSupport(cx)) {
if (I64BigIntConversionAvailable(cx)) {
return args.thisv().toObject().as<WasmGlobalObject>().value(
cx, args.rval());
}
@ -2866,7 +2965,7 @@ bool WasmGlobalObject::valueSetterImpl(JSContext* cx, const CallArgs& args) {
return false;
}
if (global->type() == ValType::I64 && !HasI64BigIntSupport(cx)) {
if (global->type() == ValType::I64 && !I64BigIntConversionAvailable(cx)) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_WASM_BAD_I64_TYPE);
return false;
@ -2890,7 +2989,7 @@ bool WasmGlobalObject::valueSetterImpl(JSContext* cx, const CallArgs& args) {
break;
case ValType::I64:
#ifdef ENABLE_WASM_BIGINT
MOZ_ASSERT(HasI64BigIntSupport(cx),
MOZ_ASSERT(I64BigIntConversionAvailable(cx),
"expected BigInt support for setting I64 global");
cell->i64 = val.get().i64();
#endif
@ -3368,7 +3467,7 @@ static bool WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp) {
}
static bool EnsureStreamSupport(JSContext* cx) {
// This should match wasm::HasStreamingSupport().
// This should match wasm::StreamingCompilationAvailable().
if (!EnsurePromiseSupport(cx)) {
return false;

Просмотреть файл

@ -27,6 +27,7 @@
namespace js {
class ArrayBufferObjectMaybeShared;
class JSStringBuilder;
class StructTypeDescr;
class TypedArrayObject;
class WasmFunctionScope;
@ -35,48 +36,81 @@ class SharedArrayRawBuffer;
namespace wasm {
// Return whether WebAssembly can be compiled on this platform.
// This must be checked and must be true to call any of the top-level wasm
// eval/compile methods.
// Return whether WebAssembly can in principle be compiled on this platform (ie
// combination of hardware and OS), assuming at least one of the compilers that
// supports the platform is not disabled by other settings.
//
// This predicate must be checked and must be true to call any of the top-level
// wasm eval/compile methods.
bool HasCompilerSupport(JSContext* cx);
// Return whether WebAssembly has support for an optimized compiler backend.
bool HasOptimizedCompilerTier(JSContext* cx);
bool HasPlatformSupport(JSContext* cx);
// Return whether WebAssembly is supported on this platform. This determines
// whether the WebAssembly object is exposed to JS and takes into account
// configuration options that disable various modes.
// configuration options that disable various modes. It also checks that at
// least one compiler is (currently) available.
bool HasSupport(JSContext* cx);
// Return whether WebAssembly streaming/caching is supported on this platform.
// This takes into account prefs and necessary embedding callbacks.
// Predicates for compiler availability.
//
// These three predicates together select zero or one baseline compiler and zero
// or one optimizing compiler, based on: what's compiled into the executable,
// what's supported on the current platform, what's selected by options, and the
// current run-time environment. As it is possible for the computed values to
// change (when a value changes in about:config or the debugger pane is shown or
// hidden), it is inadvisable to cache these values in such a way that they
// could become invalid. Generally it is cheap always to recompute them.
bool HasStreamingSupport(JSContext* cx);
bool BaselineAvailable(JSContext* cx);
bool IonAvailable(JSContext* cx);
bool CraneliftAvailable(JSContext* cx);
bool HasCachingSupport(JSContext* cx);
// Predicates for white-box compiler disablement testing.
//
// These predicates determine whether the optimizing compilers were disabled by
// features that are enabled at compile-time or run-time. They do not consider
// the hardware platform on whether other compilers are enabled.
//
// If `reason` is not null then it is populated with a string that describes
// the specific features that disable the compiler.
//
// Returns false on OOM (which happens only when a reason is requested),
// otherwise true, with the result in `*isDisabled` and optionally the reason in
// `*reason`.
// Returns true if WebAssembly as configured by compile-time flags and run-time
// options can support reference types and stack walking.
bool IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason = nullptr);
bool CraneliftDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason = nullptr);
bool HasReftypesSupport(JSContext* cx);
// Predicates for feature availability.
//
// The following predicates check whether particular wasm features are enabled,
// and for each, whether at least one compiler is (currently) available that
// supports the feature.
// Returns true if WebAssembly as configured by compile-time flags and run-time
// options can support (ref T) types and structure types, etc (evolving).
// Streaming compilation.
bool StreamingCompilationAvailable(JSContext* cx);
bool HasGcSupport(JSContext* cx);
// Caching of optimized code. Implies both streaming compilation and an
// optimizing compiler tier.
bool CodeCachingAvailable(JSContext* cx);
// Returns true if WebAssembly as configured by compile-time flags and run-time
// options can support multi-value block and function returns (evolving).
// General reference types (anyref, funcref, nullref) and operations on them.
bool ReftypesAvailable(JSContext* cx);
bool HasMultiValueSupport(JSContext* cx);
// Experimental (ref T) types and structure types.
bool GcTypesAvailable(JSContext* cx);
// Returns true if WebAssembly as configured by compile-time flags and run-time
// options can support I64 to BigInt conversion.
// Multi-value block and function returns.
bool MultiValuesAvailable(JSContext* cx);
bool HasI64BigIntSupport(JSContext* cx);
// I64<->BigInt interconversion at the wasm/JS boundary.
bool I64BigIntConversionAvailable(JSContext* cx);
// Shared memory and atomics.
bool ThreadsAvailable(JSContext* cx);
// Compiles the given binary wasm module given the ArrayBufferObject
// and links the module's imports with the given import object.

Просмотреть файл

@ -45,7 +45,7 @@ void EnsureEagerProcessSignalHandlers();
// this function performs the full installation of signal handlers which must
// be performed per-thread/JSContext. This operation may incur some overhead and
// so should be done only when needed to use wasm. Currently, this is done in
// wasm::HasCompilerSupport() which is called when deciding whether to expose
// wasm::HasPlatformSupport() which is called when deciding whether to expose
// the 'WebAssembly' object on the global object.
bool EnsureFullSignalHandlers(JSContext* cx);

Просмотреть файл

@ -2986,11 +2986,11 @@ bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode,
UniqueChars* error) {
Decoder d(bytecode.bytes, 0, error);
bool gcTypesConfigured = HasGcSupport(cx);
bool refTypesConfigured = HasReftypesSupport(cx);
bool multiValueConfigured = HasMultiValueSupport(cx);
bool gcTypesConfigured = GcTypesAvailable(cx);
bool refTypesConfigured = ReftypesAvailable(cx);
bool multiValueConfigured = MultiValuesAvailable(cx);
bool hugeMemory = false;
bool bigIntConfigured = HasI64BigIntSupport(cx);
bool bigIntConfigured = I64BigIntConversionAvailable(cx);
CompilerEnvironment compilerEnv(
CompileMode::Once, Tier::Optimized, OptimizedBackend::Ion,