Commit 1ac45dd9 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm-gc] Optionally skip null checks

Bug: v8:7748
Change-Id: Ia277cf58a0eea431c4f19198914c1539fd03bc06
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3207898
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77264}
parent 5889deb1
......@@ -611,8 +611,10 @@ Node* WasmGraphBuilder::RefFunc(uint32_t function_index) {
Node* WasmGraphBuilder::RefAsNonNull(Node* arg,
wasm::WasmCodePosition position) {
TrapIfTrue(wasm::kTrapIllegalCast, gasm_->WordEqual(arg, RefNull()),
position);
if (!FLAG_experimental_wasm_skip_null_checks) {
TrapIfTrue(wasm::kTrapIllegalCast, gasm_->WordEqual(arg, RefNull()),
position);
}
return arg;
}
......
......@@ -2456,7 +2456,7 @@ class LiftoffCompiler {
LiftoffRegList pinned;
LiftoffRegister obj = pinned.set(__ PopToRegister(pinned));
Label* trap_label =
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapNullDereference);
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapIllegalCast);
LiftoffRegister null = __ GetUnusedRegister(kGpReg, pinned);
LoadNullValue(null.gp(), pinned);
__ emit_cond_jump(kUnequal, trap_label, kOptRef, obj.gp(), null.gp());
......@@ -6030,7 +6030,7 @@ class LiftoffCompiler {
void MaybeEmitNullCheck(FullDecoder* decoder, Register object,
LiftoffRegList pinned, ValueType type) {
if (!type.is_nullable()) return;
if (FLAG_experimental_wasm_skip_null_checks || !type.is_nullable()) return;
Label* trap_label =
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapNullDereference);
LiftoffRegister null = __ GetUnusedRegister(kGpReg, pinned);
......
......@@ -1754,8 +1754,9 @@ class WasmGraphBuildingInterface {
CheckForNull NullCheckFor(ValueType type) {
DCHECK(type.is_object_reference());
return type.is_nullable() ? CheckForNull::kWithNullCheck
: CheckForNull::kWithoutNullCheck;
return (!FLAG_experimental_wasm_skip_null_checks && type.is_nullable())
? CheckForNull::kWithNullCheck
: CheckForNull::kWithoutNullCheck;
}
};
......
......@@ -35,6 +35,9 @@
V(assume_ref_cast_succeeds, \
"assume ref.cast always succeeds and skip the related type check " \
"(unsafe)", \
false) \
V(skip_null_checks, \
"skip null checks for call.ref and array and struct operations (unsafe)", \
false) \
\
/* Typed function references proposal. */ \
......
......@@ -317,8 +317,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicStruct) {
tester.CheckResult(kSet, -99);
}
// Test struct.set, ref.as_non_null,
// struct refs types in globals and if-results.
// Test struct.get, ref.as_non_null and ref-typed globals.
WASM_COMPILED_EXEC_TEST(WasmRefAsNonNull) {
WasmGCTester tester(execution_tier);
const byte type_index =
......@@ -332,21 +331,48 @@ WASM_COMPILED_EXEC_TEST(WasmRefAsNonNull) {
WasmInitExpr::RefNullConst(
static_cast<HeapType::Representation>(type_index)));
const byte field_index = 0;
const byte kFunc = tester.DefineFunction(
const byte kNonNull = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_GLOBAL_SET(
global_index,
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(55), WASM_I32V(66),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_GET(
type_index, field_index,
WASM_REF_AS_NON_NULL(WASM_IF_ELSE_R(kOptRefType, WASM_I32V(1),
WASM_GLOBAL_GET(global_index),
WASM_REF_NULL(type_index)))),
WASM_STRUCT_GET(type_index, field_index,
WASM_REF_AS_NON_NULL(WASM_GLOBAL_GET(global_index))),
kExprEnd});
const byte kNull = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_GLOBAL_SET(global_index, WASM_REF_NULL(type_index)),
WASM_STRUCT_GET(type_index, field_index,
WASM_REF_AS_NON_NULL(WASM_GLOBAL_GET(global_index))),
kExprEnd});
tester.CompileModule();
tester.CheckResult(kNonNull, 55);
tester.CheckHasThrown(kNull);
}
WASM_COMPILED_EXEC_TEST(WasmRefAsNonNullSkipCheck) {
FlagScope<bool> no_check(&FLAG_experimental_wasm_skip_null_checks, true);
WasmGCTester tester(execution_tier);
const byte type_index =
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
ValueType kRefType = ref(type_index);
FunctionSig sig_q_v(1, 0, &kRefType);
const byte global_index =
tester.AddGlobal(optref(type_index), true,
WasmInitExpr::RefNullConst(
static_cast<HeapType::Representation>(type_index)));
const byte kFunc = tester.DefineFunction(
&sig_q_v, {},
{WASM_GLOBAL_SET(global_index, WASM_REF_NULL(type_index)),
WASM_REF_AS_NON_NULL(WASM_GLOBAL_GET(global_index)), kExprEnd});
tester.CompileModule();
tester.CheckResult(kFunc, 55);
Handle<Object> result = tester.GetResultObject(kFunc).ToHandleChecked();
// Without null checks, ref.as_non_null can actually return null.
CHECK(result->IsNull());
}
WASM_COMPILED_EXEC_TEST(WasmBrOnNull) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment