Commit 62cdf3f9 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm-gc] Remove immediate arguments from type checks

As per the latest wasm-gc spec, all immediate arguments are removed
from ref.cast and ref.test.

Bug: v8:7748
Change-Id: I5839103276c4c5d51f3fa82a21cf2447cbb8ecaa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2649261
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72405}
parent c6de57fb
......@@ -4084,51 +4084,47 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
case kExprRefTest: {
// "Tests whether {obj}'s runtime type is a runtime subtype of {rtt}."
TypeIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
Value rtt = Pop(1);
if (!VALIDATE(
(rtt.type.is_rtt() && rtt.type.ref_index() == imm.index) ||
rtt.type == kWasmBottom)) {
PopTypeError(1, rtt, "rtt for type " + std::to_string(imm.index));
return 0;
}
Value obj = Pop(0, kWasmAnyRef);
Value* value = Push(kWasmI32);
if (obj.type != kWasmBottom) {
if (!VALIDATE(IsSubtypeOf(ValueType::Ref(imm.index, kNonNullable),
obj.type, this->module_))) {
PopTypeError(0, obj,
"supertype of type " + std::to_string(imm.index));
if (!VALIDATE(rtt.type.is_rtt() || rtt.type.is_bottom())) {
PopTypeError(1, rtt, "rtt");
return 0;
}
if (!obj.type.is_bottom() && !rtt.type.is_bottom()) {
if (!VALIDATE(IsSubtypeOf(
ValueType::Ref(rtt.type.ref_index(), kNonNullable), obj.type,
this->module_))) {
PopTypeError(
0, obj,
"supertype of type " + std::to_string(rtt.type.ref_index()));
return 0;
}
CALL_INTERFACE_IF_REACHABLE(RefTest, obj, rtt, value);
}
return opcode_length + imm.length;
return opcode_length;
}
case kExprRefCast: {
TypeIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
Value rtt = Pop(1);
if (!VALIDATE(
(rtt.type.is_rtt() && rtt.type.ref_index() == imm.index) ||
rtt.type == kWasmBottom)) {
PopTypeError(1, rtt, "rtt for type " + std::to_string(imm.index));
Value obj = Pop(0, kWasmAnyRef);
if (!VALIDATE(rtt.type.is_rtt() || rtt.type.is_bottom())) {
PopTypeError(1, rtt, "rtt");
return 0;
}
Value obj = Pop(0, kWasmAnyRef);
if (obj.type != kWasmBottom) {
if (!VALIDATE(IsSubtypeOf(ValueType::Ref(imm.index, kNonNullable),
obj.type, this->module_))) {
PopTypeError(0, obj,
"supertype of type " + std::to_string(imm.index));
if (!obj.type.is_bottom() && !rtt.type.is_bottom()) {
if (!VALIDATE(IsSubtypeOf(
ValueType::Ref(rtt.type.ref_index(), kNonNullable), obj.type,
this->module_))) {
PopTypeError(
0, obj,
"supertype of type " + std::to_string(rtt.type.ref_index()));
return 0;
}
Value* value =
Push(ValueType::Ref(imm.index, obj.type.nullability()));
Value* value = Push(
ValueType::Ref(rtt.type.ref_index(), obj.type.nullability()));
CALL_INTERFACE_IF_REACHABLE(RefCast, obj, rtt, value);
}
return opcode_length + imm.length;
return opcode_length;
}
case kExprBrOnCast: {
BranchDepthImmediate<validate> branch_depth(this,
......
......@@ -846,11 +846,10 @@ TEST(BasicRtt) {
subtype_index, WASM_I32V(11), WASM_I32V(42),
WASM_LOCAL_GET(kRttIndexCode))),
WASM_I32_ADD(
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(kStructIndexCode),
WASM_REF_TEST(WASM_LOCAL_GET(kStructIndexCode),
WASM_LOCAL_GET(kRttIndexCode)),
WASM_STRUCT_GET(subtype_index, kFieldIndex,
WASM_REF_CAST(subtype_index,
WASM_LOCAL_GET(kStructIndexCode),
WASM_REF_CAST(WASM_LOCAL_GET(kStructIndexCode),
WASM_LOCAL_GET(kRttIndexCode))))),
kExprEnd});
......@@ -906,8 +905,7 @@ TEST(NoDepthRtt) {
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT(
subtype_index, WASM_I32V(11), WASM_I32V(42),
WASM_RTT_CANON(subtype_index))),
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(0),
WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
kExprEnd});
const byte kTestSub = tester.DefineFunction(
......@@ -916,8 +914,7 @@ TEST(NoDepthRtt) {
0, WASM_STRUCT_NEW_WITH_RTT(
subtype_index, WASM_I32V(11), WASM_I32V(42),
WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)))),
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(0),
WASM_CALL_FUNCTION0(kRttSubtypeSub)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeSub)),
kExprEnd});
const byte kTestSubVsEmpty = tester.DefineFunction(
......@@ -926,8 +923,7 @@ TEST(NoDepthRtt) {
subtype_index, WASM_I32V(11), WASM_I32V(42),
WASM_RTT_SUB(subtype_index,
WASM_RTT_CANON(empty_struct_index)))),
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(0),
WASM_CALL_FUNCTION0(kRttSubtypeSub)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeSub)),
kExprEnd});
const byte kTestSubVsCanon = tester.DefineFunction(
......@@ -935,8 +931,7 @@ TEST(NoDepthRtt) {
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT(
subtype_index, WASM_I32V(11), WASM_I32V(42),
WASM_RTT_CANON(subtype_index))),
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(0),
WASM_CALL_FUNCTION0(kRttSubtypeSub)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeSub)),
kExprEnd});
const byte kTestCanonVsSub = tester.DefineFunction(
......@@ -945,16 +940,14 @@ TEST(NoDepthRtt) {
0, WASM_STRUCT_NEW_WITH_RTT(
subtype_index, WASM_I32V(11), WASM_I32V(42),
WASM_RTT_SUB(subtype_index, WASM_RTT_CANON(type_index)))),
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(0),
WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
kExprEnd});
const byte kTestSuperVsSub = tester.DefineFunction(
tester.sigs.i_v(), {optref(type_index)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
WASM_RTT_CANON(type_index))),
WASM_REF_TEST(subtype_index, WASM_LOCAL_GET(0),
WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
kExprEnd});
tester.CompileModule();
......@@ -1020,18 +1013,16 @@ WASM_COMPILED_EXEC_TEST(FunctionRefs) {
const byte cast = tester.DefineFunction(
&sig_func, {kWasmFuncRef},
{WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)),
WASM_REF_CAST(sig_index, WASM_LOCAL_GET(0), WASM_RTT_CANON(sig_index)),
kExprEnd});
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(sig_index)), kExprEnd});
const byte cast_reference = tester.DefineFunction(
&sig_func, {}, {WASM_REF_FUNC(sig_index), kExprEnd});
const byte test =
tester.DefineFunction(tester.sigs.i_v(), {kWasmFuncRef},
{WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)),
WASM_REF_TEST(other_sig_index, WASM_LOCAL_GET(0),
WASM_RTT_CANON(other_sig_index)),
kExprEnd});
const byte test = tester.DefineFunction(
tester.sigs.i_v(), {kWasmFuncRef},
{WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)),
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_RTT_CANON(other_sig_index)),
kExprEnd});
tester.CompileModule();
......@@ -1084,13 +1075,12 @@ WASM_COMPILED_EXEC_TEST(RefTestCastNull) {
const byte kRefTestNull = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_REF_TEST(type_index, WASM_REF_NULL(type_index),
WASM_RTT_CANON(type_index)),
{WASM_REF_TEST(WASM_REF_NULL(type_index), WASM_RTT_CANON(type_index)),
kExprEnd});
const byte kRefCastNull = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_REF_IS_NULL(WASM_REF_CAST(type_index, WASM_REF_NULL(type_index),
{WASM_REF_IS_NULL(WASM_REF_CAST(WASM_REF_NULL(type_index),
WASM_RTT_CANON(type_index))),
kExprEnd});
tester.CompileModule();
......@@ -1198,7 +1188,6 @@ WASM_COMPILED_EXEC_TEST(CastsBenchmark) {
WASM_STRUCT_GET(
SuperType, 0,
WASM_REF_CAST(
SuperType,
WASM_ARRAY_GET(
ListType, WASM_LOCAL_GET(list),
WASM_I32_AND(WASM_LOCAL_GET(i),
......@@ -1272,9 +1261,9 @@ TEST(JsAccess) {
kExprEnd});
tester.DefineExportedFunction(
"consumer", &sig_i_super,
{WASM_STRUCT_GET(type_index, 0,
WASM_REF_CAST(type_index, WASM_LOCAL_GET(0),
WASM_RTT_CANON(type_index))),
{WASM_STRUCT_GET(
type_index, 0,
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(type_index))),
kExprEnd});
tester.CompileModule();
......
......@@ -501,10 +501,8 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define WASM_REF_IS_NULL(val) val, kExprRefIsNull
#define WASM_REF_AS_NON_NULL(val) val, kExprRefAsNonNull
#define WASM_REF_EQ(lhs, rhs) lhs, rhs, kExprRefEq
#define WASM_REF_TEST(rtt_type, ref, rtt) \
ref, rtt, WASM_GC_OP(kExprRefTest), rtt_type
#define WASM_REF_CAST(rtt_type, ref, rtt) \
ref, rtt, WASM_GC_OP(kExprRefCast), rtt_type
#define WASM_REF_TEST(ref, rtt) ref, rtt, WASM_GC_OP(kExprRefTest)
#define WASM_REF_CAST(ref, rtt) ref, rtt, WASM_GC_OP(kExprRefCast)
// Takes a reference value from the value stack to allow sequences of
// conditional branches.
#define WASM_BR_ON_CAST(depth, rtt) \
......
......@@ -4259,30 +4259,28 @@ TEST_F(FunctionBodyDecoderTest, RefTestCast) {
if (should_pass) {
ExpectValidates(&test_sig,
{WASM_REF_TEST(WASM_HEAP_TYPE(to_heap), WASM_LOCAL_GET(0),
{WASM_REF_TEST(WASM_LOCAL_GET(0),
WASM_RTT_CANON(WASM_HEAP_TYPE(to_heap)))});
ExpectValidates(&cast_sig_with_depth,
{WASM_REF_CAST(WASM_HEAP_TYPE(to_heap), WASM_LOCAL_GET(0),
{WASM_REF_CAST(WASM_LOCAL_GET(0),
WASM_RTT_CANON(WASM_HEAP_TYPE(to_heap)))});
ExpectValidates(&cast_sig,
{WASM_REF_CAST(WASM_HEAP_TYPE(to_heap), WASM_LOCAL_GET(0),
WASM_LOCAL_GET(1))});
{WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1))});
} else {
std::string error_message = "[0] expected supertype of type " +
std::to_string(to_heap.ref_index()) +
", found local.get of type " +
test_reps[1].name();
ExpectFailure(&test_sig,
{WASM_REF_TEST(WASM_HEAP_TYPE(to_heap), WASM_LOCAL_GET(0),
{WASM_REF_TEST(WASM_LOCAL_GET(0),
WASM_RTT_CANON(WASM_HEAP_TYPE(to_heap)))},
kAppendEnd, ("ref.test" + error_message).c_str());
ExpectFailure(&cast_sig_with_depth,
{WASM_REF_CAST(WASM_HEAP_TYPE(to_heap), WASM_LOCAL_GET(0),
{WASM_REF_CAST(WASM_LOCAL_GET(0),
WASM_RTT_CANON(WASM_HEAP_TYPE(to_heap)))},
kAppendEnd, ("ref.cast" + error_message).c_str());
ExpectFailure(&cast_sig,
{WASM_REF_CAST(WASM_HEAP_TYPE(to_heap), WASM_LOCAL_GET(0),
WASM_LOCAL_GET(1))},
{WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1))},
kAppendEnd, ("ref.cast" + error_message).c_str());
}
}
......@@ -4290,54 +4288,24 @@ TEST_F(FunctionBodyDecoderTest, RefTestCast) {
// Trivial type error.
ExpectFailure(
sigs.v_v(),
{WASM_REF_TEST(static_cast<byte>(array_heap), WASM_I32V(1),
WASM_RTT_CANON(array_heap)),
kExprDrop},
{WASM_REF_TEST(WASM_I32V(1), WASM_RTT_CANON(array_heap)), kExprDrop},
kAppendEnd,
"ref.test[0] expected type anyref, found i32.const of type i32");
ExpectFailure(
sigs.v_v(),
{WASM_REF_CAST(static_cast<byte>(array_heap), WASM_I32V(1),
WASM_RTT_CANON(array_heap)),
kExprDrop},
{WASM_REF_CAST(WASM_I32V(1), WASM_RTT_CANON(array_heap)), kExprDrop},
kAppendEnd,
"ref.cast[0] expected type anyref, found i32.const of type i32");
// Mismached object heap immediate.
{
ValueType arg_type = ValueType::Ref(HeapType::kEq, kNonNullable);
FunctionSig sig(0, 1, &arg_type);
ExpectFailure(
&sig,
{WASM_REF_TEST(static_cast<byte>(array_heap), WASM_LOCAL_GET(0),
WASM_RTT_CANON(sub_struct_heap)),
kExprDrop},
kAppendEnd,
"ref.test[1] expected rtt for type 0, found rtt.canon of type (rtt 0 "
"2)");
ExpectFailure(
&sig,
{WASM_REF_CAST(static_cast<byte>(array_heap), WASM_LOCAL_GET(0),
WASM_RTT_CANON(sub_struct_heap)),
kExprDrop},
kAppendEnd,
"ref.cast[1] expected rtt for type 0, found rtt.canon of type (rtt 0 "
"2)");
}
// Trivial type error.
ExpectFailure(
sigs.v_v(),
{WASM_REF_TEST(static_cast<byte>(array_heap), WASM_I32V(1),
WASM_RTT_CANON(array_heap)),
kExprDrop},
{WASM_REF_TEST(WASM_I32V(1), WASM_RTT_CANON(array_heap)), kExprDrop},
kAppendEnd,
"ref.test[0] expected type anyref, found i32.const of type i32");
ExpectFailure(
sigs.v_v(),
{WASM_REF_CAST(static_cast<byte>(array_heap), WASM_I32V(1),
WASM_RTT_CANON(array_heap)),
kExprDrop},
{WASM_REF_CAST(WASM_I32V(1), WASM_RTT_CANON(array_heap)), kExprDrop},
kAppendEnd,
"ref.cast[0] expected type anyref, found i32.const of type i32");
}
......
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