[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:
parent
3ad6bc44f3
commit
5889deb100
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 */ \
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user