Commit 26626f87 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-gc] Implement struct.new_with_rtt

Bug: v8:7748
Change-Id: I6bbb73ceb397b102783ecfcc553264d83e926df2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2273126
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68620}
parent 8e54afbe
...@@ -242,6 +242,15 @@ builtin WasmAllocateRtt(implicit context: Context)( ...@@ -242,6 +242,15 @@ builtin WasmAllocateRtt(implicit context: Context)(
tail runtime::WasmAllocateRtt(context, typeIndex, parent); tail runtime::WasmAllocateRtt(context, typeIndex, parent);
} }
builtin WasmAllocateStructWithRtt(implicit context: Context)(rtt: Map):
HeapObject {
const instanceSize: intptr =
unsafe::TimesTaggedSize(Convert<intptr>(rtt.instance_size_in_words));
const result: HeapObject = unsafe::Allocate(instanceSize);
* UnsafeConstCast(& result.map) = rtt;
return result;
}
builtin WasmInt32ToNumber(value: int32): Number { builtin WasmInt32ToNumber(value: int32): Number {
return ChangeInt32ToTagged(value); return ChangeInt32ToTagged(value);
} }
......
...@@ -5287,6 +5287,18 @@ Node* WasmGraphBuilder::StructNew(uint32_t struct_index, ...@@ -5287,6 +5287,18 @@ Node* WasmGraphBuilder::StructNew(uint32_t struct_index,
return s; return s;
} }
Node* WasmGraphBuilder::StructNewWithRtt(uint32_t struct_index,
const wasm::StructType* type,
Node* rtt, Vector<Node*> fields) {
Node* s = CALL_BUILTIN(
WasmAllocateStructWithRtt, rtt,
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
for (uint32_t i = 0; i < type->field_count(); i++) {
StoreStructFieldUnchecked(mcgraph(), gasm_.get(), s, type, i, fields[i]);
}
return s;
}
Node* WasmGraphBuilder::ArrayNew(uint32_t array_index, Node* WasmGraphBuilder::ArrayNew(uint32_t array_index,
const wasm::ArrayType* type, Node* length, const wasm::ArrayType* type, Node* length,
Node* initial_value) { Node* initial_value) {
......
...@@ -383,6 +383,8 @@ class WasmGraphBuilder { ...@@ -383,6 +383,8 @@ class WasmGraphBuilder {
Node* StructNew(uint32_t struct_index, const wasm::StructType* type, Node* StructNew(uint32_t struct_index, const wasm::StructType* type,
Vector<Node*> fields); Vector<Node*> fields);
Node* StructNewWithRtt(uint32_t struct_index, const wasm::StructType* type,
Node* rtt, Vector<Node*> fields);
Node* StructGet(Node* struct_object, const wasm::StructType* struct_type, Node* StructGet(Node* struct_object, const wasm::StructType* struct_type,
uint32_t field_index, CheckForNull null_check, bool is_signed, uint32_t field_index, CheckForNull null_check, bool is_signed,
wasm::WasmCodePosition position); wasm::WasmCodePosition position);
......
...@@ -3576,6 +3576,12 @@ class LiftoffCompiler { ...@@ -3576,6 +3576,12 @@ class LiftoffCompiler {
// TODO(7748): Implement. // TODO(7748): Implement.
unsupported(decoder, kGC, "struct.new"); unsupported(decoder, kGC, "struct.new");
} }
void StructNewWithRtt(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm,
const Value& rtt, const Value args[], Value* result) {
// TODO(7748): Implement.
unsupported(decoder, kGC, "struct.new_with_rtt");
}
void StructGet(FullDecoder* decoder, const Value& struct_obj, void StructGet(FullDecoder* decoder, const Value& struct_obj,
const FieldIndexImmediate<validate>& field, bool is_signed, const FieldIndexImmediate<validate>& field, bool is_signed,
Value* result) { Value* result) {
......
...@@ -953,6 +953,8 @@ struct ControlBase { ...@@ -953,6 +953,8 @@ struct ControlBase {
const Value& value, const Value& count) \ const Value& value, const Value& count) \
F(StructNew, const StructIndexImmediate<validate>& imm, const Value args[], \ F(StructNew, const StructIndexImmediate<validate>& imm, const Value args[], \
Value* result) \ Value* result) \
F(StructNewWithRtt, const StructIndexImmediate<validate>& imm, \
const Value& rtt, const Value args[], Value* result) \
F(StructGet, const Value& struct_object, \ F(StructGet, const Value& struct_object, \
const FieldIndexImmediate<validate>& field, bool is_signed, Value* result) \ const FieldIndexImmediate<validate>& field, bool is_signed, Value* result) \
F(StructSet, const Value& struct_object, \ F(StructSet, const Value& struct_object, \
...@@ -1667,7 +1669,7 @@ class WasmDecoder : public Decoder { ...@@ -1667,7 +1669,7 @@ class WasmDecoder : public Decoder {
WasmOpcode opcode = static_cast<WasmOpcode>(kGCPrefix << 8 | gc_index); WasmOpcode opcode = static_cast<WasmOpcode>(kGCPrefix << 8 | gc_index);
switch (opcode) { switch (opcode) {
case kExprStructNew: case kExprStructNew:
case kExprStructNewSub: case kExprStructNewWithRtt:
case kExprStructNewDefault: { case kExprStructNewDefault: {
StructIndexImmediate<validate> imm(decoder, pc + 2); StructIndexImmediate<validate> imm(decoder, pc + 2);
return 2 + imm.length; return 2 + imm.length;
...@@ -3334,6 +3336,33 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -3334,6 +3336,33 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE_IF_REACHABLE(StructNew, imm, args.begin(), value); CALL_INTERFACE_IF_REACHABLE(StructNew, imm, args.begin(), value);
break; break;
} }
case kExprStructNewWithRtt: {
StructIndexImmediate<validate> imm(this, this->pc_ + len);
len += imm.length;
if (!this->Validate(this->pc_, imm)) break;
Value rtt = Pop();
if (!VALIDATE(rtt.type.kind() == ValueType::kRtt)) {
this->errorf(
this->pc_ + len,
"struct.new_with_rtt expected type rtt, found %s of type %s",
SafeOpcodeNameAt(rtt.pc), rtt.type.type_name().c_str());
break;
}
// TODO(7748): Drop this check if {imm} is dropped from the proposal
// à la https://github.com/WebAssembly/function-references/pull/31.
if (!VALIDATE(rtt.type.heap() == imm.index)) {
this->errorf(this->pc_ + len,
"struct.new_with_rtt expected rtt for type %d, found "
"rtt for type %s",
imm.index, rtt.type.heap_type().name().c_str());
break;
}
ArgVector args = PopArgs(imm.struct_type);
Value* value = Push(ValueType::Ref(imm.index, kNonNullable));
CALL_INTERFACE_IF_REACHABLE(StructNewWithRtt, imm, rtt, args.begin(),
value);
break;
}
case kExprStructGet: { case kExprStructGet: {
FieldIndexImmediate<validate> field(this, this->pc_ + 2); FieldIndexImmediate<validate> field(this, this->pc_ + 2);
len += field.length; len += field.length;
......
...@@ -653,6 +653,18 @@ class WasmGraphBuildingInterface { ...@@ -653,6 +653,18 @@ class WasmGraphBuildingInterface {
BUILD(StructNew, imm.index, imm.struct_type, VectorOf(arg_nodes)); BUILD(StructNew, imm.index, imm.struct_type, VectorOf(arg_nodes));
} }
void StructNewWithRtt(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm,
const Value& rtt, const Value args[], Value* result) {
uint32_t field_count = imm.struct_type->field_count();
base::SmallVector<TFNode*, 16> arg_nodes(field_count);
for (uint32_t i = 0; i < field_count; i++) {
arg_nodes[i] = args[i].node;
}
result->node = BUILD(StructNewWithRtt, imm.index, imm.struct_type, rtt.node,
VectorOf(arg_nodes));
}
void StructGet(FullDecoder* decoder, const Value& struct_object, void StructGet(FullDecoder* decoder, const Value& struct_object,
const FieldIndexImmediate<validate>& field, bool is_signed, const FieldIndexImmediate<validate>& field, bool is_signed,
Value* result) { Value* result) {
......
...@@ -355,7 +355,7 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) { ...@@ -355,7 +355,7 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
// GC operations. // GC operations.
CASE_OP(StructNew, "struct.new") CASE_OP(StructNew, "struct.new")
CASE_OP(StructNewSub, "struct.new_sub") CASE_OP(StructNewWithRtt, "struct.new_with_rtt")
CASE_OP(StructNewDefault, "struct.new_default") CASE_OP(StructNewDefault, "struct.new_default")
CASE_OP(StructGet, "struct.get") CASE_OP(StructGet, "struct.get")
CASE_OP(StructGetS, "struct.get_s") CASE_OP(StructGetS, "struct.get_s")
......
...@@ -598,7 +598,7 @@ bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmFeatures&); ...@@ -598,7 +598,7 @@ bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmFeatures&);
#define FOREACH_GC_OPCODE(V) \ #define FOREACH_GC_OPCODE(V) \
V(StructNew, 0xfb00, _) \ V(StructNew, 0xfb00, _) \
V(StructNewSub, 0xfb01, _) \ V(StructNewWithRtt, 0xfb01, _) \
V(StructNewDefault, 0xfb02, _) \ V(StructNewDefault, 0xfb02, _) \
V(StructGet, 0xfb03, _) \ V(StructGet, 0xfb03, _) \
V(StructGetS, 0xfb04, _) \ V(StructGetS, 0xfb04, _) \
......
...@@ -555,12 +555,19 @@ TEST(BasicRTT) { ...@@ -555,12 +555,19 @@ TEST(BasicRTT) {
ValueType kRttSubtypes[] = { ValueType kRttSubtypes[] = {
ValueType::Rtt(static_cast<HeapType>(subtype_index), 2)}; ValueType::Rtt(static_cast<HeapType>(subtype_index), 2)};
FunctionSig sig_t2_v(1, 0, kRttSubtypes); FunctionSig sig_t2_v(1, 0, kRttSubtypes);
ValueType kRefTypes[] = {
ValueType::Ref(static_cast<HeapType>(type_index), kNonNullable)};
FunctionSig sig_q_v(1, 0, kRefTypes);
tester.DefineFunction("f", &sig_t_v, {}, tester.DefineFunction("f", &sig_t_v, {},
{WASM_RTT_CANON(type_index), kExprEnd}); {WASM_RTT_CANON(type_index), kExprEnd});
tester.DefineFunction( tester.DefineFunction(
"g", &sig_t2_v, {}, "g", &sig_t2_v, {},
{WASM_RTT_CANON(type_index), WASM_RTT_SUB(subtype_index), kExprEnd}); {WASM_RTT_CANON(type_index), WASM_RTT_SUB(subtype_index), kExprEnd});
tester.DefineFunction("h", &sig_q_v, {},
{WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
WASM_RTT_CANON(type_index)),
kExprEnd});
tester.CompileModule(); tester.CompileModule();
...@@ -580,6 +587,10 @@ TEST(BasicRTT) { ...@@ -580,6 +587,10 @@ TEST(BasicRTT) {
CHECK_EQ(reinterpret_cast<Address>( CHECK_EQ(reinterpret_cast<Address>(
tester.instance()->module()->struct_type(subtype_index)), tester.instance()->module()->struct_type(subtype_index)),
submap->wasm_type_info().foreign_address()); submap->wasm_type_info().foreign_address());
Handle<Object> s = tester.GetJSResult("h", {}).ToHandleChecked();
CHECK(s->IsWasmStruct());
CHECK_EQ(Handle<WasmStruct>::cast(s)->map(), *map);
} }
TEST(BasicI31) { TEST(BasicI31) {
......
...@@ -426,6 +426,8 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -426,6 +426,8 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define WASM_GC_OP(op) kGCPrefix, static_cast<byte>(op) #define WASM_GC_OP(op) kGCPrefix, static_cast<byte>(op)
#define WASM_STRUCT_NEW(index, ...) \ #define WASM_STRUCT_NEW(index, ...) \
__VA_ARGS__, WASM_GC_OP(kExprStructNew), static_cast<byte>(index) __VA_ARGS__, WASM_GC_OP(kExprStructNew), static_cast<byte>(index)
#define WASM_STRUCT_NEW_WITH_RTT(index, ...) \
__VA_ARGS__, WASM_GC_OP(kExprStructNewWithRtt), static_cast<byte>(index)
#define WASM_STRUCT_GET(typeidx, fieldidx, struct_obj) \ #define WASM_STRUCT_GET(typeidx, fieldidx, struct_obj) \
struct_obj, WASM_GC_OP(kExprStructGet), static_cast<byte>(typeidx), \ struct_obj, WASM_GC_OP(kExprStructGet), static_cast<byte>(typeidx), \
static_cast<byte>(fieldidx) static_cast<byte>(fieldidx)
......
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