зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
bc5a3e6d09
Коммит
23854fd5a5
|
@ -474,6 +474,9 @@ set_define('MOZ_RUST_SIMD', rust_simd)
|
||||||
|
|
||||||
|
|
||||||
# Experimental support for wasm code generation with Cranelift
|
# 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',
|
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.
|
# Support for the WebAssembly multi-value proposal.
|
||||||
|
# Do not remove until Cranelift supports multi-value.
|
||||||
# =====================================================
|
# =====================================================
|
||||||
|
|
||||||
@depends(milestone.is_nightly, building_js)
|
@depends(milestone.is_nightly, building_js)
|
||||||
|
@ -604,6 +608,23 @@ js_option('--enable-wasm-multi-value',
|
||||||
set_config('ENABLE_WASM_MULTI_VALUE', depends_if('--enable-wasm-multi-value')(lambda x: True))
|
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))
|
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.
|
||||||
|
# =====================================================
|
||||||
|
|
||||||
|
js_option('--enable-wasm-threads',
|
||||||
|
default=True,
|
||||||
|
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
|
# Initial support for new regexp engine
|
||||||
# ==================================================
|
# ==================================================
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,9 @@
|
||||||
#include "vm/TraceLogging.h"
|
#include "vm/TraceLogging.h"
|
||||||
#include "wasm/AsmJS.h"
|
#include "wasm/AsmJS.h"
|
||||||
#include "wasm/WasmBaselineCompile.h"
|
#include "wasm/WasmBaselineCompile.h"
|
||||||
|
#include "wasm/WasmCraneliftCompile.h"
|
||||||
#include "wasm/WasmInstance.h"
|
#include "wasm/WasmInstance.h"
|
||||||
|
#include "wasm/WasmIonCompile.h"
|
||||||
#include "wasm/WasmJS.h"
|
#include "wasm/WasmJS.h"
|
||||||
#include "wasm/WasmModule.h"
|
#include "wasm/WasmModule.h"
|
||||||
#include "wasm/WasmSignalHandlers.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) {
|
static bool WasmIsSupportedByHardware(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasCompilerSupport(cx));
|
args.rval().setBoolean(wasm::HasPlatformSupport(cx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmDebuggingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmDebuggingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmStreamingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmStreamingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasStreamingSupport(cx));
|
args.rval().setBoolean(wasm::StreamingCompilationAvailable(cx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmCachingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmCachingIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasCachingSupport(cx));
|
args.rval().setBoolean(wasm::CodeCachingAvailable(cx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,26 +752,9 @@ static bool WasmHugeMemoryIsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return true;
|
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) {
|
static bool WasmThreadsSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
bool isSupported = wasm::HasSupport(cx);
|
args.rval().setBoolean(wasm::ThreadsAvailable(cx));
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
|
||||||
if (cx->options().wasmCranelift()) {
|
|
||||||
isSupported = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
args.rval().setBoolean(isSupported);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,47 +772,69 @@ static bool WasmBulkMemSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
|
||||||
static bool WasmReftypesEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmReftypesEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasReftypesSupport(cx));
|
args.rval().setBoolean(wasm::ReftypesAvailable(cx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasGcSupport(cx));
|
args.rval().setBoolean(wasm::GcTypesAvailable(cx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmMultiValueEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmMultiValueEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasMultiValueSupport(cx));
|
args.rval().setBoolean(wasm::MultiValuesAvailable(cx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmBigIntEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmBigIntEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasI64BigIntSupport(cx));
|
args.rval().setBoolean(wasm::I64BigIntConversionAvailable(cx));
|
||||||
return true;
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmCompileMode(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmCompileMode(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
bool baseline = cx->options().wasmBaseline();
|
// This triplet of predicates will select zero or one baseline compiler and
|
||||||
bool ion = cx->options().wasmIon();
|
// zero or one optimizing compiler.
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
bool baseline = wasm::BaselineAvailable(cx);
|
||||||
bool cranelift = cx->options().wasmCranelift();
|
bool ion = wasm::IonAvailable(cx);
|
||||||
#else
|
bool cranelift = wasm::CraneliftAvailable(cx);
|
||||||
bool cranelift = false;
|
|
||||||
#endif
|
MOZ_ASSERT(!(ion && cranelift));
|
||||||
|
|
||||||
// We default to ion if nothing is enabled, as does the Wasm compiler.
|
|
||||||
JSString* result;
|
JSString* result;
|
||||||
if (!wasm::HasSupport(cx)) {
|
if (!wasm::HasSupport(cx)) {
|
||||||
result = JS_NewStringCopyZ(cx, "none");
|
result = JS_NewStringCopyZ(cx, "none");
|
||||||
|
@ -851,6 +858,45 @@ static bool WasmCompileMode(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return true;
|
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) {
|
static bool WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
RootedObject callee(cx, &args.callee());
|
RootedObject callee(cx, &args.callee());
|
||||||
|
@ -6629,12 +6675,6 @@ gc::ZealModeHelpText),
|
||||||
" Returns a boolean indicating whether WebAssembly supports using a large"
|
" Returns a boolean indicating whether WebAssembly supports using a large"
|
||||||
" virtual memory reservation in order to elide bounds checks on this platform."),
|
" 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,
|
JS_FN_HELP("wasmThreadsSupported", WasmThreadsSupported, 0, 0,
|
||||||
"wasmThreadsSupported()",
|
"wasmThreadsSupported()",
|
||||||
" Returns a boolean indicating whether the WebAssembly threads proposal is\n"
|
" 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"
|
" Returns a boolean indicating whether the WebAssembly bulk memory proposal is\n"
|
||||||
" supported on the current device."),
|
" 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,
|
JS_FN_HELP("wasmCompileMode", WasmCompileMode, 0, 0,
|
||||||
"wasmCompileMode()",
|
"wasmCompileMode()",
|
||||||
" Returns a string indicating the available compile policy: 'baseline', 'ion',\n"
|
" Returns a string indicating the available wasm compilers: 'baseline', 'ion',\n"
|
||||||
" 'baseline-or-ion', or 'disabled' (if wasm is not available at all)."),
|
" '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,
|
JS_FN_HELP("wasmTextToBinary", WasmTextToBinary, 1, 0,
|
||||||
"wasmTextToBinary(str)",
|
"wasmTextToBinary(str)",
|
||||||
|
@ -6693,10 +6754,6 @@ gc::ZealModeHelpText),
|
||||||
"wasmBigIntEnabled()",
|
"wasmBigIntEnabled()",
|
||||||
" Returns a boolean indicating whether the WebAssembly I64 to BigInt proposal is enabled."),
|
" 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,
|
JS_FN_HELP("isLazyFunction", IsLazyFunction, 1, 0,
|
||||||
"isLazyFunction(fun)",
|
"isLazyFunction(fun)",
|
||||||
" True if fun is a lazy JSFunction."),
|
" True if fun is a lazy JSFunction."),
|
||||||
|
|
|
@ -139,16 +139,20 @@ static int testWasmFuzz(const uint8_t* buf, size_t size) {
|
||||||
// overwritten later on.
|
// overwritten later on.
|
||||||
uint8_t optByte = (uint8_t)buf[currentIndex];
|
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 enableWasmBaseline = ((optByte & 0xF0) == (1 << 7));
|
||||||
bool enableWasmIon = IonCanCompile() && ((optByte & 0xF0) == (1 << 6));
|
bool enableWasmIon =
|
||||||
|
IonPlatformSupport() && ((optByte & 0xF0) == (1 << 6));
|
||||||
bool enableWasmCranelift = false;
|
bool enableWasmCranelift = false;
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
enableWasmCranelift =
|
enableWasmCranelift =
|
||||||
CraneliftCanCompile() && ((optByte & 0xF0) == (1 << 5));
|
CraneliftPlatformSupport() && ((optByte & 0xF0) == (1 << 5));
|
||||||
#endif
|
#endif
|
||||||
bool enableWasmAwaitTier2 = (IonCanCompile()
|
bool enableWasmAwaitTier2 = (IonPlatformSupport()
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
|| CraneliftCanCompile()
|
|| CraneliftPlatformSupport()
|
||||||
#endif
|
#endif
|
||||||
) &&
|
) &&
|
||||||
((optByte & 0xF) == (1 << 3));
|
((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,
|
// more platform specific JIT code. However, on some platforms,
|
||||||
// e.g. ARM64, we do not have Ion available, so we need to switch
|
// e.g. ARM64, we do not have Ion available, so we need to switch
|
||||||
// to baseline instead.
|
// to baseline instead.
|
||||||
if (IonCanCompile()) {
|
if (IonPlatformSupport()) {
|
||||||
enableWasmIon = true;
|
enableWasmIon = true;
|
||||||
} else {
|
} else {
|
||||||
enableWasmBaseline = true;
|
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.
|
// Tests that wasm module scripts has inspectable globals and memory.
|
||||||
|
|
||||||
load(libdir + "wasm.js");
|
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.
|
// Tests that JS can be evaluated on wasm module scripts frames.
|
||||||
|
|
||||||
load(libdir + "wasm.js");
|
load(libdir + "wasm.js");
|
||||||
|
|
|
@ -3054,8 +3054,14 @@ const cacheEntry = streamCacheEntry(bytecode);
|
||||||
|
|
||||||
runBox2d(cacheEntry);
|
runBox2d(cacheEntry);
|
||||||
|
|
||||||
while (!wasmHasTier2CompilationCompleted(cacheEntry.module)) sleep(1);
|
while (!wasmHasTier2CompilationCompleted(cacheEntry.module))
|
||||||
assertEq(cacheEntry.cached, wasmCachingIsSupported());
|
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);
|
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.
|
// element segment is completely OOB.
|
||||||
assertEq(typeof tbl.get(0), "function");
|
assertEq(typeof tbl.get(0), "function");
|
||||||
assertEq(tbl.get(1), null);
|
assertEq(tbl.get(1), null);
|
||||||
} else if (!wasmUsesCranelift()) {
|
} else if (!wasmCompileMode().match("cranelift")) {
|
||||||
assertEq(tbl.get(0), null);
|
assertEq(tbl.get(0), null);
|
||||||
assertEq(tbl.get(1), null);
|
assertEq(tbl.get(1), null);
|
||||||
}
|
}
|
||||||
|
@ -543,7 +543,7 @@ if (wasmBulkMemSupported()) {
|
||||||
assertEq(typeof tbl.get(0), "function");
|
assertEq(typeof tbl.get(0), "function");
|
||||||
assertEq(typeof tbl.get(1), "function");
|
assertEq(typeof tbl.get(1), "function");
|
||||||
assertEq(mem8[0], 1);
|
assertEq(mem8[0], 1);
|
||||||
} else if (!wasmUsesCranelift()) {
|
} else if (!wasmCompileMode().match("cranelift")) {
|
||||||
assertEq(tbl.get(0), null);
|
assertEq(tbl.get(0), null);
|
||||||
assertEq(tbl.get(1), null);
|
assertEq(tbl.get(1), null);
|
||||||
assertEq(mem8[0], 0);
|
assertEq(mem8[0], 0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmDebugSupport()
|
// |jit-test| skip-if: !wasmDebuggingIsSupported()
|
||||||
var g = newGlobal({newCompartment: true});
|
var g = newGlobal({newCompartment: true});
|
||||||
g.parent = this;
|
g.parent = this;
|
||||||
g.eval("Debugger(parent).onExceptionUnwind = function () {};");
|
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 g = newGlobal({newCompartment: true});
|
||||||
var dbg = new g.Debugger(this);
|
var dbg = new g.Debugger(this);
|
||||||
var dbg = new Debugger;
|
var dbg = new Debugger;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmDebugSupport()
|
// |jit-test| skip-if: !wasmDebuggingIsSupported()
|
||||||
var evalInFrame = (function(global) {
|
var evalInFrame = (function(global) {
|
||||||
var dbgGlobal = newGlobal({newCompartment: true});
|
var dbgGlobal = newGlobal({newCompartment: true});
|
||||||
var dbg = new dbgGlobal.Debugger();
|
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(`
|
var mod = new WebAssembly.Module(wasmTextToBinary(`
|
||||||
(module
|
(module
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmDebugSupport()
|
// |jit-test| skip-if: !wasmDebuggingIsSupported()
|
||||||
g = newGlobal({newCompartment: true});
|
g = newGlobal({newCompartment: true});
|
||||||
g.parent = this;
|
g.parent = this;
|
||||||
g.eval("(" + function() {
|
g.eval("(" + function() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmDebugSupport()
|
// |jit-test| skip-if: !wasmDebuggingIsSupported()
|
||||||
g = newGlobal({newCompartment: true});
|
g = newGlobal({newCompartment: true});
|
||||||
g.parent = this;
|
g.parent = this;
|
||||||
g.eval("(" + function() {
|
g.eval("(" + function() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmIsSupported() || !wasmDebugSupport(); exitstatus:3
|
// |jit-test| skip-if: !wasmDebuggingIsSupported(); exitstatus:3
|
||||||
|
|
||||||
function userError() {};
|
function userError() {};
|
||||||
|
|
||||||
|
|
|
@ -862,7 +862,7 @@ void LIRGenerator::visitWasmCompareExchangeHeap(MWasmCompareExchangeHeap* ins) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
|
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
|
||||||
MOZ_ASSERT(HasLDSTREXBHD(), "by HasCompilerSupport() constraints");
|
MOZ_ASSERT(HasLDSTREXBHD(), "by HasPlatformSupport() constraints");
|
||||||
|
|
||||||
LWasmCompareExchangeHeap* lir = new (alloc())
|
LWasmCompareExchangeHeap* lir = new (alloc())
|
||||||
LWasmCompareExchangeHeap(useRegister(base), useRegister(ins->oldValue()),
|
LWasmCompareExchangeHeap(useRegister(base), useRegister(ins->oldValue()),
|
||||||
|
@ -885,7 +885,7 @@ void LIRGenerator::visitWasmAtomicExchangeHeap(MWasmAtomicExchangeHeap* ins) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
|
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 base = useRegister(ins->base());
|
||||||
const LAllocation value = useRegister(ins->value());
|
const LAllocation value = useRegister(ins->value());
|
||||||
|
@ -905,7 +905,7 @@ void LIRGenerator::visitWasmAtomicBinopHeap(MWasmAtomicBinopHeap* ins) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
|
MOZ_ASSERT(ins->access().type() < Scalar::Float32);
|
||||||
MOZ_ASSERT(HasLDSTREXBHD(), "by HasCompilerSupport() constraints");
|
MOZ_ASSERT(HasLDSTREXBHD(), "by HasPlatformSupport() constraints");
|
||||||
|
|
||||||
MDefinition* base = ins->base();
|
MDefinition* base = ins->base();
|
||||||
MOZ_ASSERT(base->type() == MIRType::Int32);
|
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;
|
static const double MAX_TIMEOUT_SECONDS = 1800.0;
|
||||||
|
|
||||||
// Not necessarily in sync with the browser
|
// 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
|
// Fuzzing support for JS runtime fuzzing
|
||||||
#ifdef FUZZING_INTERFACES
|
#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
|
// 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
|
// if we're trying to disable a compiler that is currently enabled and that is
|
||||||
// the last compiler enabled then we must throw.
|
// 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 ||
|
if ((opt == JSJITCOMPILER_WASM_JIT_BASELINE ||
|
||||||
opt == JSJITCOMPILER_WASM_JIT_ION ||
|
opt == JSJITCOMPILER_WASM_JIT_ION ||
|
||||||
opt == JSJITCOMPILER_WASM_JIT_CRANELIFT) &&
|
opt == JSJITCOMPILER_WASM_JIT_CRANELIFT) &&
|
||||||
|
@ -6292,7 +6300,7 @@ static bool CompileAndSerializeInSeparateProcess(JSContext* cx,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WasmCompileAndSerialize(JSContext* cx) {
|
static bool WasmCompileAndSerialize(JSContext* cx) {
|
||||||
MOZ_ASSERT(wasm::HasCachingSupport(cx));
|
MOZ_ASSERT(wasm::CodeCachingAvailable(cx));
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// See CompileAndSerializeInSeparateProcess for why we've had to smuggle
|
// 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,
|
static bool WasmCompileInSeparateProcess(JSContext* cx, unsigned argc,
|
||||||
Value* vp) {
|
Value* vp) {
|
||||||
if (!wasm::HasCachingSupport(cx)) {
|
if (!wasm::CodeCachingAvailable(cx)) {
|
||||||
JS_ReportErrorASCII(cx, "WebAssembly caching not supported");
|
JS_ReportErrorASCII(cx, "WebAssembly caching not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6843,10 +6843,10 @@ static bool TryInstantiate(JSContext* cx, CallArgs args, const Module& module,
|
||||||
HandleValue importVal = args.get(1);
|
HandleValue importVal = args.get(1);
|
||||||
HandleValue bufferVal = args.get(2);
|
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.
|
// 'module' may have been produced on a parser thread.
|
||||||
if (!HasCompilerSupport(cx)) {
|
if (!HasPlatformSupport(cx)) {
|
||||||
return LinkFail(cx, "no compiler support");
|
return LinkFail(cx, "no platform support");
|
||||||
}
|
}
|
||||||
|
|
||||||
Rooted<ImportValues> imports(cx);
|
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
|
// 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.
|
// enabled for wasm, since asm.js compilation goes via wasm.
|
||||||
static bool IsAsmJSCompilerAvailable(JSContext* cx) {
|
static bool IsAsmJSCompilerAvailable(JSContext* cx) {
|
||||||
return HasCompilerSupport(cx) && IonCanCompile() && cx->options().wasmIon();
|
return HasPlatformSupport(cx) && IonAvailable(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EstablishPreconditions(JSContext* cx,
|
static bool EstablishPreconditions(JSContext* cx,
|
||||||
|
|
|
@ -12918,7 +12918,7 @@ FuncOffsets BaseCompiler::finish() {
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
bool js::wasm::BaselineCanCompile() {
|
bool js::wasm::BaselinePlatformSupport() {
|
||||||
#if defined(JS_CODEGEN_ARM)
|
#if defined(JS_CODEGEN_ARM)
|
||||||
// Simplifying assumption: require SDIV and UDIV.
|
// Simplifying assumption: require SDIV and UDIV.
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,8 +25,9 @@ namespace js {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
// Return whether BaselineCompileFunction can generate code on the current
|
// Return whether BaselineCompileFunction can generate code on the current
|
||||||
// device.
|
// device. Usually you do *not* want to call this, you want
|
||||||
bool BaselineCanCompile();
|
// BaselineAvailable().
|
||||||
|
MOZ_MUST_USE bool BaselinePlatformSupport();
|
||||||
|
|
||||||
// Generate adequate code quickly.
|
// Generate adequate code quickly.
|
||||||
MOZ_MUST_USE bool BaselineCompileFunctions(const ModuleEnvironment& env,
|
MOZ_MUST_USE bool BaselineCompileFunctions(const ModuleEnvironment& env,
|
||||||
|
|
|
@ -78,25 +78,12 @@ uint32_t wasm::ObservedCPUFeatures() {
|
||||||
|
|
||||||
SharedCompileArgs CompileArgs::build(JSContext* cx,
|
SharedCompileArgs CompileArgs::build(JSContext* cx,
|
||||||
ScriptedCaller&& scriptedCaller) {
|
ScriptedCaller&& scriptedCaller) {
|
||||||
bool baseline = BaselineCanCompile() && cx->options().wasmBaseline();
|
bool baseline = BaselineAvailable(cx);
|
||||||
bool ion = IonCanCompile() && cx->options().wasmIon();
|
bool ion = IonAvailable(cx);
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
bool cranelift = CraneliftAvailable(cx);
|
||||||
bool cranelift = CraneliftCanCompile() && cx->options().wasmCranelift();
|
|
||||||
#else
|
|
||||||
bool cranelift = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
// At most one optimizing compiler.
|
||||||
bool gc = cx->options().wasmGc();
|
MOZ_RELEASE_ASSERT(!(ion && cranelift));
|
||||||
#else
|
|
||||||
bool gc = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
|
||||||
bool bigInt = cx->options().isWasmBigIntEnabled();
|
|
||||||
#else
|
|
||||||
bool bigInt = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Debug information such as source view or debug traps will require
|
// Debug information such as source view or debug traps will require
|
||||||
// additional memory and permanently stay in baseline code, so we try to
|
// additional memory and permanently stay in baseline code, so we try to
|
||||||
|
@ -104,39 +91,23 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
|
||||||
// is open.
|
// is open.
|
||||||
bool debug = cx->realm()->debuggerObservesAsmJS();
|
bool debug = cx->realm()->debuggerObservesAsmJS();
|
||||||
|
|
||||||
bool sharedMemory =
|
|
||||||
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
|
|
||||||
bool forceTiering =
|
bool forceTiering =
|
||||||
cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2;
|
cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2;
|
||||||
|
|
||||||
if (debug || gc) {
|
// The <Compiler>Available() predicates should ensure this.
|
||||||
if (!baseline) {
|
MOZ_RELEASE_ASSERT(!(debug && (ion || cranelift)));
|
||||||
JS_ReportErrorASCII(cx, "can't use wasm debug/gc without baseline");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
ion = false;
|
|
||||||
cranelift = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
// 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,
|
// 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.
|
// instead of adding a skip-if directive to every test using debug/gc.
|
||||||
forceTiering = false;
|
forceTiering = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
if (!(baseline || ion || cranelift)) {
|
||||||
if (!baseline && !ion && !cranelift) {
|
JS_ReportErrorASCII(cx, "no WebAssembly compiler available");
|
||||||
if (cx->options().wasmCranelift() && !CraneliftCanCompile()) {
|
return nullptr;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// HasCompilerSupport() should prevent failure here.
|
|
||||||
MOZ_RELEASE_ASSERT(baseline || ion || cranelift);
|
|
||||||
|
|
||||||
CompileArgs* target = cx->new_<CompileArgs>(std::move(scriptedCaller));
|
CompileArgs* target = cx->new_<CompileArgs>(std::move(scriptedCaller));
|
||||||
if (!target) {
|
if (!target) {
|
||||||
|
@ -147,11 +118,17 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
|
||||||
target->ionEnabled = ion;
|
target->ionEnabled = ion;
|
||||||
target->craneliftEnabled = cranelift;
|
target->craneliftEnabled = cranelift;
|
||||||
target->debugEnabled = debug;
|
target->debugEnabled = debug;
|
||||||
target->sharedMemoryEnabled = sharedMemory;
|
target->sharedMemoryEnabled =
|
||||||
|
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
|
||||||
target->forceTiering = forceTiering;
|
target->forceTiering = forceTiering;
|
||||||
target->gcEnabled = gc;
|
target->gcEnabled = wasm::GcTypesAvailable(cx);
|
||||||
target->hugeMemory = wasm::IsHugeMemoryEnabled();
|
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;
|
return target;
|
||||||
}
|
}
|
||||||
|
@ -486,13 +463,15 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
|
||||||
bool forceTiering = args_->forceTiering;
|
bool forceTiering = args_->forceTiering;
|
||||||
bool hugeMemory = args_->hugeMemory;
|
bool hugeMemory = args_->hugeMemory;
|
||||||
bool bigIntEnabled = args_->bigIntEnabled;
|
bool bigIntEnabled = args_->bigIntEnabled;
|
||||||
|
bool multiValuesEnabled = args_->multiValuesEnabled;
|
||||||
|
|
||||||
bool hasSecondTier = ionEnabled || craneliftEnabled;
|
bool hasSecondTier = ionEnabled || craneliftEnabled;
|
||||||
MOZ_ASSERT_IF(gcEnabled || debugEnabled, baselineEnabled);
|
MOZ_ASSERT_IF(debugEnabled, baselineEnabled);
|
||||||
MOZ_ASSERT_IF(forceTiering, baselineEnabled && hasSecondTier);
|
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(baselineEnabled || ionEnabled || craneliftEnabled);
|
||||||
|
MOZ_RELEASE_ASSERT(!(ionEnabled && craneliftEnabled));
|
||||||
|
|
||||||
uint32_t codeSectionSize = 0;
|
uint32_t codeSectionSize = 0;
|
||||||
|
|
||||||
|
@ -516,13 +495,10 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
|
||||||
debug_ = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
|
debug_ = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
|
||||||
gcTypes_ = gcEnabled;
|
gcTypes_ = gcEnabled;
|
||||||
refTypes_ = true;
|
refTypes_ = true;
|
||||||
#ifdef ENABLE_WASM_MULTI_VALUE
|
multiValues_ = multiValuesEnabled;
|
||||||
multiValues_ = !craneliftEnabled;
|
|
||||||
#else
|
|
||||||
multiValues_ = false;
|
|
||||||
#endif
|
|
||||||
hugeMemory_ = hugeMemory;
|
hugeMemory_ = hugeMemory;
|
||||||
bigInt_ = bigIntEnabled && !craneliftEnabled;
|
bigInt_ = bigIntEnabled;
|
||||||
|
multiValues_ = multiValuesEnabled;
|
||||||
state_ = Computed;
|
state_ = Computed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,12 +603,8 @@ void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
||||||
#else
|
#else
|
||||||
bool refTypesConfigured = false;
|
bool refTypesConfigured = false;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_MULTI_VALUE
|
bool multiValueConfigured = args.multiValuesEnabled;
|
||||||
bool multiValueConfigured = !args.craneliftEnabled;
|
bool bigIntConfigured = args.bigIntEnabled;
|
||||||
#else
|
|
||||||
bool multiValueConfigured = false;
|
|
||||||
#endif
|
|
||||||
bool bigIntConfigured = args.bigIntEnabled && !args.craneliftEnabled;
|
|
||||||
|
|
||||||
OptimizedBackend optimizedBackend = args.craneliftEnabled
|
OptimizedBackend optimizedBackend = args.craneliftEnabled
|
||||||
? OptimizedBackend::Cranelift
|
? OptimizedBackend::Cranelift
|
||||||
|
|
|
@ -59,6 +59,7 @@ struct CompileArgs : ShareableBase<CompileArgs> {
|
||||||
bool gcEnabled;
|
bool gcEnabled;
|
||||||
bool hugeMemory;
|
bool hugeMemory;
|
||||||
bool bigIntEnabled;
|
bool bigIntEnabled;
|
||||||
|
bool multiValuesEnabled;
|
||||||
|
|
||||||
// CompileArgs has two constructors:
|
// CompileArgs has two constructors:
|
||||||
//
|
//
|
||||||
|
@ -82,7 +83,8 @@ struct CompileArgs : ShareableBase<CompileArgs> {
|
||||||
forceTiering(false),
|
forceTiering(false),
|
||||||
gcEnabled(false),
|
gcEnabled(false),
|
||||||
hugeMemory(false),
|
hugeMemory(false),
|
||||||
bigIntEnabled(false) {}
|
bigIntEnabled(false),
|
||||||
|
multiValuesEnabled(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the estimated compiled (machine) code size for the given bytecode size
|
// 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::jit;
|
||||||
using namespace js::wasm;
|
using namespace js::wasm;
|
||||||
|
|
||||||
bool wasm::CraneliftCanCompile() {
|
bool wasm::CraneliftPlatformSupport() {
|
||||||
#ifdef JS_CODEGEN_X64
|
#ifdef JS_CODEGEN_X64
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
@ -427,7 +427,7 @@ bool wasm::CraneliftCompileFunctions(const ModuleEnvironment& env,
|
||||||
LifoAlloc& lifo,
|
LifoAlloc& lifo,
|
||||||
const FuncCompileInputVector& inputs,
|
const FuncCompileInputVector& inputs,
|
||||||
CompiledCode* code, UniqueChars* error) {
|
CompiledCode* code, UniqueChars* error) {
|
||||||
MOZ_RELEASE_ASSERT(CraneliftCanCompile());
|
MOZ_RELEASE_ASSERT(CraneliftPlatformSupport());
|
||||||
|
|
||||||
MOZ_ASSERT(env.tier() == Tier::Optimized);
|
MOZ_ASSERT(env.tier() == Tier::Optimized);
|
||||||
MOZ_ASSERT(env.optimizedBackend() == OptimizedBackend::Cranelift);
|
MOZ_ASSERT(env.optimizedBackend() == OptimizedBackend::Cranelift);
|
||||||
|
|
|
@ -27,16 +27,25 @@ namespace js {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
MOZ_MUST_USE bool CraneliftCanCompile();
|
// Return whether CraneliftCompileFunction() can generate code on the current
|
||||||
#else
|
// device. Usually you do *not* want this, you want CraneliftAvailable().
|
||||||
MOZ_MUST_USE inline bool CraneliftCanCompile() { return false; }
|
MOZ_MUST_USE bool CraneliftPlatformSupport();
|
||||||
#endif
|
|
||||||
|
|
||||||
// Generates code with Cranelift.
|
// Generates code with Cranelift.
|
||||||
MOZ_MUST_USE bool CraneliftCompileFunctions(
|
MOZ_MUST_USE bool CraneliftCompileFunctions(
|
||||||
const ModuleEnvironment& env, LifoAlloc& lifo,
|
const ModuleEnvironment& env, LifoAlloc& lifo,
|
||||||
const FuncCompileInputVector& inputs, CompiledCode* code,
|
const FuncCompileInputVector& inputs, CompiledCode* code,
|
||||||
UniqueChars* error);
|
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 wasm
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
|
@ -724,19 +724,19 @@ static bool ExecuteCompileTask(CompileTask* task, UniqueChars* error) {
|
||||||
|
|
||||||
switch (task->env.tier()) {
|
switch (task->env.tier()) {
|
||||||
case Tier::Optimized:
|
case Tier::Optimized:
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
switch (task->env.optimizedBackend()) {
|
||||||
if (task->env.optimizedBackend() == OptimizedBackend::Cranelift) {
|
case OptimizedBackend::Cranelift:
|
||||||
if (!CraneliftCompileFunctions(task->env, task->lifo, task->inputs,
|
if (!CraneliftCompileFunctions(task->env, task->lifo, task->inputs,
|
||||||
&task->output, error)) {
|
&task->output, error)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
case OptimizedBackend::Ion:
|
||||||
#endif
|
if (!IonCompileFunctions(task->env, task->lifo, task->inputs,
|
||||||
MOZ_ASSERT(task->env.optimizedBackend() == OptimizedBackend::Ion);
|
&task->output, error)) {
|
||||||
if (!IonCompileFunctions(task->env, task->lifo, task->inputs,
|
return false;
|
||||||
&task->output, error)) {
|
}
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Tier::Baseline:
|
case Tier::Baseline:
|
||||||
|
|
|
@ -117,7 +117,7 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fi.funcType().hasI64ArgOrRet() && !HasI64BigIntSupport(cx)) {
|
if (fi.funcType().hasI64ArgOrRet() && !I64BigIntConversionAvailable(cx)) {
|
||||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_WASM_BAD_I64_TYPE);
|
JSMSG_WASM_BAD_I64_TYPE);
|
||||||
return false;
|
return false;
|
||||||
|
@ -132,7 +132,7 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
|
||||||
}
|
}
|
||||||
case ValType::I64: {
|
case ValType::I64: {
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
MOZ_ASSERT(HasI64BigIntSupport(cx));
|
MOZ_ASSERT(I64BigIntConversionAvailable(cx));
|
||||||
// If bi is manipulated other than test & storing, it would need
|
// If bi is manipulated other than test & storing, it would need
|
||||||
// to be rooted here.
|
// to be rooted here.
|
||||||
BigInt* bi = BigInt::createFromInt64(cx, *(int64_t*)&argv[i]);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funcType->hasI64ArgOrRet() && !HasI64BigIntSupport(cx)) {
|
if (funcType->hasI64ArgOrRet() && !I64BigIntConversionAvailable(cx)) {
|
||||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_WASM_BAD_I64_TYPE);
|
JSMSG_WASM_BAD_I64_TYPE);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1729,7 +1729,7 @@ bool Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args) {
|
||||||
break;
|
break;
|
||||||
case ValType::I64: {
|
case ValType::I64: {
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
MOZ_ASSERT(HasI64BigIntSupport(cx),
|
MOZ_ASSERT(I64BigIntConversionAvailable(cx),
|
||||||
"unexpected i64 flowing into callExport");
|
"unexpected i64 flowing into callExport");
|
||||||
RootedBigInt bigint(cx, ToBigInt(cx, v));
|
RootedBigInt bigint(cx, ToBigInt(cx, v));
|
||||||
if (!bigint) {
|
if (!bigint) {
|
||||||
|
@ -1848,7 +1848,7 @@ bool Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args) {
|
||||||
break;
|
break;
|
||||||
case ValType::I64: {
|
case ValType::I64: {
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
MOZ_ASSERT(HasI64BigIntSupport(cx),
|
MOZ_ASSERT(I64BigIntConversionAvailable(cx),
|
||||||
"unexpected i64 flowing from callExport");
|
"unexpected i64 flowing from callExport");
|
||||||
// If bi is manipulated other than test & storing, it would need
|
// If bi is manipulated other than test & storing, it would need
|
||||||
// to be rooted here.
|
// to be rooted here.
|
||||||
|
|
|
@ -4745,7 +4745,7 @@ bool wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,
|
||||||
return code->swap(masm);
|
return code->swap(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool js::wasm::IonCanCompile() {
|
bool js::wasm::IonPlatformSupport() {
|
||||||
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || \
|
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || \
|
||||||
defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || \
|
defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || \
|
||||||
defined(JS_CODEGEN_MIPS64)
|
defined(JS_CODEGEN_MIPS64)
|
||||||
|
|
|
@ -27,7 +27,8 @@ namespace js {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
// Return whether IonCompileFunction() can generate code on the current device.
|
// 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.
|
// Generates very fast code at the expense of compilation time.
|
||||||
MOZ_MUST_USE bool IonCompileFunctions(const ModuleEnvironment& env,
|
MOZ_MUST_USE bool IonCompileFunctions(const ModuleEnvironment& env,
|
||||||
|
|
|
@ -64,33 +64,7 @@ using mozilla::RangedPtr;
|
||||||
|
|
||||||
extern mozilla::Atomic<bool> fuzzingSafe;
|
extern mozilla::Atomic<bool> fuzzingSafe;
|
||||||
|
|
||||||
bool wasm::HasReftypesSupport(JSContext* cx) {
|
static inline bool WasmMultiValueFlag(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
|
|
||||||
#ifdef ENABLE_WASM_MULTI_VALUE
|
#ifdef ENABLE_WASM_MULTI_VALUE
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
@ -98,12 +72,132 @@ bool wasm::HasMultiValueSupport(JSContext* cx) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasm::HasI64BigIntSupport(JSContext* cx) {
|
// Compiler availability predicates. These must be kept in sync with the
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
// feature predicates in the next section below.
|
||||||
if (cx->options().wasmCranelift()) {
|
//
|
||||||
|
// 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;
|
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
|
#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
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
return cx->options().isWasmBigIntEnabled();
|
return cx->options().isWasmBigIntEnabled();
|
||||||
#else
|
#else
|
||||||
|
@ -111,7 +205,14 @@ bool wasm::HasI64BigIntSupport(JSContext* cx) {
|
||||||
#endif
|
#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)
|
#if !MOZ_LITTLE_ENDIAN() || defined(JS_CODEGEN_NONE)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -143,22 +244,10 @@ bool wasm::HasCompilerSupport(JSContext* cx) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return BaselineCanCompile() || IonCanCompile() || CraneliftCanCompile();
|
// Test only whether the compilers are supported on the hardware, not whether
|
||||||
}
|
// they are enabled.
|
||||||
|
return BaselinePlatformSupport() || IonPlatformSupport() ||
|
||||||
bool wasm::HasOptimizedCompilerTier(JSContext* cx) {
|
CraneliftPlatformSupport();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasm::HasSupport(JSContext* cx) {
|
bool wasm::HasSupport(JSContext* cx) {
|
||||||
|
@ -170,10 +259,11 @@ bool wasm::HasSupport(JSContext* cx) {
|
||||||
cx->realm()->principals() &&
|
cx->realm()->principals() &&
|
||||||
cx->realm()->principals()->isSystemOrAddonPrincipal();
|
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().
|
// This should match EnsureStreamSupport().
|
||||||
return HasSupport(cx) &&
|
return HasSupport(cx) &&
|
||||||
cx->runtime()->offThreadPromiseState.ref().initialized() &&
|
cx->runtime()->offThreadPromiseState.ref().initialized() &&
|
||||||
|
@ -181,8 +271,12 @@ bool wasm::HasStreamingSupport(JSContext* cx) {
|
||||||
cx->runtime()->reportStreamErrorCallback;
|
cx->runtime()->reportStreamErrorCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasm::HasCachingSupport(JSContext* cx) {
|
bool wasm::CodeCachingAvailable(JSContext* cx) {
|
||||||
return HasStreamingSupport(cx) && HasOptimizedCompilerTier(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,
|
bool wasm::CheckRefType(JSContext* cx, RefType::Kind targetTypeKind,
|
||||||
|
@ -242,7 +336,7 @@ static bool ToWebAssemblyValue(JSContext* cx, ValType targetType, HandleValue v,
|
||||||
}
|
}
|
||||||
case ValType::I64: {
|
case ValType::I64: {
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
if (HasI64BigIntSupport(cx)) {
|
if (I64BigIntConversionAvailable(cx)) {
|
||||||
BigInt* bigint = ToBigInt(cx, v);
|
BigInt* bigint = ToBigInt(cx, v);
|
||||||
if (!bigint) {
|
if (!bigint) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -289,7 +383,7 @@ static bool ToJSValue(JSContext* cx, const Val& val, MutableHandleValue out) {
|
||||||
return true;
|
return true;
|
||||||
case ValType::I64: {
|
case ValType::I64: {
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
if (HasI64BigIntSupport(cx)) {
|
if (I64BigIntConversionAvailable(cx)) {
|
||||||
BigInt* bi = BigInt::createFromInt64(cx, val.i64());
|
BigInt* bi = BigInt::createFromInt64(cx, val.i64());
|
||||||
if (!bi) {
|
if (!bi) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -442,7 +536,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module,
|
||||||
obj->val(&val);
|
obj->val(&val);
|
||||||
} else {
|
} else {
|
||||||
if (IsNumberType(global.type())) {
|
if (IsNumberType(global.type())) {
|
||||||
if (HasI64BigIntSupport(cx)) {
|
if (I64BigIntConversionAvailable(cx)) {
|
||||||
if (global.type() == ValType::I64 && v.isNumber()) {
|
if (global.type() == ValType::I64 && v.isNumber()) {
|
||||||
return ThrowBadImportType(cx, import.field.get(), "BigInt");
|
return ThrowBadImportType(cx, import.field.get(), "BigInt");
|
||||||
}
|
}
|
||||||
|
@ -591,10 +685,15 @@ bool wasm::CompileAndSerialize(const ShareableBytes& bytecode,
|
||||||
return false;
|
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
|
// we go straight to tier-2 so that we synchronously call
|
||||||
// JS::OptimizedEncodingListener::storeOptimizedEncoding().
|
// JS::OptimizedEncodingListener::storeOptimizedEncoding().
|
||||||
compileArgs->baselineEnabled = false;
|
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;
|
compileArgs->ionEnabled = true;
|
||||||
|
|
||||||
// The caller must ensure that huge memory support is configured the same in
|
// 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
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
} else if (StringEqualsLiteral(elementLinearStr, "anyref") ||
|
} else if (StringEqualsLiteral(elementLinearStr, "anyref") ||
|
||||||
StringEqualsLiteral(elementLinearStr, "nullref")) {
|
StringEqualsLiteral(elementLinearStr, "nullref")) {
|
||||||
if (!HasReftypesSupport(cx)) {
|
if (!ReftypesAvailable(cx)) {
|
||||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_WASM_BAD_ELEMENT);
|
JSMSG_WASM_BAD_ELEMENT);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2735,18 +2834,18 @@ bool WasmGlobalObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
} else if (StringEqualsLiteral(typeLinearStr, "f64")) {
|
} else if (StringEqualsLiteral(typeLinearStr, "f64")) {
|
||||||
globalType = ValType::F64;
|
globalType = ValType::F64;
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
} else if (HasI64BigIntSupport(cx) &&
|
} else if (I64BigIntConversionAvailable(cx) &&
|
||||||
StringEqualsLiteral(typeLinearStr, "i64")) {
|
StringEqualsLiteral(typeLinearStr, "i64")) {
|
||||||
globalType = ValType::I64;
|
globalType = ValType::I64;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_REFTYPES
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
} else if (HasReftypesSupport(cx) &&
|
} else if (ReftypesAvailable(cx) &&
|
||||||
StringEqualsLiteral(typeLinearStr, "funcref")) {
|
StringEqualsLiteral(typeLinearStr, "funcref")) {
|
||||||
globalType = RefType::func();
|
globalType = RefType::func();
|
||||||
} else if (HasReftypesSupport(cx) &&
|
} else if (ReftypesAvailable(cx) &&
|
||||||
StringEqualsLiteral(typeLinearStr, "anyref")) {
|
StringEqualsLiteral(typeLinearStr, "anyref")) {
|
||||||
globalType = RefType::any();
|
globalType = RefType::any();
|
||||||
} else if (HasReftypesSupport(cx) &&
|
} else if (ReftypesAvailable(cx) &&
|
||||||
StringEqualsLiteral(typeLinearStr, "nullref")) {
|
StringEqualsLiteral(typeLinearStr, "nullref")) {
|
||||||
globalType = RefType::null();
|
globalType = RefType::null();
|
||||||
#endif
|
#endif
|
||||||
|
@ -2822,7 +2921,7 @@ bool WasmGlobalObject::valueGetterImpl(JSContext* cx, const CallArgs& args) {
|
||||||
return true;
|
return true;
|
||||||
case ValType::I64:
|
case ValType::I64:
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
if (HasI64BigIntSupport(cx)) {
|
if (I64BigIntConversionAvailable(cx)) {
|
||||||
return args.thisv().toObject().as<WasmGlobalObject>().value(
|
return args.thisv().toObject().as<WasmGlobalObject>().value(
|
||||||
cx, args.rval());
|
cx, args.rval());
|
||||||
}
|
}
|
||||||
|
@ -2866,7 +2965,7 @@ bool WasmGlobalObject::valueSetterImpl(JSContext* cx, const CallArgs& args) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global->type() == ValType::I64 && !HasI64BigIntSupport(cx)) {
|
if (global->type() == ValType::I64 && !I64BigIntConversionAvailable(cx)) {
|
||||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_WASM_BAD_I64_TYPE);
|
JSMSG_WASM_BAD_I64_TYPE);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2890,7 +2989,7 @@ bool WasmGlobalObject::valueSetterImpl(JSContext* cx, const CallArgs& args) {
|
||||||
break;
|
break;
|
||||||
case ValType::I64:
|
case ValType::I64:
|
||||||
#ifdef ENABLE_WASM_BIGINT
|
#ifdef ENABLE_WASM_BIGINT
|
||||||
MOZ_ASSERT(HasI64BigIntSupport(cx),
|
MOZ_ASSERT(I64BigIntConversionAvailable(cx),
|
||||||
"expected BigInt support for setting I64 global");
|
"expected BigInt support for setting I64 global");
|
||||||
cell->i64 = val.get().i64();
|
cell->i64 = val.get().i64();
|
||||||
#endif
|
#endif
|
||||||
|
@ -3368,7 +3467,7 @@ static bool WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EnsureStreamSupport(JSContext* cx) {
|
static bool EnsureStreamSupport(JSContext* cx) {
|
||||||
// This should match wasm::HasStreamingSupport().
|
// This should match wasm::StreamingCompilationAvailable().
|
||||||
|
|
||||||
if (!EnsurePromiseSupport(cx)) {
|
if (!EnsurePromiseSupport(cx)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
class ArrayBufferObjectMaybeShared;
|
class ArrayBufferObjectMaybeShared;
|
||||||
|
class JSStringBuilder;
|
||||||
class StructTypeDescr;
|
class StructTypeDescr;
|
||||||
class TypedArrayObject;
|
class TypedArrayObject;
|
||||||
class WasmFunctionScope;
|
class WasmFunctionScope;
|
||||||
|
@ -35,48 +36,81 @@ class SharedArrayRawBuffer;
|
||||||
|
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
// Return whether WebAssembly can be compiled on this platform.
|
// Return whether WebAssembly can in principle be compiled on this platform (ie
|
||||||
// This must be checked and must be true to call any of the top-level wasm
|
// combination of hardware and OS), assuming at least one of the compilers that
|
||||||
// eval/compile methods.
|
// 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);
|
bool HasPlatformSupport(JSContext* cx);
|
||||||
|
|
||||||
// Return whether WebAssembly has support for an optimized compiler backend.
|
|
||||||
|
|
||||||
bool HasOptimizedCompilerTier(JSContext* cx);
|
|
||||||
|
|
||||||
// Return whether WebAssembly is supported on this platform. This determines
|
// Return whether WebAssembly is supported on this platform. This determines
|
||||||
// whether the WebAssembly object is exposed to JS and takes into account
|
// 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);
|
bool HasSupport(JSContext* cx);
|
||||||
|
|
||||||
// Return whether WebAssembly streaming/caching is supported on this platform.
|
// Predicates for compiler availability.
|
||||||
// This takes into account prefs and necessary embedding callbacks.
|
//
|
||||||
|
// 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
|
bool IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
|
||||||
// options can support reference types and stack walking.
|
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
|
// Streaming compilation.
|
||||||
// options can support (ref T) types and structure types, etc (evolving).
|
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
|
// General reference types (anyref, funcref, nullref) and operations on them.
|
||||||
// options can support multi-value block and function returns (evolving).
|
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
|
// Multi-value block and function returns.
|
||||||
// options can support I64 to BigInt conversion.
|
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
|
// Compiles the given binary wasm module given the ArrayBufferObject
|
||||||
// and links the module's imports with the given import object.
|
// 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
|
// this function performs the full installation of signal handlers which must
|
||||||
// be performed per-thread/JSContext. This operation may incur some overhead and
|
// 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
|
// 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.
|
// the 'WebAssembly' object on the global object.
|
||||||
bool EnsureFullSignalHandlers(JSContext* cx);
|
bool EnsureFullSignalHandlers(JSContext* cx);
|
||||||
|
|
||||||
|
|
|
@ -2986,11 +2986,11 @@ bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode,
|
||||||
UniqueChars* error) {
|
UniqueChars* error) {
|
||||||
Decoder d(bytecode.bytes, 0, error);
|
Decoder d(bytecode.bytes, 0, error);
|
||||||
|
|
||||||
bool gcTypesConfigured = HasGcSupport(cx);
|
bool gcTypesConfigured = GcTypesAvailable(cx);
|
||||||
bool refTypesConfigured = HasReftypesSupport(cx);
|
bool refTypesConfigured = ReftypesAvailable(cx);
|
||||||
bool multiValueConfigured = HasMultiValueSupport(cx);
|
bool multiValueConfigured = MultiValuesAvailable(cx);
|
||||||
bool hugeMemory = false;
|
bool hugeMemory = false;
|
||||||
bool bigIntConfigured = HasI64BigIntSupport(cx);
|
bool bigIntConfigured = I64BigIntConversionAvailable(cx);
|
||||||
|
|
||||||
CompilerEnvironment compilerEnv(
|
CompilerEnvironment compilerEnv(
|
||||||
CompileMode::Once, Tier::Optimized, OptimizedBackend::Ion,
|
CompileMode::Once, Tier::Optimized, OptimizedBackend::Ion,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче