Commit 4f50c554 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-gc] Add null checks to ref.cast and ref.test

Bug: v8:7748
Change-Id: I43384d10805b62745a4bc19fa0a4174e6ee94f0f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2289777
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68804}
parent 1540a014
...@@ -5401,21 +5401,38 @@ Node* WasmGraphBuilder::RttSub(wasm::HeapType type, Node* parent_rtt) { ...@@ -5401,21 +5401,38 @@ Node* WasmGraphBuilder::RttSub(wasm::HeapType type, Node* parent_rtt) {
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer())); LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
} }
Node* WasmGraphBuilder::RefTest(Node* object, Node* rtt) { Node* WasmGraphBuilder::RefTest(Node* object, Node* rtt,
// TODO(7748): Check if {object} is null. CheckForNull null_check) {
// TODO(7748): Check if {object} is an i31ref. // TODO(7748): Check if {object} is an i31ref.
auto done = gasm_->MakeLabel(MachineRepresentation::kWord32);
if (null_check == kWithNullCheck) {
gasm_->GotoIf(gasm_->WordEqual(object, RefNull()), &done,
gasm_->Int32Constant(0));
}
Node* map = gasm_->Load(MachineType::TaggedPointer(), object, Node* map = gasm_->Load(MachineType::TaggedPointer(), object,
HeapObject::kMapOffset - kHeapObjectTag); HeapObject::kMapOffset - kHeapObjectTag);
// TODO(7748): Add a fast path for map == rtt. // TODO(7748): Add a fast path for map == rtt.
return BuildChangeSmiToInt32(CALL_BUILTIN( Node* subtype_check = BuildChangeSmiToInt32(CALL_BUILTIN(
WasmIsRttSubtype, map, rtt, WasmIsRttSubtype, map, rtt,
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()))); LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer())));
if (null_check == kWithNullCheck) {
gasm_->Goto(&done, subtype_check);
gasm_->Bind(&done);
subtype_check = done.PhiAt(0);
}
return subtype_check;
} }
Node* WasmGraphBuilder::RefCast(Node* object, Node* rtt, Node* WasmGraphBuilder::RefCast(Node* object, Node* rtt,
CheckForNull null_check,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position) {
// TODO(7748): Check if {object} is null.
// TODO(7748): Check if {object} is an i31ref. // TODO(7748): Check if {object} is an i31ref.
if (null_check == kWithNullCheck) {
TrapIfTrue(wasm::kTrapIllegalCast, gasm_->WordEqual(object, RefNull()),
position);
}
Node* map = gasm_->Load(MachineType::TaggedPointer(), object, Node* map = gasm_->Load(MachineType::TaggedPointer(), object,
HeapObject::kMapOffset - kHeapObjectTag); HeapObject::kMapOffset - kHeapObjectTag);
// TODO(7748): Add a fast path for map == rtt. // TODO(7748): Add a fast path for map == rtt.
......
...@@ -407,8 +407,9 @@ class WasmGraphBuilder { ...@@ -407,8 +407,9 @@ class WasmGraphBuilder {
Node* I31GetU(Node* input); Node* I31GetU(Node* input);
Node* RttCanon(wasm::HeapType type); Node* RttCanon(wasm::HeapType type);
Node* RttSub(wasm::HeapType type, Node* parent_rtt); Node* RttSub(wasm::HeapType type, Node* parent_rtt);
Node* RefTest(Node* object, Node* rtt); Node* RefTest(Node* object, Node* rtt, CheckForNull null_check);
Node* RefCast(Node* object, Node* rtt, wasm::WasmCodePosition position); Node* RefCast(Node* object, Node* rtt, CheckForNull null_check,
wasm::WasmCodePosition position);
bool has_simd() const { return has_simd_; } bool has_simd() const { return has_simd_; }
......
...@@ -750,12 +750,21 @@ class WasmGraphBuildingInterface { ...@@ -750,12 +750,21 @@ class WasmGraphBuildingInterface {
void RefTest(FullDecoder* decoder, const Value& object, const Value& rtt, void RefTest(FullDecoder* decoder, const Value& object, const Value& rtt,
Value* result) { Value* result) {
result->node = BUILD(RefTest, object.node, rtt.node); using CheckForNull = compiler::WasmGraphBuilder::CheckForNull;
CheckForNull null_check = object.type.is_nullable()
? CheckForNull::kWithNullCheck
: CheckForNull::kWithoutNullCheck;
result->node = BUILD(RefTest, object.node, rtt.node, null_check);
} }
void RefCast(FullDecoder* decoder, const Value& object, const Value& rtt, void RefCast(FullDecoder* decoder, const Value& object, const Value& rtt,
Value* result) { Value* result) {
result->node = BUILD(RefCast, object.node, rtt.node, decoder->position()); using CheckForNull = compiler::WasmGraphBuilder::CheckForNull;
CheckForNull null_check = object.type.is_nullable()
? CheckForNull::kWithNullCheck
: CheckForNull::kWithoutNullCheck;
result->node =
BUILD(RefCast, object.node, rtt.node, null_check, decoder->position());
} }
void PassThrough(FullDecoder* decoder, const Value& from, Value* to) { void PassThrough(FullDecoder* decoder, const Value& from, Value* to) {
......
...@@ -649,6 +649,28 @@ TEST(BasicRTT) { ...@@ -649,6 +649,28 @@ TEST(BasicRTT) {
tester.CheckResult(kRefCast, 43); tester.CheckResult(kRefCast, 43);
} }
TEST(RefTestCastNull) {
WasmGCTester tester;
uint8_t type_index =
static_cast<uint8_t>(tester.DefineStruct({F(wasm::kWasmI32, true)}));
const uint32_t kRefTestNull = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_REF_TEST(type_index, type_index, WASM_REF_NULL(type_index),
WASM_RTT_CANON(type_index)),
kExprEnd});
const uint32_t kRefCastNull = tester.DefineFunction(
tester.sigs.i_i(), // Argument and return value ignored
{},
{WASM_REF_CAST(type_index, type_index, WASM_REF_NULL(type_index),
WASM_RTT_CANON(type_index)),
kExprDrop, WASM_I32V(0), kExprEnd});
tester.CompileModule();
tester.CheckResult(kRefTestNull, 0);
tester.CheckHasThrown(kRefCastNull, 0);
}
TEST(BasicI31) { TEST(BasicI31) {
WasmGCTester tester; WasmGCTester tester;
const uint32_t kSigned = tester.DefineFunction( const uint32_t kSigned = tester.DefineFunction(
......
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