Commit 6e36e3ec authored by Jakob Kummerow's avatar Jakob Kummerow Committed by V8 LUCI CQ

[wasm-gc] Support immutable arrays

Since we introduced `array.init` as a way to create fully initialized
arrays, immutable arrays are no longer useless, and they enable certain
static optimizations, so this patch allows them.

Bug: v8:7748
Change-Id: I404aab60099826f4bd83cf54e5e1acbc38a3ca9b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3221151
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarManos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77397}
parent 7efcab88
......@@ -1926,9 +1926,6 @@ class ModuleDecoderImpl : public Decoder {
ValueType field = consume_storage_type();
if (failed()) return nullptr;
bool mutability = consume_mutability();
if (!V8_LIKELY(mutability)) {
error(this->pc() - 1, "immutable arrays are not supported yet");
}
return zone->New<ArrayType>(field, mutability);
}
......
......@@ -918,6 +918,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
const byte type_index = tester.DefineArray(wasm::kWasmI32, true);
const byte fp_type_index = tester.DefineArray(wasm::kWasmF64, true);
const byte immut_type_index = tester.DefineArray(wasm::kWasmI32, false);
ValueType kRefTypes[] = {ref(type_index)};
FunctionSig sig_q_v(1, 0, kRefTypes);
ValueType kOptRefType = optref(type_index);
......@@ -961,6 +962,15 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
WASM_I32V(30), WASM_RTT_CANON(type_index)),
kExprEnd});
const byte kImmutable = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_ARRAY_GET(
immut_type_index,
WASM_ARRAY_INIT(immut_type_index, 2, WASM_I32V(42), WASM_I32V(43),
WASM_RTT_CANON(immut_type_index)),
WASM_I32V(0)),
kExprEnd});
const uint32_t kLongLength = 1u << 16;
const byte kAllocateLarge = tester.DefineFunction(
&sig_q_v, {},
......@@ -998,6 +1008,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
tester.CheckHasThrown(kGetElem, 3);
tester.CheckHasThrown(kGetElem, -1);
tester.CheckResult(kGetLength, 42);
tester.CheckResult(kImmutable, 42);
tester.CheckResult(kTestFpArray, static_cast<int32_t>(result_value));
Handle<Object> h_result = tester.GetResultObject(kAllocate).ToHandleChecked();
......
......@@ -1291,7 +1291,6 @@ class WasmStructSubtype extends WasmStruct {
class WasmArray {
constructor(type, mutability) {
this.type = type;
if (!mutability) throw new Error("Immutable arrays are not supported yet");
this.mutability = mutability;
this.type_form = kWasmArrayTypeForm;
}
......
......@@ -4131,13 +4131,17 @@ TEST_F(FunctionBodyDecoderTest, GCArray) {
byte array_type_index = builder.AddArray(kWasmFuncRef, true);
byte struct_type_index = builder.AddStruct({F(kWasmI32, false)});
byte immutable_array_type_index = builder.AddArray(kWasmI32, false);
ValueType array_type = ValueType::Ref(array_type_index, kNonNullable);
ValueType immutable_array_type =
ValueType::Ref(immutable_array_type_index, kNonNullable);
ValueType reps_c_r[] = {kWasmFuncRef, array_type};
ValueType reps_f_r[] = {kWasmF32, array_type};
ValueType reps_i_r[] = {kWasmI32, array_type};
const FunctionSig sig_c_r(1, 1, reps_c_r);
const FunctionSig sig_v_r(0, 1, &array_type);
const FunctionSig sig_v_r2(0, 1, &immutable_array_type);
const FunctionSig sig_r_v(1, 0, &array_type);
const FunctionSig sig_f_r(1, 1, reps_f_r);
const FunctionSig sig_v_cr(0, 2, reps_c_r);
......@@ -4260,6 +4264,21 @@ TEST_F(FunctionBodyDecoderTest, GCArray) {
ExpectFailure(&sig_i_r,
{WASM_ARRAY_LEN(struct_type_index, WASM_LOCAL_GET(0))},
kAppendEnd, "invalid array index: 1");
// Immutable array.
// Allocating and reading is OK:
ExpectValidates(
sigs.i_v(),
{WASM_ARRAY_GET(
immutable_array_type_index,
WASM_ARRAY_INIT(immutable_array_type_index, 1, WASM_I32V(42),
WASM_RTT_CANON(immutable_array_type_index)),
WASM_I32V(0))});
// Writing fails:
ExpectFailure(&sig_v_r2,
{WASM_ARRAY_SET(immutable_array_type_index, WASM_LOCAL_GET(0),
WASM_I32V(0), WASM_I32V(42))},
kAppendEnd, "array.set: immediate array type 2 is immutable");
}
TEST_F(FunctionBodyDecoderTest, PackedFields) {
......
......@@ -1118,6 +1118,7 @@ TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) {
WASM_INIT_EXPR_ARRAY_INIT(0, 3, WASM_I32V(10), WASM_I32V(20),
WASM_I32V(30), WASM_RTT_CANON(0)))};
EXPECT_VERIFIES(basic);
static const byte basic_nominal[] = {
SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI16Code, true)),
SECTION(Global, ENTRY_COUNT(1), // --
......@@ -1126,6 +1127,14 @@ TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) {
WASM_I32V(20), WASM_I32V(30)))};
EXPECT_VERIFIES(basic_nominal);
static const byte basic_immutable[] = {
SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI32Code, false)),
SECTION(Global, ENTRY_COUNT(1), // --
kRefCode, 0, 0, // type, mutability
WASM_INIT_EXPR_ARRAY_INIT(0, 3, WASM_I32V(10), WASM_I32V(20),
WASM_I32V(30), WASM_RTT_CANON(0)))};
EXPECT_VERIFIES(basic_immutable);
static const byte type_error[] = {
SECTION(Type, ENTRY_COUNT(2), // --
WASM_ARRAY_DEF(kI32Code, true),
......@@ -1421,14 +1430,12 @@ TEST_F(WasmModuleVerifyTest, InvalidArrayTypeDef) {
2)}; // invalid mutability value
EXPECT_FAILURE_WITH_MSG(invalid_mutability, "invalid mutability");
static const byte invalid_mutability2[] = {
SECTION(Type,
static const byte immutable[] = {SECTION(Type,
ENTRY_COUNT(1), // --
kWasmArrayTypeCode, // --
kI32Code, // field type
0)}; // immmutability (disallowed in MVP)
EXPECT_FAILURE_WITH_MSG(invalid_mutability2,
"immutable arrays are not supported");
0)}; // immmutability
EXPECT_VERIFIES(immutable);
}
TEST_F(WasmModuleVerifyTest, ZeroExceptions) {
......
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