797e4afefe
WasmModuleBuilder is a class that is used to build Wasm modules in the asm.js parser, in the fuzzer, as well as some tests. When it comes to Wasm tables, WasmModuleBuilder currently supports only basic tables (before the reftypes proposal) using an ad-hoc indirect-function index vector. This CL adds proper support for element sections and tables that use them in the full potential of the reftypes extension. The new functionality will only be used in the fuzzer and potentially some tests in the future. Along this, we drop some functionality from WasmModuleBuilder that was only used in tests and is redundant with the new architecture. Additionally, we remove tables other than externref and funcref from the fuzzer (which were not supported properly or used anyway). We will reintroduce them at a later time. Bug: v8:11954 Change-Id: I0a4f6e7b63b6e3d9f7da03b5202fbf14d8678332 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3122162 Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#76597}
123 lines
3.9 KiB
C++
123 lines
3.9 KiB
C++
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "test/wasm-api-tests/wasm-api-test.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace wasm {
|
|
|
|
using ::wasm::FUNCREF;
|
|
using ::wasm::Limits;
|
|
using ::wasm::TableType;
|
|
|
|
namespace {
|
|
|
|
own<Trap> Negate(const Val args[], Val results[]) {
|
|
results[0] = Val(-args[0].i32());
|
|
return nullptr;
|
|
}
|
|
|
|
void ExpectTrap(const Func* func, int arg1, int arg2) {
|
|
Val args[2] = {Val::i32(arg1), Val::i32(arg2)};
|
|
Val results[1];
|
|
own<Trap> trap = func->call(args, results);
|
|
EXPECT_NE(nullptr, trap);
|
|
}
|
|
|
|
void ExpectResult(int expected, const Func* func, int arg1, int arg2) {
|
|
Val args[2] = {Val::i32(arg1), Val::i32(arg2)};
|
|
Val results[1];
|
|
own<Trap> trap = func->call(args, results);
|
|
EXPECT_EQ(nullptr, trap);
|
|
EXPECT_EQ(expected, results[0].i32());
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_F(WasmCapiTest, Table) {
|
|
const uint32_t table_index = builder()->AddTable(kWasmFuncRef, 2, 10);
|
|
builder()->AddExport(base::CStrVector("table"), kExternalTable, table_index);
|
|
const uint32_t sig_i_i_index = builder()->AddSignature(wasm_i_i_sig());
|
|
ValueType reps[] = {kWasmI32, kWasmI32, kWasmI32};
|
|
FunctionSig call_sig(1, 2, reps);
|
|
byte call_code[] = {
|
|
WASM_CALL_INDIRECT(sig_i_i_index, WASM_LOCAL_GET(0), WASM_LOCAL_GET(1))};
|
|
AddExportedFunction(base::CStrVector("call_indirect"), call_code,
|
|
sizeof(call_code), &call_sig);
|
|
byte f_code[] = {WASM_LOCAL_GET(0)};
|
|
AddExportedFunction(base::CStrVector("f"), f_code, sizeof(f_code),
|
|
wasm_i_i_sig());
|
|
byte g_code[] = {WASM_I32V_1(42)};
|
|
AddExportedFunction(base::CStrVector("g"), g_code, sizeof(g_code),
|
|
wasm_i_i_sig());
|
|
// Set table[1] to {f}, which has function index 1.
|
|
builder()->SetIndirectFunction(
|
|
table_index, 1, 1,
|
|
WasmModuleBuilder::WasmElemSegment::kRelativeToImports);
|
|
|
|
Instantiate(nullptr);
|
|
|
|
Table* table = GetExportedTable(0);
|
|
Func* call_indirect = GetExportedFunction(1);
|
|
Func* f = GetExportedFunction(2);
|
|
Func* g = GetExportedFunction(3);
|
|
own<Func> h = Func::make(store(), cpp_i_i_sig(), Negate);
|
|
|
|
// Try cloning.
|
|
EXPECT_TRUE(table->copy()->same(table));
|
|
|
|
// Check initial table state.
|
|
EXPECT_EQ(2u, table->size());
|
|
EXPECT_EQ(nullptr, table->get(0));
|
|
EXPECT_NE(nullptr, table->get(1));
|
|
ExpectTrap(call_indirect, 0, 0);
|
|
ExpectResult(7, call_indirect, 7, 1);
|
|
ExpectTrap(call_indirect, 0, 2);
|
|
|
|
// Mutate table.
|
|
EXPECT_TRUE(table->set(0, g));
|
|
EXPECT_TRUE(table->set(1, nullptr));
|
|
EXPECT_FALSE(table->set(2, f));
|
|
EXPECT_NE(nullptr, table->get(0));
|
|
EXPECT_EQ(nullptr, table->get(1));
|
|
ExpectResult(42, call_indirect, 7, 0);
|
|
ExpectTrap(call_indirect, 0, 1);
|
|
ExpectTrap(call_indirect, 0, 2);
|
|
|
|
// Grow table.
|
|
EXPECT_TRUE(table->grow(3));
|
|
EXPECT_EQ(5u, table->size());
|
|
EXPECT_TRUE(table->set(2, f));
|
|
EXPECT_TRUE(table->set(3, h.get()));
|
|
EXPECT_FALSE(table->set(5, nullptr));
|
|
EXPECT_NE(nullptr, table->get(2));
|
|
EXPECT_NE(nullptr, table->get(3));
|
|
EXPECT_EQ(nullptr, table->get(4));
|
|
ExpectResult(5, call_indirect, 5, 2);
|
|
ExpectResult(-6, call_indirect, 6, 3);
|
|
ExpectTrap(call_indirect, 0, 4);
|
|
ExpectTrap(call_indirect, 0, 5);
|
|
EXPECT_TRUE(table->grow(2, f));
|
|
EXPECT_EQ(7u, table->size());
|
|
EXPECT_NE(nullptr, table->get(5));
|
|
EXPECT_NE(nullptr, table->get(6));
|
|
EXPECT_FALSE(table->grow(5));
|
|
EXPECT_TRUE(table->grow(3));
|
|
EXPECT_TRUE(table->grow(0));
|
|
|
|
// Create standalone table.
|
|
// TODO(wasm+): Once Wasm allows multiple tables, turn this into import.
|
|
own<TableType> tabletype =
|
|
TableType::make(ValType::make(FUNCREF), Limits(5, 5));
|
|
own<Table> table2 = Table::make(store(), tabletype.get());
|
|
EXPECT_EQ(5u, table2->size());
|
|
EXPECT_FALSE(table2->grow(1));
|
|
EXPECT_TRUE(table2->grow(0));
|
|
}
|
|
|
|
} // namespace wasm
|
|
} // namespace internal
|
|
} // namespace v8
|