2019-08-19 12:26:07 +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"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace wasm {
|
|
|
|
|
|
|
|
using ::wasm::Frame;
|
|
|
|
using ::wasm::Message;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Trap> IdentityCallback(const Val args[], Val results[]) {
|
2019-08-19 12:26:07 +00:00
|
|
|
results[0] = args[0].copy();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_F(WasmCapiTest, HostRef) {
|
|
|
|
ValueType rr_reps[] = {kWasmAnyRef, kWasmAnyRef};
|
|
|
|
ValueType ri_reps[] = {kWasmAnyRef, kWasmI32};
|
|
|
|
ValueType ir_reps[] = {kWasmI32, kWasmAnyRef};
|
|
|
|
// Naming convention: result_params_sig.
|
|
|
|
FunctionSig r_r_sig(1, 1, rr_reps);
|
|
|
|
FunctionSig v_r_sig(0, 1, rr_reps);
|
|
|
|
FunctionSig r_v_sig(1, 0, rr_reps);
|
|
|
|
FunctionSig v_ir_sig(0, 2, ir_reps);
|
|
|
|
FunctionSig r_i_sig(1, 1, ri_reps);
|
|
|
|
uint32_t func_index = builder()->AddImport(CStrVector("f"), &r_r_sig);
|
|
|
|
const bool kMutable = true;
|
2020-06-03 12:48:16 +00:00
|
|
|
const WasmInitExpr global_init(WasmInitExpr::kRefNullConst);
|
2019-08-21 12:43:23 +00:00
|
|
|
uint32_t global_index = builder()->AddExportedGlobal(
|
|
|
|
kWasmAnyRef, kMutable, global_init, CStrVector("global"));
|
2019-08-19 12:26:07 +00:00
|
|
|
uint32_t table_index = builder()->AddTable(kWasmAnyRef, 10);
|
2019-08-21 12:43:23 +00:00
|
|
|
builder()->AddExport(CStrVector("table"), kExternalTable, table_index);
|
2019-08-19 12:26:07 +00:00
|
|
|
byte global_set_code[] = {WASM_SET_GLOBAL(global_index, WASM_GET_LOCAL(0))};
|
|
|
|
AddExportedFunction(CStrVector("global.set"), global_set_code,
|
|
|
|
sizeof(global_set_code), &v_r_sig);
|
|
|
|
byte global_get_code[] = {WASM_GET_GLOBAL(global_index)};
|
|
|
|
AddExportedFunction(CStrVector("global.get"), global_get_code,
|
|
|
|
sizeof(global_get_code), &r_v_sig);
|
|
|
|
byte table_set_code[] = {
|
|
|
|
WASM_TABLE_SET(table_index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
|
|
|
|
AddExportedFunction(CStrVector("table.set"), table_set_code,
|
|
|
|
sizeof(table_set_code), &v_ir_sig);
|
|
|
|
byte table_get_code[] = {WASM_TABLE_GET(table_index, WASM_GET_LOCAL(0))};
|
|
|
|
AddExportedFunction(CStrVector("table.get"), table_get_code,
|
|
|
|
sizeof(table_get_code), &r_i_sig);
|
|
|
|
byte func_call_code[] = {WASM_CALL_FUNCTION(func_index, WASM_GET_LOCAL(0))};
|
|
|
|
AddExportedFunction(CStrVector("func.call"), func_call_code,
|
|
|
|
sizeof(func_call_code), &r_r_sig);
|
|
|
|
|
2019-08-19 14:35:47 +00:00
|
|
|
own<FuncType> func_type =
|
|
|
|
FuncType::make(ownvec<ValType>::make(ValType::make(::wasm::ANYREF)),
|
|
|
|
ownvec<ValType>::make(ValType::make(::wasm::ANYREF)));
|
|
|
|
own<Func> callback = Func::make(store(), func_type.get(), IdentityCallback);
|
2019-08-19 12:26:07 +00:00
|
|
|
Extern* imports[] = {callback.get()};
|
|
|
|
Instantiate(imports);
|
|
|
|
|
2019-08-21 12:43:23 +00:00
|
|
|
Global* global = GetExportedGlobal(0);
|
|
|
|
Table* table = GetExportedTable(1);
|
|
|
|
const Func* global_set = GetExportedFunction(2);
|
|
|
|
const Func* global_get = GetExportedFunction(3);
|
|
|
|
const Func* table_set = GetExportedFunction(4);
|
|
|
|
const Func* table_get = GetExportedFunction(5);
|
|
|
|
const Func* func_call = GetExportedFunction(6);
|
2019-08-19 12:26:07 +00:00
|
|
|
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Foreign> host1 = Foreign::make(store());
|
|
|
|
own<Foreign> host2 = Foreign::make(store());
|
2019-08-19 12:26:07 +00:00
|
|
|
host1->set_host_info(reinterpret_cast<void*>(1));
|
|
|
|
host2->set_host_info(reinterpret_cast<void*>(2));
|
|
|
|
|
|
|
|
// Basic checks.
|
|
|
|
EXPECT_TRUE(host1->copy()->same(host1.get()));
|
|
|
|
EXPECT_TRUE(host2->copy()->same(host2.get()));
|
|
|
|
Val val = Val::ref(host1->copy());
|
|
|
|
EXPECT_TRUE(val.ref()->copy()->same(host1.get()));
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Ref> ref = val.release_ref();
|
2019-08-19 12:26:07 +00:00
|
|
|
EXPECT_EQ(nullptr, val.ref());
|
|
|
|
EXPECT_TRUE(ref->copy()->same(host1.get()));
|
|
|
|
|
|
|
|
// Interact with the Global.
|
|
|
|
Val args[2];
|
|
|
|
Val results[1];
|
2019-08-19 14:35:47 +00:00
|
|
|
own<Trap> trap = global_get->call(nullptr, results);
|
2019-08-19 12:26:07 +00:00
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(nullptr, results[0].release_ref());
|
|
|
|
args[0] = Val::ref(host1.get()->copy());
|
|
|
|
trap = global_set->call(args, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
trap = global_get->call(nullptr, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host1.get()));
|
|
|
|
args[0] = Val::ref(host2.get()->copy());
|
|
|
|
trap = global_set->call(args, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
trap = global_get->call(nullptr, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host2.get()));
|
2019-08-19 14:35:47 +00:00
|
|
|
args[0] = Val::ref(own<Ref>());
|
2019-08-19 12:26:07 +00:00
|
|
|
trap = global_set->call(args, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
trap = global_get->call(nullptr, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(nullptr, results[0].release_ref());
|
|
|
|
|
2019-08-21 12:43:23 +00:00
|
|
|
EXPECT_EQ(nullptr, global->get().release_ref());
|
|
|
|
global->set(Val(host2->copy()));
|
|
|
|
trap = global_get->call(nullptr, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host2.get()));
|
|
|
|
EXPECT_TRUE(global->get().release_ref()->same(host2.get()));
|
|
|
|
|
2019-08-19 12:26:07 +00:00
|
|
|
// Interact with the Table.
|
|
|
|
args[0] = Val::i32(0);
|
|
|
|
trap = table_get->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(nullptr, results[0].release_ref());
|
|
|
|
args[0] = Val::i32(1);
|
|
|
|
trap = table_get->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(nullptr, results[0].release_ref());
|
|
|
|
args[0] = Val::i32(0);
|
|
|
|
args[1] = Val::ref(host1.get()->copy());
|
|
|
|
trap = table_set->call(args, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
args[0] = Val::i32(1);
|
|
|
|
args[1] = Val::ref(host2.get()->copy());
|
|
|
|
trap = table_set->call(args, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
args[0] = Val::i32(0);
|
|
|
|
trap = table_get->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host1.get()));
|
|
|
|
args[0] = Val::i32(1);
|
|
|
|
trap = table_get->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host2.get()));
|
|
|
|
args[0] = Val::i32(0);
|
2019-08-19 14:35:47 +00:00
|
|
|
args[1] = Val::ref(own<Ref>());
|
2019-08-19 12:26:07 +00:00
|
|
|
trap = table_set->call(args, nullptr);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
trap = table_get->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(nullptr, results[0].release_ref());
|
|
|
|
|
2019-08-21 12:43:23 +00:00
|
|
|
EXPECT_EQ(nullptr, table->get(2));
|
|
|
|
table->set(2, host1.get());
|
|
|
|
args[0] = Val::i32(2);
|
|
|
|
trap = table_get->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host1.get()));
|
|
|
|
EXPECT_TRUE(table->get(2)->same(host1.get()));
|
|
|
|
|
2019-08-19 12:26:07 +00:00
|
|
|
// Interact with the Function.
|
2019-08-19 14:35:47 +00:00
|
|
|
args[0] = Val::ref(own<Ref>());
|
2019-08-19 12:26:07 +00:00
|
|
|
trap = func_call->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_EQ(nullptr, results[0].release_ref());
|
|
|
|
args[0] = Val::ref(host1.get()->copy());
|
|
|
|
trap = func_call->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host1.get()));
|
|
|
|
args[0] = Val::ref(host2.get()->copy());
|
|
|
|
trap = func_call->call(args, results);
|
|
|
|
EXPECT_EQ(nullptr, trap);
|
|
|
|
EXPECT_TRUE(results[0].release_ref()->same(host2.get()));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace wasm
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|