2019-07-11 13:48:21 +00:00
|
|
|
// 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 {
|
|
|
|
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Trap> Negate(const Val args[], Val results[]) {
|
2019-07-11 13:48:21 +00:00
|
|
|
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];
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Trap> trap = func->call(args, results);
|
2019-07-11 13:48:21 +00:00
|
|
|
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];
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Trap> trap = func->call(args, results);
|
2019-07-11 13:48:21 +00:00
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(expected, results[0].i32());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_F(WasmCapiTest, Table) {
|
2021-08-31 09:17:12 +00:00
|
|
|
const uint32_t table_index = builder()->AddTable(kWasmFuncRef, 2, 10);
|
|
|
|
builder()->AddExport(base::CStrVector("table"), kExternalTable, table_index);
|
2019-07-11 13:48:21 +00:00
|
|
|
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[] = {
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_CALL_INDIRECT(sig_i_i_index, WASM_LOCAL_GET(0), WASM_LOCAL_GET(1))};
|
2021-06-17 15:43:55 +00:00
|
|
|
AddExportedFunction(base::CStrVector("call_indirect"), call_code,
|
|
|
|
sizeof(call_code), &call_sig);
|
2020-12-17 16:55:33 +00:00
|
|
|
byte f_code[] = {WASM_LOCAL_GET(0)};
|
2021-06-17 15:43:55 +00:00
|
|
|
AddExportedFunction(base::CStrVector("f"), f_code, sizeof(f_code),
|
|
|
|
wasm_i_i_sig());
|
2019-07-11 13:48:21 +00:00
|
|
|
byte g_code[] = {WASM_I32V_1(42)};
|
2021-06-17 15:43:55 +00:00
|
|
|
AddExportedFunction(base::CStrVector("g"), g_code, sizeof(g_code),
|
|
|
|
wasm_i_i_sig());
|
2019-07-11 13:48:21 +00:00
|
|
|
// Set table[1] to {f}, which has function index 1.
|
2021-08-31 09:17:12 +00:00
|
|
|
builder()->SetIndirectFunction(
|
|
|
|
table_index, 1, 1,
|
|
|
|
WasmModuleBuilder::WasmElemSegment::kRelativeToImports);
|
2019-07-11 13:48:21 +00:00
|
|
|
|
|
|
|
Instantiate(nullptr);
|
|
|
|
|
2019-07-11 15:02:44 +00:00
|
|
|
Table* table = GetExportedTable(0);
|
|
|
|
Func* call_indirect = GetExportedFunction(1);
|
|
|
|
Func* f = GetExportedFunction(2);
|
|
|
|
Func* g = GetExportedFunction(3);
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Func> h = Func::make(store(), cpp_i_i_sig(), Negate);
|
2019-07-11 13:48:21 +00:00
|
|
|
|
2019-08-06 13:56:56 +00:00
|
|
|
// Try cloning.
|
|
|
|
EXPECT_TRUE(table->copy()->same(table));
|
|
|
|
|
2019-07-11 13:48:21 +00:00
|
|
|
// 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.
|
2019-08-19 14:35:47 +00:00
|
|
|
own<TableType> tabletype =
|
2019-07-11 13:48:21 +00:00
|
|
|
TableType::make(ValType::make(FUNCREF), Limits(5, 5));
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Table> table2 = Table::make(store(), tabletype.get());
|
2019-07-11 13:48:21 +00:00
|
|
|
EXPECT_EQ(5u, table2->size());
|
|
|
|
EXPECT_FALSE(table2->grow(1));
|
|
|
|
EXPECT_TRUE(table2->grow(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace wasm
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|