[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 <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76927}
This commit is contained in:
Manos Koukoutos 2021-09-17 14:45:06 +00:00 committed by V8 LUCI CQ
parent 6ec7e0a76c
commit eee722cbf4
7 changed files with 125 additions and 8 deletions

View File

@ -945,6 +945,8 @@ struct ControlBase : public PcForErrors<validate> {
F(GlobalGet, Value* result, const GlobalIndexImmediate<validate>& imm) \
F(StructNewWithRtt, const StructIndexImmediate<validate>& imm, \
const Value& rtt, const Value args[], Value* result) \
F(StructNewDefault, const StructIndexImmediate<validate>& imm, \
const Value& rtt, Value* result) \
F(ArrayInit, const ArrayIndexImmediate<validate>& imm, \
const base::Vector<Value>& elements, const Value& rtt, Value* result) \
F(RttCanon, uint32_t type_index, Value* result) \
@ -1047,8 +1049,6 @@ struct ControlBase : public PcForErrors<validate> {
F(TableSize, const IndexImmediate<validate>& imm, Value* result) \
F(TableFill, const IndexImmediate<validate>& imm, const Value& start, \
const Value& value, const Value& count) \
F(StructNewDefault, const StructIndexImmediate<validate>& imm, \
const Value& rtt, Value* result) \
F(StructGet, const Value& struct_object, \
const FieldImmediate<validate>& field, bool is_signed, Value* result) \
F(StructSet, const Value& struct_object, \
@ -4074,7 +4074,6 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
}
case kExprStructNewDefault:
case kExprStructNewDefaultWithRtt: {
NON_CONST_ONLY
StructIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
if (validate) {

View File

@ -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<validate>& imm,
const Value& rtt, Value* result) {
if (isolate_ == nullptr) return;
std::vector<WasmValue> 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<Map>::cast(rtt.runtime_value.to_ref())),
ValueType::Ref(HeapType(imm.index), kNonNullable));
}
void InitExprInterface::ArrayInit(FullDecoder* decoder,
const ArrayIndexImmediate<validate>& imm,
const base::Vector<Value>& elements,

View File

@ -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);

View File

@ -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<WasmInitExpr> 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++) {

View File

@ -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<uint8_t>(
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<uint8_t>(opcode));
buffer->write_u32v(init.immediate().index);
break;
case WasmInitExpr::kArrayInit:

View File

@ -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() {

View File

@ -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};
}