[wasm-gc][cleanup] Remove array.new, struct.new

They have been replaced with {array,struct}.new_with_rtt.

Also, rework tests that used those instructions.

Bug: v8:7748
Change-Id: I2aaccb1958bf2b8d6cad4969abc612216856393d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2307318
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68961}
This commit is contained in:
Manos Koukoutos 2020-07-21 09:03:20 +00:00 committed by Commit Bot
parent cfebd19a3a
commit 0747681e41
13 changed files with 186 additions and 273 deletions

View File

@ -819,7 +819,6 @@ namespace internal {
ASM(WasmDebugBreak, Dummy) \
TFC(WasmFloat32ToNumber, WasmFloat32ToNumber) \
TFC(WasmFloat64ToNumber, WasmFloat64ToNumber) \
TFS(WasmAllocateArray, kMapIndex, kLength, kElementSize) \
TFS(WasmAllocateArrayWithRtt, kMap, kLength, kElementSize) \
TFC(WasmI32AtomicWait32, WasmI32AtomicWait32) \
TFC(WasmI64AtomicWait32, WasmI64AtomicWait32) \

View File

@ -114,30 +114,6 @@ TF_BUILTIN(WasmI64AtomicWait32, WasmBuiltinsAssembler) {
Return(Unsigned(SmiToInt32(result_smi)));
}
TF_BUILTIN(WasmAllocateArray, WasmBuiltinsAssembler) {
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
TNode<Smi> map_index = CAST(Parameter(Descriptor::kMapIndex));
TNode<Smi> length = CAST(Parameter(Descriptor::kLength));
TNode<Smi> element_size = CAST(Parameter(Descriptor::kElementSize));
TNode<FixedArray> maps_list = LoadObjectField<FixedArray>(
instance, WasmInstanceObject::kManagedObjectMapsOffset);
TNode<Map> map = CAST(LoadFixedArrayElement(maps_list, map_index));
TNode<IntPtrT> untagged_length = SmiUntag(length);
// instance_size = WasmArray::kHeaderSize
// + RoundUp(element_size * length, kObjectAlignment)
TNode<IntPtrT> raw_size = IntPtrMul(SmiUntag(element_size), untagged_length);
TNode<IntPtrT> rounded_size =
WordAnd(IntPtrAdd(raw_size, IntPtrConstant(kObjectAlignmentMask)),
IntPtrConstant(~kObjectAlignmentMask));
TNode<IntPtrT> instance_size =
IntPtrAdd(IntPtrConstant(WasmArray::kHeaderSize), rounded_size);
TNode<WasmArray> result = UncheckedCast<WasmArray>(Allocate(instance_size));
StoreMap(result, map);
StoreObjectFieldNoWriteBarrier(result, WasmArray::kLengthOffset,
TruncateIntPtrToInt32(untagged_length));
Return(result);
}
TF_BUILTIN(WasmAllocateArrayWithRtt, WasmBuiltinsAssembler) {
TNode<Map> map = CAST(Parameter(Descriptor::kMap));
TNode<Smi> length = CAST(Parameter(Descriptor::kLength));

View File

@ -225,18 +225,6 @@ builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray {
return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size);
}
builtin WasmAllocateStruct(implicit context: Context)(mapIndex: Smi):
HeapObject {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const maps: FixedArray = LoadManagedObjectMapsFromInstance(instance);
const map: Map = %RawDownCast<Map>(LoadFixedArrayElement(maps, mapIndex));
const instanceSize: intptr =
unsafe::TimesTaggedSize(Convert<intptr>(map.instance_size_in_words));
const result: HeapObject = unsafe::Allocate(instanceSize);
*UnsafeConstCast(&result.map) = map;
return result;
}
builtin WasmAllocateRtt(implicit context: Context)(
typeIndex: Smi, parent: Map): Map {
tail runtime::WasmAllocateRtt(context, typeIndex, parent);

View File

@ -5243,7 +5243,7 @@ Node* StoreWithTaggedAlignment(WasmGraphAssembler* gasm, Node* base,
}
// Set a field of a struct, without checking if the struct is null.
// Helper method for StructNew and StructSet.
// Helper method for StructNewWithRtt and StructSet.
Node* StoreStructFieldUnchecked(MachineGraph* graph, WasmGraphAssembler* gasm,
Node* struct_object,
const wasm::StructType* type,
@ -5269,20 +5269,6 @@ Node* ArrayLength(GraphAssembler* gasm, Node* array) {
} // namespace
Node* WasmGraphBuilder::StructNew(uint32_t struct_index,
const wasm::StructType* type,
Vector<Node*> fields) {
int map_index = wasm::GetCanonicalRttIndex(env_->module, struct_index);
Node* s = CALL_BUILTIN(
WasmAllocateStruct,
graph()->NewNode(mcgraph()->common()->NumberConstant(map_index)),
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::StructNewWithRtt(uint32_t struct_index,
const wasm::StructType* type,
Node* rtt, Vector<Node*> fields) {
@ -5295,46 +5281,6 @@ Node* WasmGraphBuilder::StructNewWithRtt(uint32_t struct_index,
return s;
}
Node* WasmGraphBuilder::ArrayNew(uint32_t array_index,
const wasm::ArrayType* type, Node* length,
Node* initial_value) {
int map_index = GetCanonicalRttIndex(env_->module, array_index);
wasm::ValueType element_type = type->element_type();
Node* a = CALL_BUILTIN(
WasmAllocateArray,
graph()->NewNode(mcgraph()->common()->NumberConstant(map_index)),
BuildChangeUint31ToSmi(length),
graph()->NewNode(mcgraph()->common()->NumberConstant(
element_type.element_size_bytes())),
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
auto loop = gasm_->MakeLoopLabel(MachineRepresentation::kWord32);
auto done = gasm_->MakeLabel();
Node* start_offset =
gasm_->Int32Constant(WasmArray::kHeaderSize - kHeapObjectTag);
Node* element_size = gasm_->Int32Constant(element_type.element_size_bytes());
Node* end_offset =
gasm_->Int32Add(start_offset, gasm_->Int32Mul(element_size, length));
// "Goto" requires the graph's end to have been set up.
// TODO(jkummerow): Figure out if there's a more elegant solution.
Graph* g = mcgraph()->graph();
if (!g->end()) {
g->SetEnd(g->NewNode(mcgraph()->common()->End(0)));
}
gasm_->Goto(&loop, start_offset);
gasm_->Bind(&loop);
{
Node* offset = loop.PhiAt(0);
Node* check = gasm_->Uint32LessThan(offset, end_offset);
gasm_->GotoIfNot(check, &done);
StoreWithTaggedAlignment(gasm_.get(), a, offset, initial_value,
type->element_type());
offset = gasm_->Int32Add(offset, element_size);
gasm_->Goto(&loop, offset);
}
gasm_->Bind(&done);
return a;
}
Node* WasmGraphBuilder::ArrayNewWithRtt(uint32_t array_index,
const wasm::ArrayType* type,
Node* length, Node* initial_value,

View File

@ -390,8 +390,6 @@ class WasmGraphBuilder {
Node* TableSize(uint32_t table_index);
Node* TableFill(uint32_t table_index, Node* start, Node* value, Node* count);
Node* StructNew(uint32_t struct_index, const wasm::StructType* type,
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,
@ -400,8 +398,6 @@ class WasmGraphBuilder {
Node* StructSet(Node* struct_object, const wasm::StructType* struct_type,
uint32_t field_index, Node* value, CheckForNull null_check,
wasm::WasmCodePosition position);
Node* ArrayNew(uint32_t array_index, const wasm::ArrayType* type,
Node* length, Node* initial_value);
Node* ArrayNewWithRtt(uint32_t array_index, const wasm::ArrayType* type,
Node* length, Node* initial_value, Node* rtt);
void BoundsCheck(Node* array, Node* index, wasm::WasmCodePosition position);

View File

@ -3587,12 +3587,6 @@ class LiftoffCompiler {
unsupported(decoder, kRefTypes, "table.fill");
}
void StructNew(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm, const Value args[],
Value* result) {
// TODO(7748): Implement.
unsupported(decoder, kGC, "struct.new");
}
void StructNewWithRtt(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm,
const Value& rtt, const Value args[], Value* result) {
@ -3612,12 +3606,6 @@ class LiftoffCompiler {
unsupported(decoder, kGC, "struct.set");
}
void ArrayNew(FullDecoder* decoder, const ArrayIndexImmediate<validate>& imm,
const Value& length, const Value& initial_value,
Value* result) {
// TODO(7748): Implement.
unsupported(decoder, kGC, "array.new");
}
void ArrayNewWithRtt(FullDecoder* decoder,
const ArrayIndexImmediate<validate>& imm,
const Value& length, const Value& initial_value,

View File

@ -944,16 +944,12 @@ struct ControlBase {
F(TableSize, const TableIndexImmediate<validate>& imm, Value* result) \
F(TableFill, const TableIndexImmediate<validate>& imm, const Value& start, \
const Value& value, const Value& count) \
F(StructNew, const StructIndexImmediate<validate>& imm, const Value args[], \
Value* result) \
F(StructNewWithRtt, const StructIndexImmediate<validate>& imm, \
const Value& rtt, const Value args[], Value* result) \
F(StructGet, const Value& struct_object, \
const FieldIndexImmediate<validate>& field, bool is_signed, Value* result) \
F(StructSet, const Value& struct_object, \
const FieldIndexImmediate<validate>& field, const Value& field_value) \
F(ArrayNew, const ArrayIndexImmediate<validate>& imm, const Value& length, \
const Value& initial_value, Value* result) \
F(ArrayNewWithRtt, const ArrayIndexImmediate<validate>& imm, \
const Value& length, const Value& initial_value, const Value& rtt, \
Value* result) \
@ -1670,7 +1666,6 @@ class WasmDecoder : public Decoder {
byte gc_index = decoder->read_u8<validate>(pc + 1, "gc_index");
WasmOpcode opcode = static_cast<WasmOpcode>(kGCPrefix << 8 | gc_index);
switch (opcode) {
case kExprStructNew:
case kExprStructNewWithRtt:
case kExprStructNewDefault: {
StructIndexImmediate<validate> imm(decoder, pc + 2);
@ -1683,7 +1678,6 @@ class WasmDecoder : public Decoder {
FieldIndexImmediate<validate> imm(decoder, pc + 2);
return 2 + imm.length;
}
case kExprArrayNew:
case kExprArrayNewWithRtt:
case kExprArrayNewDefault:
case kExprArrayGet:
@ -1845,7 +1839,6 @@ class WasmDecoder : public Decoder {
return {1, 1};
case kExprStructSet:
return {2, 0};
case kExprArrayNew:
case kExprArrayGet:
case kExprArrayGetS:
case kExprArrayGetU:
@ -1859,11 +1852,6 @@ class WasmDecoder : public Decoder {
return {0, 1};
case kExprArrayNewWithRtt:
return {3, 1};
case kExprStructNew: {
StructIndexImmediate<validate> imm(this, this->pc_ + 2);
this->Complete(imm);
return {imm.struct_type->field_count(), 1};
}
case kExprStructNewWithRtt: {
StructIndexImmediate<validate> imm(this, this->pc_ + 2);
this->Complete(imm);
@ -3381,14 +3369,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
int DecodeGCOpcode(WasmOpcode opcode) {
switch (opcode) {
case kExprStructNew: {
StructIndexImmediate<validate> imm(this, this->pc_ + 2);
if (!this->Validate(this->pc_ + 2, imm)) return 0;
ArgVector args = PopArgs(imm.struct_type);
Value* value = Push(ValueType::Ref(imm.index, kNonNullable));
CALL_INTERFACE_IF_REACHABLE(StructNew, imm, args.begin(), value);
return 2 + imm.length;
}
case kExprStructNewWithRtt: {
StructIndexImmediate<validate> imm(this, this->pc_ + 2);
if (!this->Validate(this->pc_, imm)) return 0;
@ -3466,16 +3446,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE_IF_REACHABLE(StructSet, struct_obj, field, field_value);
return 2 + field.length;
}
case kExprArrayNew: {
ArrayIndexImmediate<validate> imm(this, this->pc_ + 2);
if (!this->Validate(this->pc_ + 2, imm)) return 0;
Value length = Pop(1, kWasmI32);
Value initial_value = Pop(0, imm.array_type->element_type().Unpacked());
Value* value = Push(ValueType::Ref(imm.index, kNonNullable));
CALL_INTERFACE_IF_REACHABLE(ArrayNew, imm, length, initial_value,
value);
return 2 + imm.length;
}
case kExprArrayNewWithRtt: {
ArrayIndexImmediate<validate> imm(this, this->pc_ + 2);
if (!this->Validate(this->pc_ + 2, imm)) return 0;

View File

@ -646,18 +646,6 @@ class WasmGraphBuildingInterface {
BUILD(TableFill, imm.index, start.node, value.node, count.node);
}
void StructNew(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm, 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(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) {
@ -693,13 +681,6 @@ class WasmGraphBuildingInterface {
field.index, field_value.node, null_check, decoder->position());
}
void ArrayNew(FullDecoder* decoder, const ArrayIndexImmediate<validate>& imm,
const Value& length, const Value& initial_value,
Value* result) {
result->node = BUILD(ArrayNew, imm.index, imm.array_type, length.node,
initial_value.node);
}
void ArrayNewWithRtt(FullDecoder* decoder,
const ArrayIndexImmediate<validate>& imm,
const Value& length, const Value& initial_value,

View File

@ -355,14 +355,12 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_UNSIGNED_ALL_OP(AtomicCompareExchange, "atomic.cmpxchng")
// GC operations.
CASE_OP(StructNew, "struct.new")
CASE_OP(StructNewWithRtt, "struct.new_with_rtt")
CASE_OP(StructNewDefault, "struct.new_default")
CASE_OP(StructGet, "struct.get")
CASE_OP(StructGetS, "struct.get_s")
CASE_OP(StructGetU, "struct.get_u")
CASE_OP(StructSet, "struct.set")
CASE_OP(ArrayNew, "array.new")
CASE_OP(ArrayNewWithRtt, "array.new_with_rtt")
CASE_OP(ArrayNewDefault, "array.new_default")
CASE_OP(ArrayGet, "array.get")

View File

@ -601,14 +601,12 @@ bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmFeatures&);
V(I64AtomicCompareExchange32U, 0xfe4e, l_ill)
#define FOREACH_GC_OPCODE(V) \
V(StructNew, 0xfb00, _) \
V(StructNewWithRtt, 0xfb01, _) \
V(StructNewDefault, 0xfb02, _) \
V(StructGet, 0xfb03, _) \
V(StructGetS, 0xfb04, _) \
V(StructGetU, 0xfb05, _) \
V(StructSet, 0xfb06, _) \
V(ArrayNew, 0xfb10, _) \
V(ArrayNewWithRtt, 0xfb11, _) \
V(ArrayNewDefault, 0xfb12, _) \
V(ArrayGet, 0xfb13, _) \

View File

@ -172,7 +172,8 @@ TEST(WasmBasicStruct) {
tester.sigs.i_v(), {},
{WASM_STRUCT_GET(
type_index, 0,
WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64))),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
WASM_RTT_CANON(type_index))),
kExprEnd});
// Test struct.new and struct.get.
@ -180,21 +181,26 @@ TEST(WasmBasicStruct) {
tester.sigs.i_v(), {},
{WASM_STRUCT_GET(
type_index, 1,
WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64))),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
WASM_RTT_CANON(type_index))),
kExprEnd});
// Test struct.new, returning struct reference.
const uint32_t kGetStruct = tester.DefineFunction(
&sig_q_v, {},
{WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64)), kExprEnd});
{WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
WASM_RTT_CANON(type_index)),
kExprEnd});
// Test struct.set, struct refs types in locals.
uint32_t j_local_index = 0;
uint32_t j_field_index = 0;
const uint32_t kSet = tester.DefineFunction(
tester.sigs.i_v(), {kOptRefType},
{WASM_SET_LOCAL(j_local_index, WASM_STRUCT_NEW(type_index, WASM_I32V(42),
WASM_I32V(64))),
{WASM_SET_LOCAL(
j_local_index,
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_SET(type_index, j_field_index, WASM_GET_LOCAL(j_local_index),
WASM_I32V(-99)),
WASM_STRUCT_GET(type_index, j_field_index,
@ -226,8 +232,10 @@ TEST(WasmRefAsNonNull) {
uint32_t field_index = 0;
const uint32_t kFunc = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_SET_GLOBAL(global_index, WASM_STRUCT_NEW(type_index, WASM_I32V(55),
WASM_I32V(66))),
{WASM_SET_GLOBAL(
global_index,
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(55), WASM_I32V(66),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_GET(
type_index, field_index,
WASM_REF_AS_NON_NULL(WASM_IF_ELSE_R(
@ -265,8 +273,9 @@ TEST(WasmBrOnNull) {
type_index, m_field_index,
// Branch will not be taken.
// 52 left on stack outside the block (not 42).
WASM_BR_ON_NULL(0, WASM_STRUCT_NEW(type_index, WASM_I32V(52),
WASM_I32V(62)))),
WASM_BR_ON_NULL(0, WASM_STRUCT_NEW_WITH_RTT(
type_index, WASM_I32V(52), WASM_I32V(62),
WASM_RTT_CANON(type_index)))),
WASM_BR(0)),
kExprEnd});
@ -286,8 +295,9 @@ TEST(WasmRefEq) {
byte local_index = 0;
const uint32_t kFunc = tester.DefineFunction(
tester.sigs.i_v(), {kOptRefType},
{WASM_SET_LOCAL(local_index, WASM_STRUCT_NEW(type_index, WASM_I32V(55),
WASM_I32V(66))),
{WASM_SET_LOCAL(local_index, WASM_STRUCT_NEW_WITH_RTT(
type_index, WASM_I32V(55), WASM_I32V(66),
WASM_RTT_CANON(type_index))),
WASM_I32_ADD(
WASM_I32_SHL(
WASM_REF_EQ( // true
@ -296,8 +306,9 @@ TEST(WasmRefEq) {
WASM_I32_ADD(
WASM_I32_SHL(WASM_REF_EQ( // false
WASM_GET_LOCAL(local_index),
WASM_STRUCT_NEW(type_index, WASM_I32V(55),
WASM_I32V(66))),
WASM_STRUCT_NEW_WITH_RTT(
type_index, WASM_I32V(55), WASM_I32V(66),
WASM_RTT_CANON(type_index))),
WASM_I32V(1)),
WASM_I32_ADD(WASM_I32_SHL( // false
WASM_REF_EQ(WASM_GET_LOCAL(local_index),
@ -328,18 +339,20 @@ TEST(WasmPackedStructU) {
const uint32_t kF0 = tester.DefineFunction(
tester.sigs.i_v(), {struct_type},
{WASM_SET_LOCAL(local_index,
WASM_STRUCT_NEW(type_index, WASM_I32V(expected_output_0),
WASM_I32V(expected_output_1),
WASM_I32V(0x12345678))),
WASM_STRUCT_NEW_WITH_RTT(
type_index, WASM_I32V(expected_output_0),
WASM_I32V(expected_output_1), WASM_I32V(0x12345678),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_GET_U(type_index, 0, WASM_GET_LOCAL(local_index)),
kExprEnd});
const uint32_t kF1 = tester.DefineFunction(
tester.sigs.i_v(), {struct_type},
{WASM_SET_LOCAL(local_index,
WASM_STRUCT_NEW(type_index, WASM_I32V(expected_output_0),
WASM_I32V(expected_output_1),
WASM_I32V(0x12345678))),
WASM_STRUCT_NEW_WITH_RTT(
type_index, WASM_I32V(expected_output_0),
WASM_I32V(expected_output_1), WASM_I32V(0x12345678),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_GET_U(type_index, 1, WASM_GET_LOCAL(local_index)),
kExprEnd});
tester.CompileModule();
@ -364,16 +377,19 @@ TEST(WasmPackedStructS) {
tester.sigs.i_v(), {struct_type},
{WASM_SET_LOCAL(
local_index,
WASM_STRUCT_NEW(type_index, WASM_I32V(expected_output_0),
WASM_I32V(expected_output_1), WASM_I32V(0))),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(expected_output_0),
WASM_I32V(expected_output_1), WASM_I32V(0),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_GET_S(type_index, 0, WASM_GET_LOCAL(local_index)),
kExprEnd});
const uint32_t kF1 = tester.DefineFunction(
tester.sigs.i_v(), {struct_type},
{WASM_SET_LOCAL(local_index, WASM_STRUCT_NEW(type_index, WASM_I32V(0x80),
WASM_I32V(expected_output_1),
WASM_I32V(0))),
{WASM_SET_LOCAL(
local_index,
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(0x80),
WASM_I32V(expected_output_1), WASM_I32V(0),
WASM_RTT_CANON(type_index))),
WASM_STRUCT_GET_S(type_index, 1, WASM_GET_LOCAL(local_index)),
kExprEnd});
@ -392,21 +408,25 @@ TEST(WasmLetInstruction) {
uint32_t let_field_index = 0;
const uint32_t kLetTest1 = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_LET_1_I(WASM_SEQ(kLocalRef, static_cast<byte>(type_index)),
WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(52)),
WASM_STRUCT_GET(type_index, let_field_index,
WASM_GET_LOCAL(let_local_index))),
{WASM_LET_1_I(
WASM_SEQ(kLocalRef, static_cast<byte>(type_index)),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(52),
WASM_RTT_CANON(type_index)),
WASM_STRUCT_GET(type_index, let_field_index,
WASM_GET_LOCAL(let_local_index))),
kExprEnd});
uint32_t let_2_field_index = 0;
const uint32_t kLetTest2 = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_LET_2_I(kLocalI32, WASM_I32_ADD(WASM_I32V(42), WASM_I32V(-32)),
WASM_SEQ(kLocalRef, static_cast<byte>(type_index)),
WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(52)),
WASM_I32_MUL(WASM_STRUCT_GET(type_index, let_2_field_index,
WASM_GET_LOCAL(1)),
WASM_GET_LOCAL(0))),
{WASM_LET_2_I(
kLocalI32, WASM_I32_ADD(WASM_I32V(42), WASM_I32V(-32)),
WASM_SEQ(kLocalRef, static_cast<byte>(type_index)),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(52),
WASM_RTT_CANON(type_index)),
WASM_I32_MUL(WASM_STRUCT_GET(type_index, let_2_field_index,
WASM_GET_LOCAL(1)),
WASM_GET_LOCAL(0))),
kExprEnd});
const uint32_t kLetTestLocals = tester.DefineFunction(
@ -449,8 +469,9 @@ TEST(WasmBasicArray) {
uint32_t local_index = 1;
const uint32_t kGetElem = tester.DefineFunction(
tester.sigs.i_i(), {kOptRefType},
{WASM_SET_LOCAL(local_index,
WASM_ARRAY_NEW(type_index, WASM_I32V(12), WASM_I32V(3))),
{WASM_SET_LOCAL(local_index, WASM_ARRAY_NEW_WITH_RTT(
type_index, WASM_I32V(12), WASM_I32V(3),
WASM_RTT_CANON(type_index))),
WASM_ARRAY_SET(type_index, WASM_GET_LOCAL(local_index), WASM_I32V(1),
WASM_I32V(42)),
WASM_ARRAY_GET(type_index, WASM_GET_LOCAL(local_index),
@ -460,14 +481,17 @@ TEST(WasmBasicArray) {
// Reads and returns an array's length.
const uint32_t kGetLength = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_ARRAY_LEN(type_index,
WASM_ARRAY_NEW(type_index, WASM_I32V(0), WASM_I32V(42))),
{WASM_ARRAY_LEN(type_index, WASM_ARRAY_NEW_WITH_RTT(
type_index, WASM_I32V(0), WASM_I32V(42),
WASM_RTT_CANON(type_index))),
kExprEnd});
// Create an array of length 2, initialized to [42, 42].
const uint32_t kAllocate = tester.DefineFunction(
&sig_q_v, {},
{WASM_ARRAY_NEW(type_index, WASM_I32V(42), WASM_I32V(2)), kExprEnd});
{WASM_ARRAY_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(2),
WASM_RTT_CANON(type_index)),
kExprEnd});
tester.CompileModule();
@ -497,8 +521,9 @@ TEST(WasmPackedArrayU) {
const uint32_t kF = tester.DefineFunction(
tester.sigs.i_i(), {array_type},
{WASM_SET_LOCAL(local_index,
WASM_ARRAY_NEW(array_index, WASM_I32V(0), WASM_I32V(4))),
{WASM_SET_LOCAL(local_index, WASM_ARRAY_NEW_WITH_RTT(
array_index, WASM_I32V(0), WASM_I32V(4),
WASM_RTT_CANON(array_index))),
WASM_ARRAY_SET(array_index, WASM_GET_LOCAL(local_index), WASM_I32V(0),
WASM_I32V(1)),
WASM_ARRAY_SET(array_index, WASM_GET_LOCAL(local_index), WASM_I32V(1),
@ -532,7 +557,8 @@ TEST(WasmPackedArrayS) {
tester.sigs.i_i(), {array_type},
{WASM_SET_LOCAL(
local_index,
WASM_ARRAY_NEW(array_index, WASM_I32V(0x12345678), WASM_I32V(4))),
WASM_ARRAY_NEW_WITH_RTT(array_index, WASM_I32V(0x12345678),
WASM_I32V(4), WASM_RTT_CANON(array_index))),
WASM_ARRAY_SET(array_index, WASM_GET_LOCAL(local_index), WASM_I32V(1),
WASM_I32V(10)),
WASM_ARRAY_SET(array_index, WASM_GET_LOCAL(local_index), WASM_I32V(2),
@ -649,7 +675,7 @@ TEST(BasicRTT) {
tester.CheckResult(kRefCast, 43);
}
TEST(ArrayNewWithRtt) {
TEST(ArrayNewMap) {
WasmGCTester tester;
uint32_t type_index = tester.DefineArray(kWasmI32, true);
@ -784,7 +810,9 @@ TEST(JsAccessDisallowed) {
FunctionSig sig_q_v(1, 0, kRefTypes);
WasmFunctionBuilder* fun = tester.builder()->AddFunction(&sig_q_v);
byte code[] = {WASM_STRUCT_NEW(type_index, WASM_I32V(42)), kExprEnd};
byte code[] = {WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
WASM_RTT_CANON(type_index)),
kExprEnd};
fun->EmitCode(code, sizeof(code));
tester.builder()->AddExport(CStrVector("f"), fun);
tester.CompileModule();

View File

@ -428,8 +428,6 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
// Heap-allocated object operations.
//------------------------------------------------------------------------------
#define WASM_GC_OP(op) kGCPrefix, static_cast<byte>(op)
#define WASM_STRUCT_NEW(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) \
@ -456,8 +454,6 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
ref, rtt, WASM_GC_OP(kExprRefCast), static_cast<byte>(obj_type), \
static_cast<byte>(rtt_type)
#define WASM_ARRAY_NEW(index, default_value, length) \
default_value, length, WASM_GC_OP(kExprArrayNew), static_cast<byte>(index)
#define WASM_ARRAY_NEW_WITH_RTT(index, default_value, length, rtt) \
default_value, length, rtt, WASM_GC_OP(kExprArrayNewWithRtt), \
static_cast<byte>(index)

View File

@ -3363,26 +3363,30 @@ TEST_F(FunctionBodyDecoderTest, TableInitMultiTable) {
TEST_F(FunctionBodyDecoderTest, UnpackPackedTypes) {
WASM_FEATURE_SCOPE(reftypes);
WASM_FEATURE_SCOPE(typed_funcref);
WASM_FEATURE_SCOPE(gc);
{
TestModuleBuilder builder;
byte type_index = builder.AddStruct({F(kWasmI8, true), F(kWasmI16, false)});
module = builder.module();
ExpectValidates(sigs.v_v(),
{WASM_STRUCT_SET(type_index, 0,
WASM_STRUCT_NEW(type_index, WASM_I32V(1),
WASM_I32V(42)),
WASM_I32V(-1))});
ExpectValidates(
sigs.v_v(),
{WASM_STRUCT_SET(
type_index, 0,
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(1), WASM_I32V(42),
WASM_RTT_CANON(type_index)),
WASM_I32V(-1))});
}
{
TestModuleBuilder builder;
byte type_index = builder.AddArray(kWasmI8, true);
module = builder.module();
ExpectValidates(
sigs.v_v(),
{WASM_ARRAY_SET(type_index,
WASM_ARRAY_NEW(type_index, WASM_I32V(10), WASM_I32V(5)),
WASM_I32V(3), WASM_I32V(12345678))});
ExpectValidates(sigs.v_v(),
{WASM_ARRAY_SET(type_index,
WASM_ARRAY_NEW_WITH_RTT(
type_index, WASM_I32V(10), WASM_I32V(5),
WASM_RTT_CANON(type_index)),
WASM_I32V(3), WASM_I32V(12345678))});
}
}
@ -3610,29 +3614,50 @@ TEST_F(FunctionBodyDecoderTest, GCStruct) {
const FunctionSig sig_r_v(1, 0, &struct_type);
const FunctionSig sig_f_r(1, 1, reps_f_r);
/** struct.new **/
ExpectValidates(&sig_r_v, {WASM_STRUCT_NEW(struct_type_index, WASM_I32V(0))});
/** struct.new_with_rtt **/
ExpectValidates(
&sig_r_v, {WASM_STRUCT_NEW_WITH_RTT(struct_type_index, WASM_I32V(0),
WASM_RTT_CANON(struct_type_index))});
// Too few arguments.
ExpectFailure(
&sig_r_v, {WASM_GC_OP(kExprStructNew), struct_type_index}, kAppendEnd,
"not enough arguments on the stack for struct.new, expected 1 more");
ExpectFailure(&sig_r_v,
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index,
WASM_RTT_CANON(struct_type_index))},
kAppendEnd,
"not enough arguments on the stack for struct.new_with_rtt, "
"expected 1 more");
// Too many arguments.
ExpectFailure(
&sig_r_v,
{WASM_STRUCT_NEW(struct_type_index, WASM_I32V(0), WASM_I32V(1))},
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index, WASM_I32V(0), WASM_I32V(1),
WASM_RTT_CANON(struct_type_index))},
kAppendEnd,
"expected 1 elements on the stack for fallthru to @1, found 2");
// Mistyped arguments.
ExpectFailure(
&sig_v_r, {WASM_STRUCT_NEW(struct_type_index, WASM_GET_LOCAL(0))},
kAppendEnd,
"struct.new[0] expected type i32, found local.get of type (ref 0)");
ExpectFailure(&sig_v_r,
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index, WASM_GET_LOCAL(0),
WASM_RTT_CANON(struct_type_index))},
kAppendEnd,
"struct.new_with_rtt[0] expected type i32, found local.get of "
"type (ref 0)");
// Wrongly typed index.
ExpectFailure(sigs.v_v(),
{WASM_STRUCT_NEW(array_type_index, WASM_I32V(0)), kExprDrop},
{WASM_STRUCT_NEW_WITH_RTT(array_type_index, WASM_I32V(0),
WASM_RTT_CANON(struct_type_index)),
kExprDrop},
kAppendEnd, "invalid struct index: 1");
// Wrongly typed rtt.
ExpectFailure(
sigs.v_v(),
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index, WASM_I32V(0),
WASM_RTT_CANON(array_type_index)),
kExprDrop},
kAppendEnd,
"struct.new_with_rtt expected rtt for type 0, found rtt for type 1");
// Out-of-bounds index.
ExpectFailure(sigs.v_v(), {WASM_STRUCT_NEW(42, WASM_I32V(0)), kExprDrop},
ExpectFailure(sigs.v_v(),
{WASM_STRUCT_NEW_WITH_RTT(42, WASM_I32V(0),
WASM_RTT_CANON(struct_type_index)),
kExprDrop},
kAppendEnd, "invalid struct index: 42");
/** struct.get **/
@ -3680,12 +3705,14 @@ TEST_F(FunctionBodyDecoderTest, GCStruct) {
kAppendEnd,
"expected 1 elements on the stack for fallthru to @1, found 0");
// Setting immutable field.
ExpectFailure(sigs.v_v(),
{WASM_STRUCT_SET(
immutable_struct_type_index, field_index,
WASM_STRUCT_NEW(immutable_struct_type_index, WASM_I32V(42)),
WASM_I32V(0))},
kAppendEnd, "setting immutable struct field");
ExpectFailure(
sigs.v_v(),
{WASM_STRUCT_SET(
immutable_struct_type_index, field_index,
WASM_STRUCT_NEW_WITH_RTT(immutable_struct_type_index, WASM_I32V(42),
WASM_RTT_CANON(immutable_struct_type_index)),
WASM_I32V(0))},
kAppendEnd, "setting immutable struct field");
// struct.get_s/u fail
ExpectFailure(
@ -3702,7 +3729,7 @@ TEST_F(FunctionBodyDecoderTest, GCStruct) {
"instead.");
}
TEST_F(FunctionBodyDecoderTest, GCArray1) {
TEST_F(FunctionBodyDecoderTest, GCArray) {
WASM_FEATURE_SCOPE(reftypes);
WASM_FEATURE_SCOPE(typed_funcref);
WASM_FEATURE_SCOPE(gc);
@ -3723,34 +3750,48 @@ TEST_F(FunctionBodyDecoderTest, GCArray1) {
const FunctionSig sig_v_cr(0, 2, reps_c_r);
const FunctionSig sig_i_r(1, 1, reps_i_r);
/** array.new **/
ExpectValidates(
&sig_r_v, {WASM_ARRAY_NEW(array_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I32V(10))});
/** array.new_with_rtt **/
ExpectValidates(&sig_r_v,
{WASM_ARRAY_NEW_WITH_RTT(
array_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I32V(10), WASM_RTT_CANON(array_type_index))});
// Too few arguments.
ExpectFailure(
&sig_r_v, {WASM_I32V(10), WASM_GC_OP(kExprArrayNew), array_type_index},
kAppendEnd,
"not enough arguments on the stack for array.new, expected 1 more");
ExpectFailure(&sig_r_v,
{WASM_I32V(10), WASM_RTT_CANON(array_type_index),
WASM_GC_OP(kExprArrayNewWithRtt), array_type_index},
kAppendEnd,
"not enough arguments on the stack for array.new_with_rtt, "
"expected 1 more");
// Mistyped initializer.
ExpectFailure(&sig_r_v,
{WASM_ARRAY_NEW_WITH_RTT(
array_type_index, WASM_REF_NULL(kLocalExternRef),
WASM_I32V(10), WASM_RTT_CANON(array_type_index))},
kAppendEnd,
"array.new_with_rtt[0] expected type funcref, found ref.null "
"of type externref");
// Mistyped length.
ExpectFailure(
&sig_r_v,
{WASM_ARRAY_NEW(array_type_index, WASM_REF_NULL(kLocalExternRef),
WASM_I32V(10))},
{WASM_ARRAY_NEW_WITH_RTT(array_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I64V(5), WASM_RTT_CANON(array_type_index))},
kAppendEnd,
"array.new[0] expected type funcref, found ref.null of type externref");
// Mistyped length.
ExpectFailure(&sig_r_v,
{WASM_ARRAY_NEW(array_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I64V(5))},
kAppendEnd,
"array.new[1] expected type i32, found i64.const of type i64");
"array.new_with_rtt[1] expected type i32, found i64.const of type i64");
// Mistyped rtt.
ExpectFailure(
&sig_r_v,
{WASM_ARRAY_NEW_WITH_RTT(array_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I32V(5),
WASM_RTT_CANON(struct_type_index))},
kAppendEnd,
"array.new_with_rtt expected rtt for type 0, found rtt for type 1");
// Wrong type index.
ExpectFailure(sigs.v_v(),
{WASM_ARRAY_NEW(struct_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I32V(10)),
kExprDrop},
kAppendEnd, "invalid array index: 1");
ExpectFailure(
sigs.v_v(),
{WASM_ARRAY_NEW_WITH_RTT(struct_type_index, WASM_REF_NULL(kLocalFuncRef),
WASM_I32V(10), WASM_RTT_CANON(array_type_index)),
kExprDrop},
kAppendEnd, "invalid array index: 1");
/** array.get **/
ExpectValidates(&sig_c_r, {WASM_ARRAY_GET(array_type_index, WASM_GET_LOCAL(0),
@ -3837,22 +3878,29 @@ TEST_F(FunctionBodyDecoderTest, PackedFields) {
byte field_index = 0;
// *.new with packed fields works.
ExpectValidates(sigs.v_v(), {WASM_ARRAY_NEW_WITH_RTT(
array_type_index, WASM_I32V(0), WASM_I32V(5),
WASM_RTT_CANON(array_type_index)),
kExprDrop});
ExpectValidates(sigs.v_v(),
{WASM_ARRAY_NEW(array_type_index, WASM_I32V(0), WASM_I32V(5)),
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index, WASM_I32V(42),
WASM_RTT_CANON(struct_type_index)),
kExprDrop});
ExpectValidates(
sigs.v_v(),
{WASM_STRUCT_NEW(struct_type_index, WASM_I32V(42)), kExprDrop});
// It can't unpack types other that i32.
ExpectFailure(
sigs.v_v(),
{WASM_ARRAY_NEW(array_type_index, WASM_I64V(0), WASM_I32V(5)), kExprDrop},
{WASM_ARRAY_NEW_WITH_RTT(array_type_index, WASM_I64V(0), WASM_I32V(5),
WASM_RTT_CANON(array_type_index)),
kExprDrop},
kAppendEnd,
"array.new[0] expected type i32, found i64.const of type i64");
ExpectFailure(sigs.v_v(),
{WASM_STRUCT_NEW(struct_type_index, WASM_I64V(42)), kExprDrop},
kAppendEnd,
"struct.new[0] expected type i32, found i64.const of type i64");
"array.new_with_rtt[0] expected type i32, found i64.const of type i64");
ExpectFailure(
sigs.v_v(),
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index, WASM_I64V(42),
WASM_RTT_CANON(struct_type_index)),
kExprDrop},
kAppendEnd,
"struct.new_with_rtt[0] expected type i32, found i64.const of type i64");
// *.set with packed fields works.
ExpectValidates(sigs.v_v(), {WASM_ARRAY_SET(array_type_index,
@ -3870,10 +3918,11 @@ TEST_F(FunctionBodyDecoderTest, PackedFields) {
"array.set[2] expected type i32, found i64.const of type i64");
ExpectFailure(
sigs.v_v(),
{WASM_STRUCT_NEW(struct_type_index, field_index,
WASM_REF_NULL(struct_type_index), WASM_I64V(42))},
{WASM_STRUCT_NEW_WITH_RTT(struct_type_index, field_index,
WASM_REF_NULL(struct_type_index), WASM_I64V(42),
WASM_RTT_CANON(struct_type_index))},
kAppendEnd,
"struct.new[0] expected type i32, found i64.const of type i64");
"struct.new_with_rtt[0] expected type i32, found i64.const of type i64");
// *.get_s/u works.
ExpectValidates(sigs.i_v(), {WASM_ARRAY_GET_S(array_type_index,