[wasm-gc] Optionally skip ref.cast type check

Bug: v8:7748
Change-Id: I5b0200560c5d77c1218142ca686c4e71c5106600
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3208027
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77263}
This commit is contained in:
Manos Koukoutos 2021-10-06 13:09:57 +00:00 committed by V8 LUCI CQ
parent 3ad6bc44f3
commit 5889deb100
4 changed files with 123 additions and 15 deletions

View File

@ -5815,10 +5815,12 @@ Node* WasmGraphBuilder::RefTest(Node* object, Node* rtt,
Node* WasmGraphBuilder::RefCast(Node* object, Node* rtt,
ObjectReferenceKnowledge config,
wasm::WasmCodePosition position) {
auto done = gasm_->MakeLabel();
TypeCheck(object, rtt, config, true, CastCallbacks(&done, position));
gasm_->Goto(&done);
gasm_->Bind(&done);
if (!FLAG_experimental_wasm_assume_ref_cast_succeeds) {
auto done = gasm_->MakeLabel();
TypeCheck(object, rtt, config, true, CastCallbacks(&done, position));
gasm_->Goto(&done);
gasm_->Bind(&done);
}
return object;
}

View File

@ -5413,11 +5413,16 @@ class LiftoffCompiler {
void RefCast(FullDecoder* decoder, const Value& obj, const Value& rtt,
Value* result) {
Label* trap_label =
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapIllegalCast);
LiftoffRegister obj_reg =
SubtypeCheck(decoder, obj, rtt, trap_label, kNullSucceeds);
__ PushRegister(obj.type.kind(), obj_reg);
if (FLAG_experimental_wasm_assume_ref_cast_succeeds) {
// Just drop the rtt.
__ DropValues(1);
} else {
Label* trap_label =
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapIllegalCast);
LiftoffRegister obj_reg =
SubtypeCheck(decoder, obj, rtt, trap_label, kNullSucceeds);
__ PushRegister(obj.type.kind(), obj_reg);
}
}
void BrOnCast(FullDecoder* decoder, const Value& obj, const Value& rtt,

View File

@ -32,6 +32,10 @@
false) \
V(unsafe_nn_locals, \
"allow non-defaultable/non-nullable locals, no validation", false) \
V(assume_ref_cast_succeeds, \
"assume ref.cast always succeeds and skip the related type check " \
"(unsafe)", \
false) \
\
/* Typed function references proposal. */ \
/* Official proposal: https://github.com/WebAssembly/function-references */ \

View File

@ -36,12 +36,10 @@ class WasmGCTester {
flag_reftypes(&v8::internal::FLAG_experimental_wasm_reftypes, true),
flag_typedfuns(&v8::internal::FLAG_experimental_wasm_typed_funcref,
true),
flag_liftoff(
&v8::internal::FLAG_liftoff,
execution_tier == TestExecutionTier::kTurbofan ? false : true),
flag_liftoff_only(
&v8::internal::FLAG_liftoff_only,
execution_tier == TestExecutionTier::kLiftoff ? true : false),
flag_liftoff(&v8::internal::FLAG_liftoff,
execution_tier == TestExecutionTier::kLiftoff),
flag_liftoff_only(&v8::internal::FLAG_liftoff_only,
execution_tier == TestExecutionTier::kLiftoff),
flag_tierup(&v8::internal::FLAG_wasm_tier_up, false),
zone_(&allocator, ZONE_NAME),
builder_(&zone_),
@ -431,6 +429,105 @@ WASM_COMPILED_EXEC_TEST(WasmBrOnNonNull) {
tester.CheckResult(kNotTaken, 11);
}
WASM_COMPILED_EXEC_TEST(RefCast) {
WasmGCTester tester(execution_tier);
const byte supertype_index = tester.DefineStruct({F(kWasmI32, true)});
const byte subtype1_index =
tester.DefineStruct({F(kWasmI32, true), F(kWasmF32, false)});
const byte subtype2_index =
tester.DefineStruct({F(kWasmI32, true), F(kWasmI64, false)});
const byte kTestSuccessful = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
subtype1_index,
WASM_RTT_SUB(subtype1_index,
WASM_RTT_CANON(supertype_index)))),
WASM_STRUCT_GET(
subtype1_index, 0,
WASM_REF_CAST(
WASM_LOCAL_GET(0),
WASM_RTT_SUB(subtype1_index, WASM_RTT_CANON(supertype_index)))),
WASM_END});
const byte kTestFailed = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
subtype1_index,
WASM_RTT_SUB(subtype1_index,
WASM_RTT_CANON(supertype_index)))),
WASM_STRUCT_GET(
subtype2_index, 0,
WASM_REF_CAST(
WASM_LOCAL_GET(0),
WASM_RTT_SUB(subtype2_index, WASM_RTT_CANON(supertype_index)))),
WASM_END});
tester.CompileModule();
tester.CheckResult(kTestSuccessful, 0);
tester.CheckHasThrown(kTestFailed);
}
WASM_COMPILED_EXEC_TEST(RefCastStatic) {
WasmGCTester tester(execution_tier);
const byte supertype_index =
tester.DefineStruct({F(kWasmI32, true)}, kGenericSuperType);
const byte subtype1_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
const byte subtype2_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
const byte kTestSuccessful = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
WASM_STRUCT_GET(subtype1_index, 0,
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype1_index)),
WASM_END});
const byte kTestFailed = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
WASM_STRUCT_GET(subtype2_index, 0,
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype2_index)),
WASM_END});
tester.CompileModule();
tester.CheckResult(kTestSuccessful, 0);
tester.CheckHasThrown(kTestFailed);
}
WASM_COMPILED_EXEC_TEST(RefCastStaticNoChecks) {
FlagScope<bool> scope(&FLAG_experimental_wasm_assume_ref_cast_succeeds, true);
WasmGCTester tester(execution_tier);
const byte supertype_index =
tester.DefineStruct({F(kWasmI32, true)}, kGenericSuperType);
const byte subtype1_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
const byte subtype2_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
const byte kTestSuccessful = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
WASM_STRUCT_GET(subtype1_index, 0,
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype1_index)),
WASM_END});
const byte kTestFailed = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
WASM_STRUCT_GET(subtype2_index, 0,
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype2_index)),
WASM_END});
tester.CompileModule();
tester.CheckResult(kTestSuccessful, 0);
tester.CheckResult(kTestFailed, 0);
}
WASM_COMPILED_EXEC_TEST(BrOnCast) {
WasmGCTester tester(execution_tier);
ValueType kDataRefNull = ValueType::Ref(HeapType::kData, kNullable);