Bug 1832378 - wasm: Refactor feature flags and let GC build in beta/release but remain disabled by-default. r=yury

This commit cleans up some of our feature logic.
 - A WasmFeatures.h internal header is added for all this code
 - The stage of a feature is turned into an enum, not a separate
   macro. This is generally easier to read.

As an improvement the concept of 'force enable flag' extension point
was added. This is used to enable the GC proposal even if the function
references proposal is not enabled.

This commit also lets wasm-gc/fr start building in beta/release. They
will remain off by default though (behind a pref).

Differential Revision: https://phabricator.services.mozilla.com/D177681
This commit is contained in:
Ryan Hunt 2023-07-12 15:32:36 +00:00
parent dab12ef62d
commit d796bdc2f7
27 changed files with 614 additions and 534 deletions

View File

@ -666,20 +666,14 @@ option(
# ===========================
@depends(milestone.is_nightly)
def default_wasm_function_references(is_nightly):
if is_nightly:
return True
option(
"--enable-wasm-function-references",
default=default_wasm_function_references,
"--disable-wasm-function-references",
default=True,
help="{Enable|Disable} WebAssembly function-references",
)
@depends("--enable-wasm-function-references", "--wasm-no-experimental")
@depends("--disable-wasm-function-references", "--wasm-no-experimental")
def wasm_function_references(value, no_experimental):
if no_experimental:
return
@ -695,19 +689,19 @@ set_define("ENABLE_WASM_FUNCTION_REFERENCES", wasm_function_references)
# ===========================
@depends(milestone.is_nightly, "--enable-wasm-function-references")
def default_wasm_gc(is_nightly, function_references):
if is_nightly and function_references:
@depends("--disable-wasm-function-references")
def default_wasm_gc(function_references):
if function_references:
return True
option(
"--enable-wasm-gc", default=default_wasm_gc, help="{Enable|Disable} WebAssembly GC"
"--disable-wasm-gc", default=default_wasm_gc, help="{Enable|Disable} WebAssembly GC"
)
@depends(
"--enable-wasm-gc", "--enable-wasm-function-references", "--wasm-no-experimental"
"--disable-wasm-gc", "--disable-wasm-function-references", "--wasm-no-experimental"
)
def wasm_gc(value, function_references, no_experimental):
if no_experimental or not value:
@ -716,7 +710,7 @@ def wasm_gc(value, function_references, no_experimental):
if function_references:
return True
die("--enable-wasm-gc only possible with --enable-wasm-function-references")
die("--disable-wasm-gc only possible with --disable-wasm-function-references")
set_config("ENABLE_WASM_GC", wasm_gc)

View File

@ -27,11 +27,9 @@ class JS_PUBLIC_API ContextOptions {
wasmVerbose_(false),
wasmBaseline_(true),
wasmIon_(true),
#define WASM_DEFAULT_FEATURE(NAME, ...) wasm##NAME##_(true),
#define WASM_EXPERIMENTAL_FEATURE(NAME, ...) wasm##NAME##_(false),
JS_FOR_WASM_FEATURES(WASM_DEFAULT_FEATURE, WASM_DEFAULT_FEATURE, WASM_EXPERIMENTAL_FEATURE)
#undef WASM_DEFAULT_FEATURE
#undef WASM_EXPERIMENTAL_FEATURE
#define WASM_FEATURE(NAME, LOWER_NAME, STAGE, ...) wasm##NAME##_(STAGE == WasmFeatureStage::Default),
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
testWasmAwaitTier2_(false),
throwOnAsmJSValidationFailure_(false),
disableIon_(false),
@ -106,7 +104,7 @@ class JS_PUBLIC_API ContextOptions {
wasm##NAME##_ = flag; \
return *this; \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
bool throwOnAsmJSValidationFailure() const {
@ -214,7 +212,7 @@ class JS_PUBLIC_API ContextOptions {
bool wasmBaseline_ : 1;
bool wasmIon_ : 1;
#define WASM_FEATURE(NAME, ...) bool wasm##NAME##_ : 1;
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
bool testWasmAwaitTier2_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;

View File

@ -55,11 +55,6 @@
// 5. [fuzzing] Add the feature to gluesmith/src/lib.rs, if wasm-smith has
// support for it.
#ifdef ENABLE_WASM_SIMD
# define WASM_SIMD_ENABLED 1
#else
# define WASM_SIMD_ENABLED 0
#endif
#ifdef ENABLE_WASM_RELAXED_SIMD
# define WASM_RELAXED_SIMD_ENABLED 1
#else
@ -101,84 +96,114 @@
# define WASM_MULTI_MEMORY_ENABLED 0
#endif
enum class WasmFeatureStage {
Experimental = 0,
Tentative,
Default,
};
// clang-format off
#define JS_FOR_WASM_FEATURES(DEFAULT, TENTATIVE, EXPERIMENTAL) \
TENTATIVE(/* capitalized name */ ExtendedConst, \
/* lower case name */ extendedConst, \
/* compile predicate */ WASM_EXTENDED_CONST_ENABLED, \
/* compiler predicate */ true, \
/* flag predicate */ true, \
/* shell flag */ "extended-const", \
/* preference name */ "extended_const") \
TENTATIVE( \
/* capitalized name */ Exceptions, \
/* lower case name */ exceptions, \
/* compile predicate */ true, \
/* compiler predicate */ BaselineAvailable(cx) || IonAvailable(cx), \
/* flag predicate */ true, \
/* shell flag */ "exceptions", \
/* preference name */ "exceptions") \
EXPERIMENTAL(/* capitalized name */ FunctionReferences, \
/* lower case name */ functionReferences, \
/* compile predicate */ WASM_FUNCTION_REFERENCES_ENABLED, \
/* compiler predicate */ BaselineAvailable(cx) || \
IonAvailable(cx), \
/* flag predicate */ true, \
/* shell flag */ "function-references", \
/* preference name */ "function_references") \
EXPERIMENTAL(/* capitalized name */ Gc, \
/* lower case name */ gc, \
/* compile predicate */ WASM_GC_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ WasmFunctionReferencesFlag(cx), \
/* shell flag */ "gc", \
/* preference name */ "gc") \
TENTATIVE(/* capitalized name */ RelaxedSimd, \
/* lower case name */ v128Relaxed, \
/* compile predicate */ WASM_RELAXED_SIMD_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ js::jit::JitSupportsWasmSimd(), \
/* shell flag */ "relaxed-simd", \
/* preference name */ "relaxed_simd") \
TENTATIVE( \
/* capitalized name */ Memory64, \
/* lower case name */ memory64, \
/* compile predicate */ WASM_MEMORY64_ENABLED, \
/* compiler predicate */ BaselineAvailable(cx) || IonAvailable(cx), \
/* flag predicate */ true, \
/* shell flag */ "memory64", \
/* preference name */ "memory64") \
EXPERIMENTAL( \
/* capitalized name */ MemoryControl, \
/* lower case name */ memoryControl, \
/* compile predicate */ WASM_MEMORY_CONTROL_ENABLED, \
/* compiler predicate */ BaselineAvailable(cx) || IonAvailable(cx), \
/* flag predicate */ true, \
/* shell flag */ "memory-control", \
/* preference name */ "memory_control") \
EXPERIMENTAL( \
/* capitalized name */ MultiMemory, \
/* lower case name */ multiMemory, \
/* compile predicate */ WASM_MULTI_MEMORY_ENABLED, \
/* compiler predicate */ BaselineAvailable(cx) || IonAvailable(cx), \
/* flag predicate */ true, \
/* shell flag */ "multi-memory", \
/* preference name */ "multi_memory") \
EXPERIMENTAL(/* capitalized name */ MozIntGemm, \
/* lower case name */ mozIntGemm, \
/* compile predicate */ WASM_MOZ_INTGEMM_ENABLED, \
/* compiler predicate */ BaselineAvailable(cx) || \
IonAvailable(cx), \
/* flag predicate */ IsSimdPrivilegedContext(cx), \
/* shell flag */ "moz-intgemm", \
/* preference name */ "moz_intgemm") \
EXPERIMENTAL(/* capitalized name */ TestSerialization, \
/* lower case name */ testSerialization, \
/* compile predicate */ 1, \
/* compiler predicate */ IonAvailable(cx), \
/* flag predicate */ true, \
/* shell flag */ "test-serialization", \
/* preference name */ "test-serialization")
#define JS_FOR_WASM_FEATURES(FEATURE) \
FEATURE( \
/* capitalized name */ ExtendedConst, \
/* lower case name */ extendedConst, \
/* stage */ WasmFeatureStage::Tentative, \
/* compile predicate */ WASM_EXTENDED_CONST_ENABLED, \
/* compiler predicate */ true, \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "extended-const", \
/* preference name */ "extended_const") \
FEATURE( \
/* capitalized name */ Exceptions, \
/* lower case name */ exceptions, \
/* stage */ WasmFeatureStage::Tentative, \
/* compile predicate */ true, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "exceptions", \
/* preference name */ "exceptions") \
FEATURE( \
/* capitalized name */ FunctionReferences, \
/* lower case name */ functionReferences, \
/* stage */ WasmFeatureStage::Experimental, \
/* compile predicate */ WASM_FUNCTION_REFERENCES_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ WasmGcFlag(cx), \
/* shell flag */ "function-references", \
/* preference name */ "function_references") \
FEATURE( \
/* capitalized name */ Gc, \
/* lower case name */ gc, \
/* stage */ WasmFeatureStage::Experimental, \
/* compile predicate */ WASM_GC_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "gc", \
/* preference name */ "gc") \
FEATURE( \
/* capitalized name */ RelaxedSimd, \
/* lower case name */ v128Relaxed, \
/* stage */ WasmFeatureStage::Tentative, \
/* compile predicate */ WASM_RELAXED_SIMD_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ js::jit::JitSupportsWasmSimd(), \
/* flag force enable */ false, \
/* shell flag */ "relaxed-simd", \
/* preference name */ "relaxed_simd") \
FEATURE( \
/* capitalized name */ Memory64, \
/* lower case name */ memory64, \
/* stage */ WasmFeatureStage::Tentative, \
/* compile predicate */ WASM_MEMORY64_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "memory64", \
/* preference name */ "memory64") \
FEATURE( \
/* capitalized name */ MemoryControl, \
/* lower case name */ memoryControl, \
/* stage */ WasmFeatureStage::Experimental, \
/* compile predicate */ WASM_MEMORY_CONTROL_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "memory-control", \
/* preference name */ "memory_control") \
FEATURE( \
/* capitalized name */ MultiMemory, \
/* lower case name */ multiMemory, \
/* stage */ WasmFeatureStage::Experimental, \
/* compile predicate */ WASM_MULTI_MEMORY_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "multi-memory", \
/* preference name */ "multi_memory") \
FEATURE( \
/* capitalized name */ MozIntGemm, \
/* lower case name */ mozIntGemm, \
/* stage */ WasmFeatureStage::Experimental, \
/* compile predicate */ WASM_MOZ_INTGEMM_ENABLED, \
/* compiler predicate */ AnyCompilerAvailable(cx), \
/* flag predicate */ IsSimdPrivilegedContext(cx), \
/* flag force enable */ false, \
/* shell flag */ "moz-intgemm", \
/* preference name */ "moz_intgemm") \
FEATURE( \
/* capitalized name */ TestSerialization, \
/* lower case name */ testSerialization, \
/* stage */ WasmFeatureStage::Experimental, \
/* compile predicate */ 1, \
/* compiler predicate */ IonAvailable(cx), \
/* flag predicate */ true, \
/* flag force enable */ false, \
/* shell flag */ "test-serialization", \
/* preference name */ "test-serialization")
// clang-format on

View File

@ -127,6 +127,7 @@
#include "vm/StringType.h"
#include "wasm/AsmJS.h"
#include "wasm/WasmBaselineCompile.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmGcObject.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmIntrinsic.h"
@ -910,7 +911,7 @@ static bool WasmThreadsEnabled(JSContext* cx, unsigned argc, Value* vp) {
args.rval().setBoolean(wasm::NAME##Available(cx)); \
return true; \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE);
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
static bool WasmSimdEnabled(JSContext* cx, unsigned argc, Value* vp) {
@ -9125,7 +9126,7 @@ gc::ZealModeHelpText),
JS_FN_HELP("wasm" #NAME "Enabled", Wasm##NAME##Enabled, 0, 0, \
"wasm" #NAME "Enabled()", \
" Returns a boolean indicating whether the WebAssembly " #NAME " proposal is enabled."),
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
JS_FN_HELP("wasmThreadsEnabled", WasmThreadsEnabled, 0, 0,

View File

@ -15,6 +15,7 @@
#include "vm/TypedArrayObject.h"
#include "wasm/WasmCompile.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmIonCompile.h"
#include "wasm/WasmJS.h"
#include "wasm/WasmTable.h"

View File

@ -1 +1 @@
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-function-references --wasm-gc; test-also=--wasm-compiler=baseline --wasm-function-references --wasm-gc; include:wasm.js
|jit-test| test-also=--wasm-compiler=optimizing; --wasm-gc; test-also=--wasm-compiler=baseline --wasm-gc; include:wasm.js

View File

@ -25,8 +25,8 @@
#include "js/experimental/JitInfo.h" // JSJitInfo
#include "util/Memory.h"
#include "wasm/WasmCodegenTypes.h"
#include "wasm/WasmFeatures.h" // for wasm::ReportSimdAnalysis
#include "wasm/WasmInstanceData.h"
#include "wasm/WasmJS.h" // for wasm::ReportSimdAnalysis
#include "jit/shared/Lowering-shared-inl.h"
#include "vm/BytecodeUtil-inl.h"

View File

@ -37,6 +37,7 @@
#include "vm/PlainObject.h" // js::PlainObject
#include "vm/Uint8Clamped.h"
#include "wasm/WasmCode.h"
#include "wasm/WasmFeatures.h" // for wasm::ReportSimdAnalysis
#include "vm/JSAtom-inl.h"
#include "wasm/WasmInstance-inl.h"

View File

@ -5,6 +5,7 @@
#include "jit/ShuffleAnalysis.h"
#include "jit/MIR.h"
#include "wasm/WasmFeatures.h"
using namespace js;
using namespace jit;

View File

@ -11,6 +11,8 @@
#include "jit/arm64/Assembler-arm64.h"
#include "jit/Lowering.h"
#include "jit/MIR.h"
#include "wasm/WasmFeatures.h" // for wasm::ReportSimdAnalysis
#include "jit/shared/Lowering-shared-inl.h"
using namespace js;

View File

@ -10,6 +10,7 @@
#include "jit/Lowering.h"
#include "jit/MIR.h"
#include "wasm/WasmFeatures.h" // for wasm::ReportSimdAnalysis
#include "jit/shared/Lowering-shared-inl.h"

View File

@ -13,7 +13,7 @@
#include "vm/ArrayBufferObject.h"
#include "vm/SharedMem.h"
#include "vm/Uint8Clamped.h"
#include "wasm/WasmJS.h"
#include "wasm/WasmFeatures.h"
using namespace js;

View File

@ -201,6 +201,7 @@
#include "vm/ToSource.h" // js::ValueToSource
#include "vm/TypedArrayObject.h"
#include "vm/WrapperObject.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmJS.h"
#include "vm/Compartment-inl.h"
@ -605,13 +606,10 @@ bool shell::enableSharedMemory = SHARED_MEMORY_DEFAULT;
bool shell::enableWasmBaseline = false;
bool shell::enableWasmOptimizing = false;
#define WASM_DEFAULT_FEATURE(NAME, ...) bool shell::enableWasm##NAME = true;
#define WASM_EXPERIMENTAL_FEATURE(NAME, ...) \
bool shell::enableWasm##NAME = false;
JS_FOR_WASM_FEATURES(WASM_DEFAULT_FEATURE, WASM_DEFAULT_FEATURE,
WASM_EXPERIMENTAL_FEATURE);
#undef WASM_DEFAULT_FEATURE
#undef WASM_EXPERIMENTAL_FEATURE
#define WASM_FEATURE(NAME, _, STAGE, ...) \
bool shell::enableWasm##NAME = STAGE != WasmFeatureStage::Experimental;
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
bool shell::enableWasmVerbose = false;
bool shell::enableTestWasmAwaitTier2 = false;
@ -10765,7 +10763,7 @@ static void SetWorkerContextOptions(JSContext* cx) {
.setWasmBaseline(enableWasmBaseline)
.setWasmIon(enableWasmOptimizing)
#define WASM_FEATURE(NAME, ...) .setWasm##NAME(enableWasm##NAME)
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
.setWasmVerbose(enableWasmVerbose)
@ -11499,24 +11497,18 @@ bool InitOptionParser(OptionParser& op) {
!op.addBoolOption('\0', "test-wasm-await-tier2",
"Forcibly activate tiering and block "
"instantiation on completion of tier2") ||
#define WASM_DEFAULT_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, SHELL, ...) \
!op.addBoolOption('\0', "no-wasm-" SHELL, "Disable wasm " SHELL "feature.") ||
#define WASM_TENTATIVE_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, SHELL, ...) \
!op.addBoolOption('\0', "no-wasm-" SHELL, \
"Disable wasm " SHELL "feature.") || \
!op.addBoolOption('\0', "wasm-" SHELL, "No-op.") ||
#define WASM_EXPERIMENTAL_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, \
COMPILER_PRED, FLAG_PRED, SHELL, ...) \
!op.addBoolOption('\0', "wasm-" SHELL, \
"Enable experimental wasm " SHELL "feature.") || \
!op.addBoolOption('\0', "no-wasm-" SHELL, "No-op.") ||
JS_FOR_WASM_FEATURES(WASM_DEFAULT_FEATURE, WASM_TENTATIVE_FEATURE,
WASM_EXPERIMENTAL_FEATURE)
#undef WASM_DEFAULT_FEATURE
#undef WASM_TENTATIVE_FEATURE
#undef WASM_EXPERIMENTAL_FEATURE
#define WASM_FEATURE(NAME, LOWER_NAME, STAGE, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, FLAG_FORCE_ON, SHELL, ...) \
!op.addBoolOption('\0', "no-wasm-" SHELL, \
STAGE == WasmFeatureStage::Experimental \
? "No-op." \
: "Disable wasm " SHELL "feature.") || \
!op.addBoolOption('\0', "wasm-" SHELL, \
STAGE == WasmFeatureStage::Experimental \
? "Enable wasm " SHELL "feature." \
: "No-op.") ||
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
!op.addBoolOption('\0', "no-native-regexp",
"Disable native regexp compilation") ||
!op.addIntOption(
@ -12176,16 +12168,13 @@ bool SetContextWasmOptions(JSContext* cx, const OptionParser& op) {
}
}
#define WASM_DEFAULT_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, SHELL, ...) \
enableWasm##NAME = !op.getBoolOption("no-wasm-" SHELL);
#define WASM_EXPERIMENTAL_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, \
COMPILER_PRED, FLAG_PRED, SHELL, ...) \
enableWasm##NAME = op.getBoolOption("wasm-" SHELL);
JS_FOR_WASM_FEATURES(WASM_DEFAULT_FEATURE, WASM_DEFAULT_FEATURE,
WASM_EXPERIMENTAL_FEATURE);
#undef WASM_DEFAULT_FEATURE
#undef WASM_EXPERIMENTAL_FEATURE
#define WASM_FEATURE(NAME, LOWER_NAME, STAGE, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, FLAG_FORCE_ON, SHELL, ...) \
enableWasm##NAME = op.getBoolOption(stage == WasmFeatureStage::Experimental \
? "wasm-" SHELL \
: "no-wasm-" SHELL); \
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
enableWasmVerbose = op.getBoolOption("wasm-verbose");
enableTestWasmAwaitTier2 = op.getBoolOption("test-wasm-await-tier2");
@ -12197,7 +12186,7 @@ bool SetContextWasmOptions(JSContext* cx, const OptionParser& op) {
.setWasmBaseline(enableWasmBaseline)
.setWasmIon(enableWasmOptimizing)
#define WASM_FEATURE(NAME, ...) .setWasm##NAME(enableWasm##NAME)
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
;
@ -12218,16 +12207,12 @@ bool SetContextWasmOptions(JSContext* cx, const OptionParser& op) {
// Also the following are to be propagated.
const char* to_propagate[] = {
# define WASM_DEFAULT_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, SHELL, ...) \
"--no-wasm-" SHELL,
# define WASM_EXPERIMENTAL_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, \
COMPILER_PRED, FLAG_PRED, SHELL, ...) \
"--wasm-" SHELL,
JS_FOR_WASM_FEATURES(WASM_DEFAULT_FEATURE, WASM_DEFAULT_FEATURE,
WASM_EXPERIMENTAL_FEATURE)
# undef WASM_DEFAULT_FEATURE
# undef WASM_EXPERIMENTAL_FEATURE
# define WASM_FEATURE(NAME, LOWER_NAME, STAGE, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, FLAG_FORCE_ON, SHELL, ...) \
STAGE == WasmFeatureStage::Experimental ? "--wasm-" SHELL \
: "--no-wasm-" SHELL,
JS_FOR_WASM_FEATURES(WASM_FEATURE)
# undef WASM_FEATURE
// Compiler selection options
"--test-wasm-await-tier2",
NULL};

View File

@ -114,7 +114,7 @@ extern bool enableWasmBaseline;
extern bool enableWasmOptimizing;
#define WASM_FEATURE(NAME, ...) extern bool enableWasm##NAME;
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE);
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
extern bool enableWasmVerbose;

View File

@ -68,6 +68,7 @@
#include "vm/RegExpStatics.h"
#include "vm/SelfHosting.h"
#include "vm/StringObject.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmJS.h"
#ifdef ENABLE_RECORD_TUPLE
# include "vm/RecordType.h"

View File

@ -64,6 +64,7 @@
#include "vm/TypedArrayObject.h"
#include "vm/Warnings.h" // js::WarnNumberASCII
#include "wasm/WasmCompile.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmGenerator.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmIonCompile.h"

View File

@ -31,6 +31,7 @@
#include "vm/HelperThreads.h"
#include "vm/Realm.h"
#include "wasm/WasmBaselineCompile.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmGenerator.h"
#include "wasm/WasmIonCompile.h"
#include "wasm/WasmOpIter.h"
@ -90,7 +91,7 @@ FeatureArgs FeatureArgs::build(JSContext* cx, const FeatureOptions& options) {
#define WASM_FEATURE(NAME, LOWER_NAME, ...) \
features.LOWER_NAME = wasm::NAME##Available(cx);
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE);
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
features.sharedMemory =

View File

@ -85,7 +85,7 @@ struct FeatureArgs {
FeatureArgs()
:
#define WASM_FEATURE(NAME, LOWER_NAME, ...) LOWER_NAME(false),
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
sharedMemory(Shareable::False),
simd(false),
@ -98,7 +98,7 @@ struct FeatureArgs {
static FeatureArgs build(JSContext* cx, const FeatureOptions& options);
#define WASM_FEATURE(NAME, LOWER_NAME, ...) bool LOWER_NAME;
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
Shareable sharedMemory;

View File

@ -0,0 +1,319 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
*
* Copyright 2016 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "wasm/WasmFeatures.h"
#include "jit/AtomicOperations.h"
#include "jit/JitContext.h"
#include "jit/JitOptions.h"
#include "util/StringBuffer.h"
#include "vm/JSContext.h"
#include "vm/Realm.h"
#include "vm/StringType.h"
#include "wasm/WasmBaselineCompile.h"
#include "wasm/WasmIonCompile.h"
#include "wasm/WasmSignalHandlers.h"
using namespace js;
using namespace js::wasm;
using namespace js::jit;
// About the fuzzer intercession points: If fuzzing has been selected and only a
// single compiler has been selected then we will disable features that are not
// supported by that single compiler. This is strictly a concession to the
// fuzzer infrastructure.
static inline bool IsFuzzingIon(JSContext* cx) {
return IsFuzzing() && !cx->options().wasmBaseline() &&
cx->options().wasmIon();
}
// These functions read flags and apply fuzzing intercession policies. Never go
// directly to the flags in code below, always go via these accessors.
static inline bool WasmThreadsFlag(JSContext* cx) {
return cx->realm() &&
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
}
#define WASM_FEATURE(NAME, ...) \
static inline bool Wasm##NAME##Flag(JSContext* cx);
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
#define WASM_FEATURE(NAME, LOWER_NAME, STAGE, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, FLAG_FORCE_ON, ...) \
static inline bool Wasm##NAME##Flag(JSContext* cx) { \
if (!(COMPILE_PRED)) { \
return false; \
} \
return ((FLAG_PRED) && cx->options().wasm##NAME()) || (FLAG_FORCE_ON); \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE);
#undef WASM_FEATURE
static inline bool WasmDebuggerActive(JSContext* cx) {
if (IsFuzzingIon(cx)) {
return false;
}
return cx->realm() && cx->realm()->debuggerObservesWasm();
}
/*
* [SMDOC] Compiler and feature selection; compiler and feature availability.
*
* In order to make the computation of whether a wasm feature or wasm compiler
* is available predictable, we have established some rules, and implemented
* those rules.
*
* Code elsewhere should use the predicates below to test for features and
* compilers, it should never try to compute feature and compiler availability
* in other ways.
*
* At the outset, there is a set of selected compilers C containing at most one
* baseline compiler [*] and at most one optimizing compiler [**], and a set of
* selected features F. These selections come from defaults and from overrides
* by command line switches in the shell and javascript.option.wasm_X in the
* browser. Defaults for both features and compilers may be platform specific,
* for example, some compilers may not be available on some platforms because
* they do not support the architecture at all or they do not support features
* that must be enabled by default on the platform.
*
* [*] Currently we have only one, "baseline" aka "Rabaldr", but other
* implementations have additional baseline translators, eg from wasm
* bytecode to an internal code processed by an interpreter.
*
* [**] Currently we have only one, "ion" aka "Baldr".
*
*
* Compiler availability:
*
* The set of features F induces a set of available compilers A: these are the
* compilers that all support all the features in F. (Some of these compilers
* may not be in the set C.)
*
* The sets C and A are intersected, yielding a set of enabled compilers E.
* Notably, the set E may be empty, in which case wasm is effectively disabled
* (though the WebAssembly object is still present in the global environment).
*
* An important consequence is that selecting a feature that is not supported by
* a particular compiler disables that compiler completely -- there is no notion
* of a compiler being available but suddenly failing when an unsupported
* feature is used by a program. If a compiler is available, it supports all
* the features that have been selected.
*
* Equally important, a feature cannot be enabled by default on a platform if
* the feature is not supported by all the compilers we wish to have enabled by
* default on the platform. We MUST by-default disable features on a platform
* that are not supported by all the compilers on the platform.
*
* In a shell build, the testing functions wasmCompilersPresent,
* wasmCompileMode, and wasmIonDisabledByFeatures can be used to probe compiler
* availability and the reasons for a compiler being unavailable.
*
*
* Feature availability:
*
* A feature is available if it is selected and there is at least one available
* compiler that implements it.
*
* For example, --wasm-gc selects the GC feature, and if Baseline is available
* then the feature is available.
*
* In a shell build, there are per-feature testing functions (of the form
* wasmFeatureEnabled) to probe whether specific features are available.
*/
// 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.
bool wasm::BaselineAvailable(JSContext* cx) {
if (!cx->options().wasmBaseline() || !BaselinePlatformSupport()) {
return false;
}
bool isDisabled = false;
MOZ_ALWAYS_TRUE(BaselineDisabledByFeatures(cx, &isDisabled));
return !isDisabled;
}
bool wasm::IonAvailable(JSContext* cx) {
if (!cx->options().wasmIon() || !IonPlatformSupport()) {
return false;
}
bool isDisabled = false;
MOZ_ALWAYS_TRUE(IonDisabledByFeatures(cx, &isDisabled));
return !isDisabled;
}
bool wasm::WasmCompilerForAsmJSAvailable(JSContext* cx) {
return IonAvailable(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::BaselineDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason) {
// Baseline cannot be used if we are testing serialization.
bool testSerialization = WasmTestSerializationFlag(cx);
if (reason) {
char sep = 0;
if (testSerialization && !Append(reason, "testSerialization", &sep)) {
return false;
}
}
*isDisabled = testSerialization;
return true;
}
bool wasm::IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason) {
// Ion has no debugging support.
bool debug = WasmDebuggerActive(cx);
if (reason) {
char sep = 0;
if (debug && !Append(reason, "debug", &sep)) {
return false;
}
}
*isDisabled = debug;
return true;
}
bool wasm::AnyCompilerAvailable(JSContext* cx) {
return wasm::BaselineAvailable(cx) || wasm::IonAvailable(cx);
}
// 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.
#define WASM_FEATURE(NAME, LOWER_NAME, STAGE, COMPILE_PRED, COMPILER_PRED, \
...) \
bool wasm::NAME##Available(JSContext* cx) { \
return Wasm##NAME##Flag(cx) && (COMPILER_PRED); \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
bool wasm::IsSimdPrivilegedContext(JSContext* cx) {
// This may be slightly more lenient than we want in an ideal world, but it
// remains safe.
return cx->realm() && cx->realm()->principals() &&
cx->realm()->principals()->isSystemOrAddonPrincipal();
}
bool wasm::SimdAvailable(JSContext* cx) {
return js::jit::JitSupportsWasmSimd();
}
bool wasm::ThreadsAvailable(JSContext* cx) {
return WasmThreadsFlag(cx) && AnyCompilerAvailable(cx);
}
bool wasm::HasPlatformSupport(JSContext* cx) {
#if !MOZ_LITTLE_ENDIAN()
return false;
#else
if (!HasJitBackend()) {
return false;
}
if (gc::SystemPageSize() > wasm::PageSize) {
return false;
}
if (!JitOptions.supportsUnalignedAccesses) {
return false;
}
# ifndef __wasi__
// WASI doesn't support signals so we don't have this function.
if (!wasm::EnsureFullSignalHandlers(cx)) {
return false;
}
# endif
if (!jit::JitSupportsAtomics()) {
return false;
}
// Wasm threads require 8-byte lock-free atomics.
if (!jit::AtomicOperations::isLockfree8()) {
return false;
}
// Test only whether the compilers are supported on the hardware, not whether
// they are enabled.
return BaselinePlatformSupport() || IonPlatformSupport();
#endif
}
bool wasm::HasSupport(JSContext* cx) {
// If the general wasm pref is on, it's on for everything.
bool prefEnabled = cx->options().wasm();
// If the general pref is off, check trusted principals.
if (MOZ_UNLIKELY(!prefEnabled)) {
prefEnabled = cx->options().wasmForTrustedPrinciples() && cx->realm() &&
cx->realm()->principals() &&
cx->realm()->principals()->isSystemOrAddonPrincipal();
}
// Do not check for compiler availability, as that may be run-time variant.
// For HasSupport() we want a stable answer depending only on prefs.
return prefEnabled && HasPlatformSupport(cx);
}
bool wasm::StreamingCompilationAvailable(JSContext* cx) {
// This should match EnsureStreamSupport().
return HasSupport(cx) && AnyCompilerAvailable(cx) &&
cx->runtime()->offThreadPromiseState.ref().initialized() &&
CanUseExtraThreads() && cx->runtime()->consumeStreamCallback &&
cx->runtime()->reportStreamErrorCallback;
}
bool wasm::CodeCachingAvailable(JSContext* cx) {
// Fuzzilli breaks the out-of-process compilation mechanism,
// so we disable it permanently in those builds.
#ifdef FUZZING_JS_FUZZILLI
return false;
#else
// 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);
#endif
}

115
js/src/wasm/WasmFeatures.h Normal file
View File

@ -0,0 +1,115 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_wasm_WasmFeatures_h
#define js_wasm_WasmFeatures_h
#include "js/WasmFeatures.h"
#include "js/TypeDecls.h"
namespace js {
class JSStringBuilder;
namespace wasm {
// 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 HasPlatformSupport(JSContext* cx);
// Return whether WebAssembly is supported on this platform. This determines
// whether the WebAssembly object is exposed to JS in this context / realm and
//
// It does *not* guarantee that a compiler is actually available; that has to be
// checked separately, as it is sometimes run-time variant, depending on whether
// a debugger has been created or not.
bool HasSupport(JSContext* cx);
// 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 BaselineAvailable(JSContext* cx);
bool IonAvailable(JSContext* cx);
// Test all three.
bool AnyCompilerAvailable(JSContext* cx);
// Asm.JS is translated to wasm and then compiled using the wasm optimizing
// compiler; test whether this compiler is available.
bool WasmCompilerForAsmJSAvailable(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`.
bool BaselineDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason = nullptr);
bool IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason = nullptr);
// 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.
// Streaming compilation.
bool StreamingCompilationAvailable(JSContext* cx);
// Caching of optimized code. Implies both streaming compilation and an
// optimizing compiler tier.
bool CodeCachingAvailable(JSContext* cx);
// Shared memory and atomics.
bool ThreadsAvailable(JSContext* cx);
#define WASM_FEATURE(NAME, ...) bool NAME##Available(JSContext* cx);
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
// SIMD operations.
bool SimdAvailable(JSContext* cx);
// Privileged content that can access experimental intrinsics
bool IsSimdPrivilegedContext(JSContext* cx);
#if defined(ENABLE_WASM_SIMD) && defined(DEBUG)
// Report the result of a Simd simplification to the testing infrastructure.
void ReportSimdAnalysis(const char* data);
#endif
// Returns true if WebAssembly as configured by compile-time flags and run-time
// options can support try/catch, throw, rethrow, and branch_on_exn (evolving).
bool ExceptionsAvailable(JSContext* cx);
} // namespace wasm
} // namespace js
#endif // js_wasm_WasmFeatures_h

View File

@ -21,6 +21,7 @@
#include "util/Text.h"
#include "vm/GlobalObject.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmGenerator.h"
#include "wasm/WasmIntrinsicGenerated.h"
#include "wasm/WasmJS.h"

View File

@ -62,6 +62,7 @@
#include "wasm/WasmBuiltins.h"
#include "wasm/WasmCompile.h"
#include "wasm/WasmDebug.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmIntrinsic.h"
#include "wasm/WasmIonCompile.h"
@ -102,283 +103,6 @@ using mozilla::Nothing;
using mozilla::RangedPtr;
using mozilla::Span;
// About the fuzzer intercession points: If fuzzing has been selected and only a
// single compiler has been selected then we will disable features that are not
// supported by that single compiler. This is strictly a concession to the
// fuzzer infrastructure.
static inline bool IsFuzzingIon(JSContext* cx) {
return IsFuzzing() && !cx->options().wasmBaseline() &&
cx->options().wasmIon();
}
// These functions read flags and apply fuzzing intercession policies. Never go
// directly to the flags in code below, always go via these accessors.
static inline bool WasmThreadsFlag(JSContext* cx) {
return cx->realm() &&
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
}
#define WASM_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, FLAG_PRED, \
...) \
static inline bool Wasm##NAME##Flag(JSContext* cx) { \
return (COMPILE_PRED) && (FLAG_PRED) && cx->options().wasm##NAME(); \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE);
#undef WASM_FEATURE
static inline bool WasmDebuggerActive(JSContext* cx) {
if (IsFuzzingIon(cx)) {
return false;
}
return cx->realm() && cx->realm()->debuggerObservesWasm();
}
/*
* [SMDOC] Compiler and feature selection; compiler and feature availability.
*
* In order to make the computation of whether a wasm feature or wasm compiler
* is available predictable, we have established some rules, and implemented
* those rules.
*
* Code elsewhere should use the predicates below to test for features and
* compilers, it should never try to compute feature and compiler availability
* in other ways.
*
* At the outset, there is a set of selected compilers C containing at most one
* baseline compiler [*] and at most one optimizing compiler [**], and a set of
* selected features F. These selections come from defaults and from overrides
* by command line switches in the shell and javascript.option.wasm_X in the
* browser. Defaults for both features and compilers may be platform specific,
* for example, some compilers may not be available on some platforms because
* they do not support the architecture at all or they do not support features
* that must be enabled by default on the platform.
*
* [*] Currently we have only one, "baseline" aka "Rabaldr", but other
* implementations have additional baseline translators, eg from wasm
* bytecode to an internal code processed by an interpreter.
*
* [**] Currently we have only one, "ion" aka "Baldr".
*
*
* Compiler availability:
*
* The set of features F induces a set of available compilers A: these are the
* compilers that all support all the features in F. (Some of these compilers
* may not be in the set C.)
*
* The sets C and A are intersected, yielding a set of enabled compilers E.
* Notably, the set E may be empty, in which case wasm is effectively disabled
* (though the WebAssembly object is still present in the global environment).
*
* An important consequence is that selecting a feature that is not supported by
* a particular compiler disables that compiler completely -- there is no notion
* of a compiler being available but suddenly failing when an unsupported
* feature is used by a program. If a compiler is available, it supports all
* the features that have been selected.
*
* Equally important, a feature cannot be enabled by default on a platform if
* the feature is not supported by all the compilers we wish to have enabled by
* default on the platform. We MUST by-default disable features on a platform
* that are not supported by all the compilers on the platform.
*
* In a shell build, the testing functions wasmCompilersPresent,
* wasmCompileMode, and wasmIonDisabledByFeatures can be used to probe compiler
* availability and the reasons for a compiler being unavailable.
*
*
* Feature availability:
*
* A feature is available if it is selected and there is at least one available
* compiler that implements it.
*
* For example, --wasm-gc selects the GC feature, and if Baseline is available
* then the feature is available.
*
* In a shell build, there are per-feature testing functions (of the form
* wasmFeatureEnabled) to probe whether specific features are available.
*/
// 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.
bool wasm::BaselineAvailable(JSContext* cx) {
if (!cx->options().wasmBaseline() || !BaselinePlatformSupport()) {
return false;
}
bool isDisabled = false;
MOZ_ALWAYS_TRUE(BaselineDisabledByFeatures(cx, &isDisabled));
return !isDisabled;
}
bool wasm::IonAvailable(JSContext* cx) {
if (!cx->options().wasmIon() || !IonPlatformSupport()) {
return false;
}
bool isDisabled = false;
MOZ_ALWAYS_TRUE(IonDisabledByFeatures(cx, &isDisabled));
return !isDisabled;
}
bool wasm::WasmCompilerForAsmJSAvailable(JSContext* cx) {
return IonAvailable(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::BaselineDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason) {
// Baseline cannot be used if we are testing serialization.
bool testSerialization = WasmTestSerializationFlag(cx);
if (reason) {
char sep = 0;
if (testSerialization && !Append(reason, "testSerialization", &sep)) {
return false;
}
}
*isDisabled = testSerialization;
return true;
}
bool wasm::IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason) {
// Ion has no debugging support.
bool debug = WasmDebuggerActive(cx);
if (reason) {
char sep = 0;
if (debug && !Append(reason, "debug", &sep)) {
return false;
}
}
*isDisabled = debug;
return true;
}
bool wasm::AnyCompilerAvailable(JSContext* cx) {
return wasm::BaselineAvailable(cx) || wasm::IonAvailable(cx);
}
// 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.
#define WASM_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, FLAG_PRED, \
...) \
bool wasm::NAME##Available(JSContext* cx) { \
return Wasm##NAME##Flag(cx) && (COMPILER_PRED); \
}
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
#undef WASM_FEATURE
bool wasm::IsSimdPrivilegedContext(JSContext* cx) {
// This may be slightly more lenient than we want in an ideal world, but it
// remains safe.
return cx->realm() && cx->realm()->principals() &&
cx->realm()->principals()->isSystemOrAddonPrincipal();
}
bool wasm::SimdAvailable(JSContext* cx) {
return js::jit::JitSupportsWasmSimd();
}
bool wasm::ThreadsAvailable(JSContext* cx) {
return WasmThreadsFlag(cx) && AnyCompilerAvailable(cx);
}
bool wasm::HasPlatformSupport(JSContext* cx) {
#if !MOZ_LITTLE_ENDIAN()
return false;
#else
if (!HasJitBackend()) {
return false;
}
if (gc::SystemPageSize() > wasm::PageSize) {
return false;
}
if (!JitOptions.supportsUnalignedAccesses) {
return false;
}
# ifndef __wasi__
// WASI doesn't support signals so we don't have this function.
if (!wasm::EnsureFullSignalHandlers(cx)) {
return false;
}
# endif
if (!jit::JitSupportsAtomics()) {
return false;
}
// Wasm threads require 8-byte lock-free atomics.
if (!jit::AtomicOperations::isLockfree8()) {
return false;
}
// Test only whether the compilers are supported on the hardware, not whether
// they are enabled.
return BaselinePlatformSupport() || IonPlatformSupport();
#endif
}
bool wasm::HasSupport(JSContext* cx) {
// If the general wasm pref is on, it's on for everything.
bool prefEnabled = cx->options().wasm();
// If the general pref is off, check trusted principals.
if (MOZ_UNLIKELY(!prefEnabled)) {
prefEnabled = cx->options().wasmForTrustedPrinciples() && cx->realm() &&
cx->realm()->principals() &&
cx->realm()->principals()->isSystemOrAddonPrincipal();
}
// Do not check for compiler availability, as that may be run-time variant.
// For HasSupport() we want a stable answer depending only on prefs.
return prefEnabled && HasPlatformSupport(cx);
}
bool wasm::StreamingCompilationAvailable(JSContext* cx) {
// This should match EnsureStreamSupport().
return HasSupport(cx) && AnyCompilerAvailable(cx) &&
cx->runtime()->offThreadPromiseState.ref().initialized() &&
CanUseExtraThreads() && cx->runtime()->consumeStreamCallback &&
cx->runtime()->reportStreamErrorCallback;
}
bool wasm::CodeCachingAvailable(JSContext* cx) {
// Fuzzilli breaks the out-of-process compilation mechanism,
// so we disable it permanently in those builds.
#ifdef FUZZING_JS_FUZZILLI
return false;
#else
// 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);
#endif
}
// ============================================================================
// Imports

View File

@ -71,99 +71,6 @@ namespace wasm {
struct ImportValues;
// 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 HasPlatformSupport(JSContext* cx);
// Return whether WebAssembly is supported on this platform. This determines
// whether the WebAssembly object is exposed to JS in this context / realm and
//
// It does *not* guarantee that a compiler is actually available; that has to be
// checked separately, as it is sometimes run-time variant, depending on whether
// a debugger has been created or not.
bool HasSupport(JSContext* cx);
// 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 BaselineAvailable(JSContext* cx);
bool IonAvailable(JSContext* cx);
// Test all three.
bool AnyCompilerAvailable(JSContext* cx);
// Asm.JS is translated to wasm and then compiled using the wasm optimizing
// compiler; test whether this compiler is available.
bool WasmCompilerForAsmJSAvailable(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`.
bool BaselineDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason = nullptr);
bool IonDisabledByFeatures(JSContext* cx, bool* isDisabled,
JSStringBuilder* reason = nullptr);
// 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.
// Streaming compilation.
bool StreamingCompilationAvailable(JSContext* cx);
// Caching of optimized code. Implies both streaming compilation and an
// optimizing compiler tier.
bool CodeCachingAvailable(JSContext* cx);
// Shared memory and atomics.
bool ThreadsAvailable(JSContext* cx);
#define WASM_FEATURE(NAME, ...) bool NAME##Available(JSContext* cx);
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
#undef WASM_FEATURE
// SIMD operations.
bool SimdAvailable(JSContext* cx);
// Privileged content that can access experimental intrinsics
bool IsSimdPrivilegedContext(JSContext* cx);
#if defined(ENABLE_WASM_SIMD) && defined(DEBUG)
// Report the result of a Simd simplification to the testing infrastructure.
void ReportSimdAnalysis(const char* data);
#endif
// Returns true if WebAssembly as configured by compile-time flags and run-time
// options can support try/catch, throw, rethrow, and branch_on_exn (evolving).
bool ExceptionsAvailable(JSContext* cx);
// Compiles the given binary wasm module given the ArrayBufferObject
// and links the module's imports with the given import object.

View File

@ -27,6 +27,7 @@
#include "vm/JSAtom.h"
#include "vm/JSObject.h"
#include "vm/StringType.h"
#include "wasm/WasmFeatures.h"
#include "wasm/WasmJS.h"
#include "vm/JSAtom-inl.h"

View File

@ -120,7 +120,7 @@ struct ModuleEnvironment {
#define WASM_FEATURE(NAME, SHORT_NAME, ...) \
bool SHORT_NAME##Enabled() const { return features.SHORT_NAME; }
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
Shareable sharedMemoryEnabled() const { return features.sharedMemory; }
bool simdAvailable() const { return features.simd; }

View File

@ -24,6 +24,7 @@ UNIFIED_SOURCES += [
"WasmCompile.cpp",
"WasmDebug.cpp",
"WasmDebugFrame.cpp",
"WasmFeatures.cpp",
"WasmFrameIter.cpp",
"WasmGC.cpp",
"WasmGcObject.cpp",

View File

@ -836,10 +836,10 @@ void xpc::SetPrefableContextOptions(JS::ContextOptions& options) {
.setWasmIon(Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_optimizingjit"))
.setWasmBaseline(
Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_baselinejit"))
#define WASM_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, FLAG_PRED, \
SHELL, PREF) \
#define WASM_FEATURE(NAME, LOWER_NAME, STAGE, COMPILE_PRED, COMPILER_PRED, \
FLAG_PRED, FLAG_FORCE_ON, SHELL, PREF) \
.setWasm##NAME(Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_" PREF))
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
JS_FOR_WASM_FEATURES(WASM_FEATURE)
#undef WASM_FEATURE
.setWasmVerbose(Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_verbose"))
.setThrowOnAsmJSValidationFailure(Preferences::GetBool(