01e59c4bd9
Motivation: With rtt.sub now allowed in constant expressions, we have to generalize WasmInitExpr to be able to handle expressions with operands. This CL prepares the ground for this change and adds no functionality. Changes: - ValueType::heap_representation and HeapType::representation now return HeapType::Representation. - Add ValueType::is_rtt(). - WasmInitExpr: - Make kind private. Rename val -> operator, make it private. Add accessors. - Rename kGlobalIndex -> kGlobalGet. - Squash global_index and function_index into index. - Add heap_type Immediate. Use it for RefNullConst. TypeOf in module-decoder.cc can now fully determine the type of a WasmInitExpr. - Add class constructors/static method constructors for each Operator kind. - Delete copy constructor. WasmInitExpr will use std::unique_ptr for its operands. - consume_init_expr now uses a stack. - A few minor improvements. Bug: v8:7748 Change-Id: I3ba3ee7ac2d6bc58e887790c37110ceb80658985 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2284483 Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#68759}
179 lines
6.5 KiB
C++
179 lines
6.5 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 <iostream>
|
|
|
|
#include "test/wasm-api-tests/wasm-api-test.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace wasm {
|
|
|
|
using ::wasm::Frame;
|
|
using ::wasm::Message;
|
|
|
|
namespace {
|
|
|
|
own<Trap> IdentityCallback(const Val args[], Val results[]) {
|
|
results[0] = args[0].copy();
|
|
return nullptr;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_F(WasmCapiTest, HostRef) {
|
|
ValueType rr_reps[] = {kWasmExternRef, kWasmExternRef};
|
|
ValueType ri_reps[] = {kWasmExternRef, kWasmI32};
|
|
ValueType ir_reps[] = {kWasmI32, kWasmExternRef};
|
|
// 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;
|
|
uint32_t global_index = builder()->AddExportedGlobal(
|
|
kWasmExternRef, kMutable, WasmInitExpr::RefNullConst(HeapType::kExtern),
|
|
CStrVector("global"));
|
|
uint32_t table_index = builder()->AddTable(kWasmExternRef, 10);
|
|
builder()->AddExport(CStrVector("table"), kExternalTable, table_index);
|
|
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);
|
|
|
|
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);
|
|
Extern* imports[] = {callback.get()};
|
|
Instantiate(imports);
|
|
|
|
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);
|
|
|
|
own<Foreign> host1 = Foreign::make(store());
|
|
own<Foreign> host2 = Foreign::make(store());
|
|
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()));
|
|
own<Ref> ref = val.release_ref();
|
|
EXPECT_EQ(nullptr, val.ref());
|
|
EXPECT_TRUE(ref->copy()->same(host1.get()));
|
|
|
|
// Interact with the Global.
|
|
Val args[2];
|
|
Val results[1];
|
|
own<Trap> trap = global_get->call(nullptr, results);
|
|
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()));
|
|
args[0] = Val::ref(own<Ref>());
|
|
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());
|
|
|
|
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()));
|
|
|
|
// 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);
|
|
args[1] = Val::ref(own<Ref>());
|
|
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());
|
|
|
|
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()));
|
|
|
|
// Interact with the Function.
|
|
args[0] = Val::ref(own<Ref>());
|
|
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
|