[wasm-gc] Enable runtime subtyping checks for functions

Bug: v8:7748
Change-Id: Ic65c09726994fddf73979b5f25b98f7ce4c5d6ef
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3574556
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79870}
This commit is contained in:
Manos Koukoutos 2022-04-06 17:24:34 +00:00 committed by V8 LUCI CQ
parent 022657040b
commit b09d550605
6 changed files with 46 additions and 30 deletions

View File

@ -5795,15 +5795,6 @@ void WasmGraphBuilder::TypeCheck(
Node* map = gasm_->LoadMap(object);
if (config.reference_kind == kFunction) {
// Currently, the only way for a function to match an rtt is if its map
// is equal to that rtt.
callbacks.fail_if_not(gasm_->TaggedEqual(map, rtt), BranchHint::kTrue);
return;
}
DCHECK(config.reference_kind == kArrayOrStruct);
// First, check if types happen to be equal. This has been shown to give large
// speedups.
callbacks.succeed_if(gasm_->TaggedEqual(map, rtt), BranchHint::kTrue);

View File

@ -223,13 +223,8 @@ class WasmGraphBuilder {
kWasmApiFunctionRefMode,
kNoSpecialParameterMode
};
enum ReferenceKind : bool { // --
kArrayOrStruct = true,
kFunction = false
};
struct ObjectReferenceKnowledge {
bool object_can_be_null;
ReferenceKind reference_kind;
uint8_t rtt_depth;
};
enum EnforceBoundsCheck : bool { // --

View File

@ -5573,17 +5573,6 @@ class LiftoffCompiler {
__ LoadMap(tmp1.gp(), obj_reg.gp());
// {tmp1} now holds the object's map.
if (decoder->module_->has_signature(rtt.type.ref_index())) {
// Function case: currently, the only way for the type check to succeed is
// that the function's map equals the rtt.
__ emit_cond_jump(kUnequal, no_match, rtt.type.kind(), tmp1.gp(),
rtt_reg.gp());
__ bind(&match);
return obj_reg;
}
// Array/struct case until the rest of the function.
// Check for rtt equality, and if not, check if the rtt is a struct/array
// rtt.
__ emit_cond_jump(kEqual, &match, rtt.type.kind(), tmp1.gp(), rtt_reg.gp());

View File

@ -1161,10 +1161,6 @@ class WasmGraphBuildingInterface {
result.object_can_be_null = object_type.is_nullable();
DCHECK(object_type.is_object_reference()); // Checked by validation.
// In the bottom case, the result is irrelevant.
result.reference_kind =
!rtt_type.is_bottom() && module->has_signature(rtt_type.ref_index())
? compiler::WasmGraphBuilder::kFunction
: compiler::WasmGraphBuilder::kArrayOrStruct;
result.rtt_depth = rtt_type.is_bottom()
? 0 /* unused */
: static_cast<uint8_t>(GetSubtypingDepth(

View File

@ -253,7 +253,6 @@ void CreateMapForType(Isolate* isolate, const WasmModule* module,
map = CreateArrayMap(isolate, module, type_index, rtt_parent, instance);
break;
case TypeDefinition::kFunction:
// TODO(7748): Create funcref RTTs lazily?
map = CreateFuncRefMap(isolate, module, rtt_parent, instance);
break;
}

View File

@ -5,6 +5,7 @@
#include <stdint.h>
#include "src/base/vector.h"
#include "src/codegen/signature.h"
#include "src/utils/utils.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/struct-types.h"
@ -491,6 +492,28 @@ WASM_COMPILED_EXEC_TEST(RefCast) {
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
const byte subtype2_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
auto super_sig = FixedSizeSignature<ValueType>::Params(
ValueType::Ref(subtype1_index, kNullable))
.Returns(ValueType::Ref(supertype_index, kNullable));
auto sub_sig1 = FixedSizeSignature<ValueType>::Params(
ValueType::Ref(supertype_index, kNullable))
.Returns(ValueType::Ref(subtype1_index, kNullable));
auto sub_sig2 = FixedSizeSignature<ValueType>::Params(
ValueType::Ref(supertype_index, kNullable))
.Returns(ValueType::Ref(subtype2_index, kNullable));
const byte function_type_index = tester.DefineSignature(&super_sig);
const byte function_subtype1_index =
tester.DefineSignature(&sub_sig1, function_type_index);
const byte function_subtype2_index =
tester.DefineSignature(&sub_sig2, function_type_index);
const byte function_index = tester.DefineFunction(
function_subtype1_index, {},
{WASM_STRUCT_NEW_DEFAULT_WITH_RTT(subtype1_index,
WASM_RTT_CANON(subtype1_index)),
WASM_END});
// Just so this function counts as "declared".
tester.AddGlobal(ValueType::Ref(function_type_index, kNullable), false,
WasmInitExpr::RefFuncConst(function_index));
const byte kTestSuccessful = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
@ -510,9 +533,32 @@ WASM_COMPILED_EXEC_TEST(RefCast) {
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(subtype2_index))),
WASM_END});
const byte kFuncTestSuccessfulSuper = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(function_type_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_REF_FUNC(function_index)),
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(function_type_index)),
WASM_DROP, WASM_I32V(0), WASM_END});
const byte kFuncTestSuccessfulSub = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(function_type_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_REF_FUNC(function_index)),
WASM_REF_CAST(WASM_LOCAL_GET(0),
WASM_RTT_CANON(function_subtype1_index)),
WASM_DROP, WASM_I32V(0), WASM_END});
const byte kFuncTestFailed = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::Ref(function_type_index, kNullable)},
{WASM_LOCAL_SET(0, WASM_REF_FUNC(function_index)),
WASM_REF_CAST(WASM_LOCAL_GET(0),
WASM_RTT_CANON(function_subtype2_index)),
WASM_DROP, WASM_I32V(1), WASM_END});
tester.CompileModule();
tester.CheckResult(kTestSuccessful, 0);
tester.CheckHasThrown(kTestFailed);
tester.CheckResult(kFuncTestSuccessfulSuper, 0);
tester.CheckResult(kFuncTestSuccessfulSub, 0);
tester.CheckHasThrown(kFuncTestFailed);
}
WASM_COMPILED_EXEC_TEST(RefCastStatic) {