From eee722cbf44a50735c3b1c153c7914436c8936fc Mon Sep 17 00:00:00 2001 From: Manos Koukoutos Date: Fri, 17 Sep 2021 14:45:06 +0000 Subject: [PATCH] [wasm-gc] Add struct.new_default* to constant expressions Bug: v8:7748 Change-Id: I5b6d8bf0b6dbf88c4762f4d61fb468c3e2898201 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3168621 Reviewed-by: Jakob Kummerow Commit-Queue: Manos Koukoutos Cr-Commit-Position: refs/heads/main@{#76927} --- src/wasm/function-body-decoder-impl.h | 5 ++- src/wasm/init-expr-interface.cc | 42 ++++++++++++++++++++++++ src/wasm/wasm-init-expr.cc | 2 ++ src/wasm/wasm-init-expr.h | 20 +++++++++++ src/wasm/wasm-module-builder.cc | 25 ++++++++++++-- test/mjsunit/wasm/reference-globals.js | 30 ++++++++++++++++- test/mjsunit/wasm/wasm-module-builder.js | 9 ++++- 7 files changed, 125 insertions(+), 8 deletions(-) diff --git a/src/wasm/function-body-decoder-impl.h b/src/wasm/function-body-decoder-impl.h index 0918ffeb5e..86816aa270 100644 --- a/src/wasm/function-body-decoder-impl.h +++ b/src/wasm/function-body-decoder-impl.h @@ -945,6 +945,8 @@ struct ControlBase : public PcForErrors { F(GlobalGet, Value* result, const GlobalIndexImmediate& imm) \ F(StructNewWithRtt, const StructIndexImmediate& imm, \ const Value& rtt, const Value args[], Value* result) \ + F(StructNewDefault, const StructIndexImmediate& imm, \ + const Value& rtt, Value* result) \ F(ArrayInit, const ArrayIndexImmediate& imm, \ const base::Vector& elements, const Value& rtt, Value* result) \ F(RttCanon, uint32_t type_index, Value* result) \ @@ -1047,8 +1049,6 @@ struct ControlBase : public PcForErrors { F(TableSize, const IndexImmediate& imm, Value* result) \ F(TableFill, const IndexImmediate& imm, const Value& start, \ const Value& value, const Value& count) \ - F(StructNewDefault, const StructIndexImmediate& imm, \ - const Value& rtt, Value* result) \ F(StructGet, const Value& struct_object, \ const FieldImmediate& field, bool is_signed, Value* result) \ F(StructSet, const Value& struct_object, \ @@ -4074,7 +4074,6 @@ class WasmFullDecoder : public WasmDecoder { } case kExprStructNewDefault: case kExprStructNewDefaultWithRtt: { - NON_CONST_ONLY StructIndexImmediate imm(this, this->pc_ + opcode_length); if (!this->Validate(this->pc_ + opcode_length, imm)) return 0; if (validate) { diff --git a/src/wasm/init-expr-interface.cc b/src/wasm/init-expr-interface.cc index 52c45bd18b..818145d095 100644 --- a/src/wasm/init-expr-interface.cc +++ b/src/wasm/init-expr-interface.cc @@ -89,6 +89,48 @@ void InitExprInterface::StructNewWithRtt( ValueType::Ref(HeapType(imm.index), kNonNullable)); } +namespace { +WasmValue DefaultValueForType(ValueType type, Isolate* isolate) { + switch (type.kind()) { + case kI32: + case kI8: + case kI16: + return WasmValue(0); + case kI64: + return WasmValue(int64_t{0}); + case kF32: + return WasmValue(0.0f); + case kF64: + return WasmValue(0.0); + case kS128: + return WasmValue(Simd128()); + case kOptRef: + return WasmValue(isolate->factory()->null_value(), type); + case kVoid: + case kRtt: + case kRttWithDepth: + case kRef: + case kBottom: + UNREACHABLE(); + } +} +} // namespace + +void InitExprInterface::StructNewDefault( + FullDecoder* decoder, const StructIndexImmediate& imm, + const Value& rtt, Value* result) { + if (isolate_ == nullptr) return; + std::vector field_values(imm.struct_type->field_count()); + for (uint32_t i = 0; i < field_values.size(); i++) { + field_values[i] = DefaultValueForType(imm.struct_type->field(i), isolate_); + } + result->runtime_value = + WasmValue(isolate_->factory()->NewWasmStruct( + imm.struct_type, field_values.data(), + Handle::cast(rtt.runtime_value.to_ref())), + ValueType::Ref(HeapType(imm.index), kNonNullable)); +} + void InitExprInterface::ArrayInit(FullDecoder* decoder, const ArrayIndexImmediate& imm, const base::Vector& elements, diff --git a/src/wasm/wasm-init-expr.cc b/src/wasm/wasm-init-expr.cc index ced4ad70b8..c6641034ba 100644 --- a/src/wasm/wasm-init-expr.cc +++ b/src/wasm/wasm-init-expr.cc @@ -40,6 +40,8 @@ ValueType WasmInitExpr::type(const WasmModule* module, return ValueType::Ref(immediate().heap_type, kNullable); case kStructNewWithRtt: case kStructNew: + case kStructNewDefaultWithRtt: + case kStructNewDefault: case kArrayInit: case kArrayInitStatic: return ValueType::Ref(immediate().index, kNonNullable); diff --git a/src/wasm/wasm-init-expr.h b/src/wasm/wasm-init-expr.h index 2a6b0813fe..551fce2991 100644 --- a/src/wasm/wasm-init-expr.h +++ b/src/wasm/wasm-init-expr.h @@ -35,6 +35,8 @@ class WasmInitExpr { kRefFuncConst, kStructNewWithRtt, kStructNew, + kStructNewDefaultWithRtt, + kStructNewDefault, kArrayInit, kArrayInitStatic, kRttCanon, @@ -110,6 +112,22 @@ class WasmInitExpr { return expr; } + static WasmInitExpr StructNewDefaultWithRtt(uint32_t index, + WasmInitExpr rtt) { + WasmInitExpr expr; + expr.kind_ = kStructNewDefaultWithRtt; + expr.immediate_.index = index; + expr.operands_.push_back(std::move(rtt)); + return expr; + } + + static WasmInitExpr StructNewDefault(uint32_t index) { + WasmInitExpr expr; + expr.kind_ = kStructNewDefault; + expr.immediate_.index = index; + return expr; + } + static WasmInitExpr ArrayInit(uint32_t index, std::vector elements) { WasmInitExpr expr; @@ -178,6 +196,8 @@ class WasmInitExpr { return immediate().heap_type == other.immediate().heap_type; case kStructNewWithRtt: case kStructNew: + case kStructNewDefaultWithRtt: + case kStructNewDefault: if (immediate().index != other.immediate().index) return false; DCHECK_EQ(operands().size(), other.operands().size()); for (uint32_t i = 0; i < operands().size(); i++) { diff --git a/src/wasm/wasm-module-builder.cc b/src/wasm/wasm-module-builder.cc index 421b7699d5..8e22b4d7a7 100644 --- a/src/wasm/wasm-module-builder.cc +++ b/src/wasm/wasm-module-builder.cc @@ -512,15 +512,34 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer, } case WasmInitExpr::kStructNew: case WasmInitExpr::kStructNewWithRtt: + case WasmInitExpr::kStructNewDefault: + case WasmInitExpr::kStructNewDefaultWithRtt: STATIC_ASSERT((kExprStructNew >> 8) == kGCPrefix); STATIC_ASSERT((kExprStructNewWithRtt >> 8) == kGCPrefix); + STATIC_ASSERT((kExprStructNewDefault >> 8) == kGCPrefix); + STATIC_ASSERT((kExprStructNewDefaultWithRtt >> 8) == kGCPrefix); for (const WasmInitExpr& operand : init.operands()) { WriteInitializerExpressionWithEnd(buffer, operand, kWasmBottom); } buffer->write_u8(kGCPrefix); - buffer->write_u8(static_cast( - init.kind() == WasmInitExpr::kStructNew ? kExprStructNew - : kExprStructNewWithRtt)); + WasmOpcode opcode; + switch (init.kind()) { + case WasmInitExpr::kStructNewWithRtt: + opcode = kExprStructNewWithRtt; + break; + case WasmInitExpr::kStructNew: + opcode = kExprStructNew; + break; + case WasmInitExpr::kStructNewDefaultWithRtt: + opcode = kExprStructNewDefaultWithRtt; + break; + case WasmInitExpr::kStructNewDefault: + opcode = kExprStructNewDefault; + break; + default: + UNREACHABLE(); + } + buffer->write_u8(static_cast(opcode)); buffer->write_u32v(init.immediate().index); break; case WasmInitExpr::kArrayInit: diff --git a/test/mjsunit/wasm/reference-globals.js b/test/mjsunit/wasm/reference-globals.js index 76d41f8f97..6ab071f9fa 100644 --- a/test/mjsunit/wasm/reference-globals.js +++ b/test/mjsunit/wasm/reference-globals.js @@ -113,7 +113,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); var struct_index = builder.addStruct([{type: kWasmI32, mutability: false}]); var composite_struct_index = builder.addStruct( [{type: kWasmI32, mutability: false}, - {type: wasmRefType(struct_index), mutability: false}, + {type: wasmOptRefType(struct_index), mutability: false}, {type: kWasmI8, mutability: true}]); let field1_value = 432; @@ -136,6 +136,12 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); WasmInitExpr.I32Const(field3_value), WasmInitExpr.RttCanon(composite_struct_index)])); + var global_default = builder.addGlobal( + wasmRefType(composite_struct_index), false, + WasmInitExpr.StructNewDefaultWithRtt( + composite_struct_index, + WasmInitExpr.RttCanon(composite_struct_index))); + builder.addFunction("field_1", kSig_i_v) .addBody([ kExprGlobalGet, global.index, @@ -156,11 +162,33 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); kExprGlobalGet, global.index, kGCPrefix, kExprStructGetS, composite_struct_index, 2]) .exportFunc(); + + builder.addFunction("field_1_default", kSig_i_v) + .addBody([ + kExprGlobalGet, global_default.index, + kGCPrefix, kExprStructGet, composite_struct_index, 0]) + .exportFunc(); + + builder.addFunction("field_2_default", makeSig([], [kWasmAnyRef])) + .addBody([ + kExprGlobalGet, global_default.index, + kGCPrefix, kExprStructGet, composite_struct_index, 1]) + .exportFunc(); + + builder.addFunction("field_3_default", kSig_i_v) + .addBody([ + kExprGlobalGet, global_default.index, + kGCPrefix, kExprStructGetS, composite_struct_index, 2]) + .exportFunc(); + var instance = builder.instantiate({}); assertEquals(field1_value, instance.exports.field_1()); assertEquals(field2_value, instance.exports.field_2()); assertEquals((field3_value << 24) >> 24, instance.exports.field_3()); + assertEquals(0, instance.exports.field_1_default()); + assertEquals(null, instance.exports.field_2_default()); + assertEquals(0, instance.exports.field_3_default()); })(); (function TestArrayInitExprNumeric() { diff --git a/test/mjsunit/wasm/wasm-module-builder.js b/test/mjsunit/wasm/wasm-module-builder.js index 5f85a3d8d7..61dbb47e69 100644 --- a/test/mjsunit/wasm/wasm-module-builder.js +++ b/test/mjsunit/wasm/wasm-module-builder.js @@ -983,7 +983,6 @@ class Binary { } } - emit_init_expr_recursive(expr) { switch (expr.kind) { case kExprGlobalGet: @@ -1015,6 +1014,8 @@ class Binary { break; case kExprStructNew: case kExprStructNewWithRtt: + case kExprStructNewDefault: + case kExprStructNewDefaultWithRtt: for (let operand of expr.operands) { this.emit_init_expr_recursive(operand); } @@ -1184,6 +1185,12 @@ class WasmInitExpr { static StructNew(type, args) { return {kind: kExprStructNew, value: type, operands: args}; } + static StructNewDefaultWithRtt(type, rtt) { + return {kind: kExprStructNewDefaultWithRtt, value: type, operands: [rtt]}; + } + static StructNewDefault(type) { + return {kind: kExprStructNewDefault, value: type, operands: []}; + } static ArrayInit(type, args) { return {kind: kExprArrayInit, value: type, operands: args}; }