Commit 97eff73b authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wams-gc] Enable i31.new as constant expression

Bug: v8:7748
Change-Id: Ib3b1d99107ad2a9c703e9dc546b522e208204d1c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3702443
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81205}
parent e4a7ef2b
......@@ -276,6 +276,16 @@ void ConstantExpressionInterface::RttCanon(FullDecoder* decoder,
ValueType::Rtt(type_index));
}
void ConstantExpressionInterface::I31New(FullDecoder* decoder,
const Value& input, Value* result) {
if (!generate_value()) return;
Address raw = static_cast<Address>(input.runtime_value.to_i32());
// 33 = 1 (Smi tag) + 31 (Smi shift) + 1 (i31ref high-bit truncation).
Address shifted = raw << (SmiValuesAre31Bits() ? 1 : 33);
result->runtime_value =
WasmValue(handle(Smi(shifted), isolate_), wasm::kWasmI31Ref.AsNonNull());
}
void ConstantExpressionInterface::DoReturn(FullDecoder* decoder,
uint32_t /*drop_values*/) {
end_found_ = true;
......
......@@ -973,11 +973,12 @@ struct ControlBase : public PcForErrors<validate> {
F(F32Const, Value* result, float value) \
F(F64Const, Value* result, double value) \
F(S128Const, Simd128Immediate<validate>& imm, Value* result) \
F(GlobalGet, Value* result, const GlobalIndexImmediate<validate>& imm) \
F(DoReturn, uint32_t drop_values) \
F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \
Value* result) \
F(RefNull, ValueType type, Value* result) \
F(RefFunc, uint32_t function_index, Value* result) \
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, \
......@@ -987,9 +988,9 @@ struct ControlBase : public PcForErrors<validate> {
F(ArrayInitFromSegment, const ArrayIndexImmediate<validate>& array_imm, \
const IndexImmediate<validate>& data_segment, const Value& offset, \
const Value& length, const Value& rtt, Value* result) \
F(I31New, const Value& input, Value* result) \
F(RttCanon, uint32_t type_index, Value* result) \
F(StringConst, const StringConstImmediate<validate>& imm, Value* result) \
F(DoReturn, uint32_t drop_values)
F(StringConst, const StringConstImmediate<validate>& imm, Value* result)
#define INTERFACE_NON_CONSTANT_FUNCTIONS(F) /* force 80 columns */ \
/* Control: */ \
......@@ -1103,7 +1104,6 @@ struct ControlBase : public PcForErrors<validate> {
F(ArrayLen, const Value& array_obj, Value* result) \
F(ArrayCopy, const Value& src, const Value& src_index, const Value& dst, \
const Value& dst_index, const Value& length) \
F(I31New, const Value& input, Value* result) \
F(I31GetS, const Value& input, Value* result) \
F(I31GetU, const Value& input, Value* result) \
F(RefTest, const Value& obj, const Value& rtt, Value* result) \
......@@ -4643,7 +4643,6 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
return opcode_length + array_imm.length + length_imm.length;
}
case kExprI31New: {
NON_CONST_ONLY
Value input = Peek(0, 0, kWasmI32);
Value value = CreateValue(kWasmI31Ref);
CALL_INTERFACE_IF_OK_AND_REACHABLE(I31New, input, &value);
......
......@@ -45,6 +45,8 @@ ValueType WasmInitExpr::type(const WasmModule* module,
case kArrayInit:
case kArrayInitStatic:
return ValueType::Ref(immediate().index, kNonNullable);
case kI31New:
return kWasmI31Ref.AsNonNull();
case kRttCanon:
return ValueType::Rtt(immediate().heap_type);
case kStringConst:
......
......@@ -42,6 +42,7 @@ class WasmInitExpr : public ZoneObject {
kStructNewDefault,
kArrayInit,
kArrayInitStatic,
kI31New,
kRttCanon,
kStringConst,
};
......@@ -148,6 +149,13 @@ class WasmInitExpr : public ZoneObject {
return expr;
}
static WasmInitExpr I31New(Zone* zone, WasmInitExpr value) {
WasmInitExpr expr(kI31New,
zone->New<ZoneVector<WasmInitExpr>>(
std::initializer_list<WasmInitExpr>{value}, zone));
return expr;
}
static WasmInitExpr StringConst(uint32_t index) {
WasmInitExpr expr;
expr.kind_ = kStringConst;
......@@ -199,6 +207,11 @@ class WasmInitExpr : public ZoneObject {
if (operands()[i] != other.operands()[i]) return false;
}
return true;
case kI31New: {
int32_t mask = int32_t{0x7fffffff};
return (immediate().i32_const & mask) ==
(other.immediate().i32_const & mask);
}
}
}
......
......@@ -570,6 +570,15 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer,
: kExprArrayInitStatic));
buffer->write_u32v(init.immediate().index);
buffer->write_u32v(static_cast<uint32_t>(init.operands()->size() - 1));
break;
case WasmInitExpr::kI31New:
WriteInitializerExpressionWithEnd(buffer, (*init.operands())[0],
kWasmI32);
static_assert((kExprI31New >> 8) == kGCPrefix);
buffer->write_u8(kGCPrefix);
buffer->write_u8(static_cast<uint8_t>(kExprI31New));
break;
case WasmInitExpr::kRttCanon:
static_assert((kExprRttCanon >> 8) == kGCPrefix);
......
......@@ -412,6 +412,10 @@ class InitExprInterface {
UNIMPLEMENTED();
}
void I31New(FullDecoder* decoder, const Value& input, Value* result) {
result->init_expr = WasmInitExpr::I31New(zone_, input.init_expr);
}
void RttCanon(FullDecoder* decoder, uint32_t type_index, Value* result) {
result->init_expr = WasmInitExpr::RttCanon(type_index);
}
......@@ -495,6 +499,9 @@ void AppendInitExpr(std::ostream& os, const WasmInitExpr& expr) {
os << "ArrayInitStatic(" << expr.immediate().index;
append_operands = true;
break;
case WasmInitExpr::kI31New:
os << "I31New(" << expr.immediate().i32_const;
break;
case WasmInitExpr::kRttCanon:
os << "RttCanon(" << expr.immediate().index;
break;
......
......@@ -283,3 +283,50 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
assertEquals(null, instance.exports.element1());
assertEquals(element2_value, instance.exports.element2());
})();
(function TestI31RefConstantExpr() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let array_index = builder.addArray(kWasmI31Ref, false);
let values = [0, 10, -22, 0x7fffffff, -1];
let global = builder.addGlobal(
wasmRefType(array_index), true,
WasmInitExpr.ArrayInitStatic(array_index, values.map(
value => WasmInitExpr.I31New(WasmInitExpr.I32Const(value)))));
for (signed of [true, false]) {
builder.addFunction(`get_${signed ? "s" : "u"}`, kSig_i_i)
.addBody([kExprGlobalGet, global.index,
kExprLocalGet, 0, kGCPrefix, kExprArrayGet, array_index,
kGCPrefix, signed ? kExprI31GetS : kExprI31GetU])
.exportFunc();
}
let instance = builder.instantiate();
assertEquals(values[0], instance.exports.get_s(0));
assertEquals(values[1], instance.exports.get_s(1));
assertEquals(values[2], instance.exports.get_s(2));
assertEquals(values[3] | 0x80000000, instance.exports.get_s(3));
assertEquals(values[4], instance.exports.get_s(4));
assertEquals(values[0], instance.exports.get_u(0));
assertEquals(values[1], instance.exports.get_u(1));
assertEquals(values[2] & 0x7fffffff, instance.exports.get_u(2));
assertEquals(values[3], instance.exports.get_u(3));
assertEquals(values[4] & 0x7fffffff, instance.exports.get_u(4));
})();
(function TestI31RefConstantExprTypeError() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addGlobal(kWasmI31Ref, false,
WasmInitExpr.I31New(WasmInitExpr.I64Const(0)));
assertThrows(() => builder.instantiate(), WebAssembly.CompileError,
/i31.new\[0\] expected type i32, found i64.const of type i64/);
})();
......@@ -1087,7 +1087,6 @@ class Binary {
this.emit_u32v(expr.value);
break;
case kExprArrayInit:
case kExprArrayInitStatic:
for (let operand of expr.operands) {
this.emit_init_expr_recursive(operand);
}
......@@ -1096,6 +1095,15 @@ class Binary {
this.emit_u32v(expr.value);
this.emit_u32v(expr.operands.length - 1);
break;
case kExprArrayInitStatic:
for (let operand of expr.operands) {
this.emit_init_expr_recursive(operand);
}
this.emit_u8(kGCPrefix);
this.emit_u8(expr.kind);
this.emit_u32v(expr.value);
this.emit_u32v(expr.operands.length);
break;
case kExprArrayInitFromData:
case kExprArrayInitFromDataStatic:
case kExprArrayInitFromElemStatic:
......@@ -1107,6 +1115,11 @@ class Binary {
this.emit_u32v(expr.array_index);
this.emit_u32v(expr.segment_index);
break;
case kExprI31New:
this.emit_init_expr_recursive(expr.operand);
this.emit_u8(kGCPrefix);
this.emit_u8(expr.kind);
break;
case kExprRttCanon:
this.emit_u8(kGCPrefix);
this.emit_u8(kExprRttCanon);
......@@ -1312,6 +1325,9 @@ class WasmInitExpr {
return {kind: kExprArrayInitFromElemStatic, array_index: array_index,
segment_index: segment_index, operands: args};
}
static I31New(value) {
return {kind: kExprI31New, operand: value};
}
static RttCanon(type) {
return {kind: kExprRttCanon, value: type};
}
......
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