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 { ...@@ -1926,9 +1926,6 @@ class ModuleDecoderImpl : public Decoder {
ValueType field = consume_storage_type(); ValueType field = consume_storage_type();
if (failed()) return nullptr; if (failed()) return nullptr;
bool mutability = consume_mutability(); bool mutability = consume_mutability();
if (!V8_LIKELY(mutability)) {
error(this->pc() - 1, "immutable arrays are not supported yet");
}
return zone->New<ArrayType>(field, mutability); return zone->New<ArrayType>(field, mutability);
} }
......
...@@ -918,6 +918,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) { ...@@ -918,6 +918,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
const byte type_index = tester.DefineArray(wasm::kWasmI32, true); const byte type_index = tester.DefineArray(wasm::kWasmI32, true);
const byte fp_type_index = tester.DefineArray(wasm::kWasmF64, 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)}; ValueType kRefTypes[] = {ref(type_index)};
FunctionSig sig_q_v(1, 0, kRefTypes); FunctionSig sig_q_v(1, 0, kRefTypes);
ValueType kOptRefType = optref(type_index); ValueType kOptRefType = optref(type_index);
...@@ -961,6 +962,15 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) { ...@@ -961,6 +962,15 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
WASM_I32V(30), WASM_RTT_CANON(type_index)), WASM_I32V(30), WASM_RTT_CANON(type_index)),
kExprEnd}); 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 uint32_t kLongLength = 1u << 16;
const byte kAllocateLarge = tester.DefineFunction( const byte kAllocateLarge = tester.DefineFunction(
&sig_q_v, {}, &sig_q_v, {},
...@@ -998,6 +1008,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) { ...@@ -998,6 +1008,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
tester.CheckHasThrown(kGetElem, 3); tester.CheckHasThrown(kGetElem, 3);
tester.CheckHasThrown(kGetElem, -1); tester.CheckHasThrown(kGetElem, -1);
tester.CheckResult(kGetLength, 42); tester.CheckResult(kGetLength, 42);
tester.CheckResult(kImmutable, 42);
tester.CheckResult(kTestFpArray, static_cast<int32_t>(result_value)); tester.CheckResult(kTestFpArray, static_cast<int32_t>(result_value));
Handle<Object> h_result = tester.GetResultObject(kAllocate).ToHandleChecked(); Handle<Object> h_result = tester.GetResultObject(kAllocate).ToHandleChecked();
......
...@@ -1291,7 +1291,6 @@ class WasmStructSubtype extends WasmStruct { ...@@ -1291,7 +1291,6 @@ class WasmStructSubtype extends WasmStruct {
class WasmArray { class WasmArray {
constructor(type, mutability) { constructor(type, mutability) {
this.type = type; this.type = type;
if (!mutability) throw new Error("Immutable arrays are not supported yet");
this.mutability = mutability; this.mutability = mutability;
this.type_form = kWasmArrayTypeForm; this.type_form = kWasmArrayTypeForm;
} }
......
...@@ -4131,13 +4131,17 @@ TEST_F(FunctionBodyDecoderTest, GCArray) { ...@@ -4131,13 +4131,17 @@ TEST_F(FunctionBodyDecoderTest, GCArray) {
byte array_type_index = builder.AddArray(kWasmFuncRef, true); byte array_type_index = builder.AddArray(kWasmFuncRef, true);
byte struct_type_index = builder.AddStruct({F(kWasmI32, false)}); 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 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_c_r[] = {kWasmFuncRef, array_type};
ValueType reps_f_r[] = {kWasmF32, array_type}; ValueType reps_f_r[] = {kWasmF32, array_type};
ValueType reps_i_r[] = {kWasmI32, array_type}; ValueType reps_i_r[] = {kWasmI32, array_type};
const FunctionSig sig_c_r(1, 1, reps_c_r); const FunctionSig sig_c_r(1, 1, reps_c_r);
const FunctionSig sig_v_r(0, 1, &array_type); 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_r_v(1, 0, &array_type);
const FunctionSig sig_f_r(1, 1, reps_f_r); const FunctionSig sig_f_r(1, 1, reps_f_r);
const FunctionSig sig_v_cr(0, 2, reps_c_r); const FunctionSig sig_v_cr(0, 2, reps_c_r);
...@@ -4260,6 +4264,21 @@ TEST_F(FunctionBodyDecoderTest, GCArray) { ...@@ -4260,6 +4264,21 @@ TEST_F(FunctionBodyDecoderTest, GCArray) {
ExpectFailure(&sig_i_r, ExpectFailure(&sig_i_r,
{WASM_ARRAY_LEN(struct_type_index, WASM_LOCAL_GET(0))}, {WASM_ARRAY_LEN(struct_type_index, WASM_LOCAL_GET(0))},
kAppendEnd, "invalid array index: 1"); 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) { TEST_F(FunctionBodyDecoderTest, PackedFields) {
......
...@@ -1118,6 +1118,7 @@ TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) { ...@@ -1118,6 +1118,7 @@ TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) {
WASM_INIT_EXPR_ARRAY_INIT(0, 3, WASM_I32V(10), WASM_I32V(20), WASM_INIT_EXPR_ARRAY_INIT(0, 3, WASM_I32V(10), WASM_I32V(20),
WASM_I32V(30), WASM_RTT_CANON(0)))}; WASM_I32V(30), WASM_RTT_CANON(0)))};
EXPECT_VERIFIES(basic); EXPECT_VERIFIES(basic);
static const byte basic_nominal[] = { static const byte basic_nominal[] = {
SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI16Code, true)), SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI16Code, true)),
SECTION(Global, ENTRY_COUNT(1), // -- SECTION(Global, ENTRY_COUNT(1), // --
...@@ -1126,6 +1127,14 @@ TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) { ...@@ -1126,6 +1127,14 @@ TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) {
WASM_I32V(20), WASM_I32V(30)))}; WASM_I32V(20), WASM_I32V(30)))};
EXPECT_VERIFIES(basic_nominal); 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[] = { static const byte type_error[] = {
SECTION(Type, ENTRY_COUNT(2), // -- SECTION(Type, ENTRY_COUNT(2), // --
WASM_ARRAY_DEF(kI32Code, true), WASM_ARRAY_DEF(kI32Code, true),
...@@ -1421,14 +1430,12 @@ TEST_F(WasmModuleVerifyTest, InvalidArrayTypeDef) { ...@@ -1421,14 +1430,12 @@ TEST_F(WasmModuleVerifyTest, InvalidArrayTypeDef) {
2)}; // invalid mutability value 2)}; // invalid mutability value
EXPECT_FAILURE_WITH_MSG(invalid_mutability, "invalid mutability"); EXPECT_FAILURE_WITH_MSG(invalid_mutability, "invalid mutability");
static const byte invalid_mutability2[] = { static const byte immutable[] = {SECTION(Type,
SECTION(Type, ENTRY_COUNT(1), // --
ENTRY_COUNT(1), // -- kWasmArrayTypeCode, // --
kWasmArrayTypeCode, // -- kI32Code, // field type
kI32Code, // field type 0)}; // immmutability
0)}; // immmutability (disallowed in MVP) EXPECT_VERIFIES(immutable);
EXPECT_FAILURE_WITH_MSG(invalid_mutability2,
"immutable arrays are not supported");
} }
TEST_F(WasmModuleVerifyTest, ZeroExceptions) { 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