Bug 1669428 - Properly control experimental SIMD instructions. r=jseward

This gets rid of an ad-hoc boolean constant and introduces a configuration flag
for experimental SIMD instructions.  The flag is on by default in Nightly if
SIMD is also enabled; otherwise off.  This patch therefore disables support for
experimental SIMD instructions in beta and release, where they have been
available with the other SIMD instructions behind a pref.  This seems OK:
code using unstable bits of an in-progress proposal should stick to Nightly.

Differential Revision: https://phabricator.services.mozilla.com/D92554
This commit is contained in:
Lars T Hansen 2020-10-06 12:10:56 +00:00
parent 17bba3d008
commit 907323e1fd
7 changed files with 82 additions and 52 deletions

View File

@ -681,6 +681,29 @@ def wasm_simd(value, jit_enabled, simulator, target):
set_config('ENABLE_WASM_SIMD', wasm_simd)
set_define('ENABLE_WASM_SIMD', wasm_simd)
# Experimental SIMD opcodes are Nightly-only by default
@depends(milestone.is_nightly, '--enable-wasm-simd')
def default_wasm_simd_experimental(is_nightly, wasm_simd):
if is_nightly and wasm_simd:
return True
js_option('--enable-wasm-simd-experimental',
default=default_wasm_simd_experimental,
help='{Enable|Disable} WebAssembly SIMD experimental opcodes')
@depends('--enable-wasm-simd-experimental', '--enable-wasm-simd')
def wasm_simd_experimental(value, wasm_simd):
if not value:
return
if wasm_simd:
return True
die('--enable-wasm-simd-experimental only possible with --enable-wasm-simd')
set_config('ENABLE_WASM_SIMD_EXPERIMENTAL', wasm_simd_experimental)
set_define('ENABLE_WASM_SIMD_EXPERIMENTAL', wasm_simd_experimental)
# Options for generating the shell as a script
# ============================================

View File

@ -874,6 +874,17 @@ static bool WasmSimdEnabled(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
static bool WasmSimdExperimentalEnabled(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
#ifdef ENABLE_WASM_SIMD_EXPERIMENTAL
args.rval().setBoolean(wasm::SimdAvailable(cx));
#else
args.rval().setBoolean(false);
#endif
return true;
}
static bool WasmCompilersPresent(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
@ -4988,7 +4999,6 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
return false;
}
/* Instantiate the stencil. */
frontend::CompilationGCOutput output(cx);
if (!compilationInfos.get().instantiateStencils(cx, output)) {
@ -6792,6 +6802,11 @@ gc::ZealModeHelpText),
" Returns a boolean indicating whether WebAssembly SIMD is supported by the\n"
" compilers and runtime."),
JS_FN_HELP("wasmSimdExperimentalEnabled", WasmSimdExperimentalEnabled, 0, 0,
"wasmSimdExperimentalEnabled()",
" Returns a boolean indicating whether WebAssembly SIMD experimental instructions\n"
" are supported by the compilers and runtime."),
JS_FN_HELP("wasmReftypesEnabled", WasmReftypesEnabled, 1, 0,
"wasmReftypesEnabled()",
" Returns a boolean indicating whether the WebAssembly reftypes proposal is enabled."),

View File

@ -1,15 +1,9 @@
// |jit-test| skip-if: !wasmSimdEnabled()
// |jit-test| skip-if: !wasmSimdExperimentalEnabled()
// Experimental opcodes. We have no text parsing support for these yet. The
// tests will be cleaned up and moved into ad-hack.js if the opcodes are
// adopted.
// When simd is enabled by default in release builds we will flip the value of
// SimdExperimentalEnabled to false in RELEASE_OR_BETA builds. At that point,
// these tests will start failing in release or beta builds, and a guard
// asserting !RELEASE_OR_BETA will have to be added above. That is how it
// should be.
load(libdir + "wasm-binary.js");
function wasmEval(bytes, imports) {

View File

@ -13996,10 +13996,11 @@ bool BaseCompiler::emitBody() {
} while (0)
#endif
#define CHECK_EXPERIMENTAL_SIMD() \
if (!SimdExperimentalEnabled) { \
break; \
}
#ifdef ENABLE_WASM_SIMD_EXPERIMENTAL
# define CHECK_SIMD_EXPERIMENTAL() (void)(0)
#else
# define CHECK_SIMD_EXPERIMENTAL() break
#endif
#define CHECK(E) \
if (!(E)) return false
@ -14962,19 +14963,19 @@ bool BaseCompiler::emitBody() {
case uint32_t(SimdOp::V8x16Swizzle):
CHECK_NEXT(dispatchVectorBinary(Swizzle));
case uint32_t(SimdOp::F32x4PMaxExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorBinary(PMaxF32x4));
case uint32_t(SimdOp::F32x4PMinExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorBinary(PMinF32x4));
case uint32_t(SimdOp::F64x2PMaxExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorBinary(PMaxF64x2));
case uint32_t(SimdOp::F64x2PMinExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorBinary(PMinF64x2));
case uint32_t(SimdOp::I32x4DotSI16x8Experimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorBinary(DotI16x8));
case uint32_t(SimdOp::I8x16Neg):
CHECK_NEXT(dispatchVectorUnary(NegI8x16));
@ -15029,28 +15030,28 @@ bool BaseCompiler::emitBody() {
case uint32_t(SimdOp::I32x4Abs):
CHECK_NEXT(dispatchVectorUnary(AbsI32x4));
case uint32_t(SimdOp::F32x4CeilExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(CeilF32x4));
case uint32_t(SimdOp::F32x4FloorExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(FloorF32x4));
case uint32_t(SimdOp::F32x4TruncExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(TruncF32x4));
case uint32_t(SimdOp::F32x4NearestExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(NearestF32x4));
case uint32_t(SimdOp::F64x2CeilExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(CeilF64x2));
case uint32_t(SimdOp::F64x2FloorExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(FloorF64x2));
case uint32_t(SimdOp::F64x2TruncExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(TruncF64x2));
case uint32_t(SimdOp::F64x2NearestExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(dispatchVectorUnary(NearestF64x2));
case uint32_t(SimdOp::I8x16Shl):
CHECK_NEXT(dispatchVectorVariableShift(ShiftLeftI8x16));
@ -15111,10 +15112,10 @@ bool BaseCompiler::emitBody() {
case uint32_t(SimdOp::I64x2LoadU32x2):
CHECK_NEXT(emitLoadExtend(Scalar::Uint32));
case uint32_t(SimdOp::V128Load32ZeroExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(emitLoadZero(Scalar::Float32));
case uint32_t(SimdOp::V128Load64ZeroExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK_NEXT(emitLoadZero(Scalar::Float64));
case uint32_t(SimdOp::V128Store):
CHECK_NEXT(emitStore(ValType::V128, Scalar::Simd128));
@ -15420,7 +15421,7 @@ bool BaseCompiler::emitBody() {
#undef NEXT
#undef CHECK_NEXT
#undef CHECK_POINTER_COUNT
#undef CHECK_EXPERIMENTAL_SIMD
#undef CHECK_SIMD_EXPERIMENTAL
#undef dispatchBinary
#undef dispatchUnary
#undef dispatchComparison

View File

@ -424,11 +424,6 @@ enum class GcOp {
// Opcodes with suffix 'Experimental' are proposed but not standardized, and are
// compatible with those same opcodes in V8. No opcode labeled 'Experimental'
// will ship in a Release build where SIMD is enabled by default.
//
// Once SIMD ships default-on in release builds, the following flag must be set
// to false for RELEASE_OR_BETA.
static constexpr bool SimdExperimentalEnabled = true;
enum class SimdOp {
V128Load = 0x00,

View File

@ -4307,10 +4307,11 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
if (!(c)) return false; \
break
#define CHECK_EXPERIMENTAL_SIMD() \
if (!SimdExperimentalEnabled) { \
return f.iter().unrecognizedOpcode(&op); \
}
#ifdef ENABLE_WASM_SIMD_EXPERIMENTAL
# define CHECK_SIMD_EXPERIMENTAL() (void)(0)
#else
# define CHECK_SIMD_EXPERIMENTAL() return f.iter().unrecognizedOpcode(&op)
#endif
while (true) {
if (!f.mirGen().ensureBallast()) {
@ -4844,7 +4845,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
case uint32_t(SimdOp::F64x2Ne):
CHECK(EmitBinarySimd128(f, /* commutative= */ true, SimdOp(op.b1)));
case uint32_t(SimdOp::I32x4DotSI16x8Experimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(EmitBinarySimd128(f, /* commutative= */ true, SimdOp(op.b1)));
case uint32_t(SimdOp::V128AndNot):
case uint32_t(SimdOp::I8x16Sub):
@ -4902,7 +4903,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
case uint32_t(SimdOp::F32x4PMinExperimental):
case uint32_t(SimdOp::F64x2PMaxExperimental):
case uint32_t(SimdOp::F64x2PMinExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(
EmitBinarySimd128(f, /* commutative= */ false, SimdOp(op.b1)));
case uint32_t(SimdOp::I8x16Splat):
@ -4950,7 +4951,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
case uint32_t(SimdOp::F64x2FloorExperimental):
case uint32_t(SimdOp::F64x2TruncExperimental):
case uint32_t(SimdOp::F64x2NearestExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(EmitUnarySimd128(f, SimdOp(op.b1)));
case uint32_t(SimdOp::I8x16AnyTrue):
case uint32_t(SimdOp::I16x8AnyTrue):
@ -5021,10 +5022,10 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
case uint32_t(SimdOp::I64x2LoadU32x2):
CHECK(EmitLoadExtendSimd128(f, SimdOp(op.b1)));
case uint32_t(SimdOp::V128Load32ZeroExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(EmitLoadZeroSimd128(f, Scalar::Float32, 4));
case uint32_t(SimdOp::V128Load64ZeroExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(EmitLoadZeroSimd128(f, Scalar::Float64, 8));
default:
return f.iter().unrecognizedOpcode(&op);
@ -5354,7 +5355,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
MOZ_CRASH("unreachable");
#undef CHECK
#undef CHECK_EXPERIMENTAL_SIMD
#undef CHECK_SIMD_EXPERIMENTAL
}
bool wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,

View File

@ -483,10 +483,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
if (!(c)) return false; \
break
#define CHECK_EXPERIMENTAL_SIMD() \
if (!SimdExperimentalEnabled) { \
return iter.unrecognizedOpcode(&op); \
}
#ifdef ENABLE_WASM_SIMD_EXPERIMENTAL
# define CHECK_SIMD_EXPERIMENTAL() (void)(0)
#else
# define CHECK_SIMD_EXPERIMENTAL() return iter.unrecognizedOpcode(&op)
#endif
while (true) {
OpBytes op;
@ -1058,7 +1059,7 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
case uint32_t(SimdOp::F64x2PMaxExperimental):
case uint32_t(SimdOp::F64x2PMinExperimental):
case uint32_t(SimdOp::I32x4DotSI16x8Experimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(iter.readBinary(ValType::V128, &nothing, &nothing));
case uint32_t(SimdOp::I8x16Neg):
@ -1097,7 +1098,7 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
case uint32_t(SimdOp::F64x2FloorExperimental):
case uint32_t(SimdOp::F64x2TruncExperimental):
case uint32_t(SimdOp::F64x2NearestExperimental):
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(iter.readUnary(ValType::V128, &nothing));
case uint32_t(SimdOp::I8x16Shl):
@ -1177,13 +1178,13 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
case uint32_t(SimdOp::V128Load32ZeroExperimental): {
LinearMemoryAddress<Nothing> addr;
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(iter.readLoadSplat(4, &addr));
}
case uint32_t(SimdOp::V128Load64ZeroExperimental): {
LinearMemoryAddress<Nothing> addr;
CHECK_EXPERIMENTAL_SIMD();
CHECK_SIMD_EXPERIMENTAL();
CHECK(iter.readLoadSplat(8, &addr));
}
@ -1507,7 +1508,7 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
MOZ_CRASH("unreachable");
#undef CHECK
#undef CHECK_EXPERIMENTAL_SIMD
#undef CHECK_SIMD_EXPERIMENTAL
}
bool wasm::ValidateFunctionBody(const ModuleEnvironment& env,