hostref.cc 6.54 KB
Newer Older
1 2 3 4 5 6
// 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>

7 8
#include "test/wasm-api-tests/wasm-api-test.h"

9 10 11 12 13 14 15 16 17
namespace v8 {
namespace internal {
namespace wasm {

using ::wasm::Frame;
using ::wasm::Message;

namespace {

18
own<Trap> IdentityCallback(const Val args[], Val results[]) {
19 20 21 22 23 24 25
  results[0] = args[0].copy();
  return nullptr;
}

}  // namespace

TEST_F(WasmCapiTest, HostRef) {
26 27 28
  ValueType rr_reps[] = {kWasmExternRef, kWasmExternRef};
  ValueType ri_reps[] = {kWasmExternRef, kWasmI32};
  ValueType ir_reps[] = {kWasmI32, kWasmExternRef};
29 30 31 32 33 34 35 36
  // 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;
37
  uint32_t global_index = builder()->AddExportedGlobal(
38 39
      kWasmExternRef, kMutable, WasmInitExpr::RefNullConst(HeapType::kExtern),
      CStrVector("global"));
40
  uint32_t table_index = builder()->AddTable(kWasmExternRef, 10);
41
  builder()->AddExport(CStrVector("table"), kExternalTable, table_index);
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
  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);

59 60 61 62
  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);
63 64 65
  Extern* imports[] = {callback.get()};
  Instantiate(imports);

66 67 68 69 70 71 72
  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);
73

74 75
  own<Foreign> host1 = Foreign::make(store());
  own<Foreign> host2 = Foreign::make(store());
76 77 78 79 80 81 82 83
  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()));
84
  own<Ref> ref = val.release_ref();
85 86 87 88 89 90
  EXPECT_EQ(nullptr, val.ref());
  EXPECT_TRUE(ref->copy()->same(host1.get()));

  // Interact with the Global.
  Val args[2];
  Val results[1];
91
  own<Trap> trap = global_get->call(nullptr, results);
92 93 94 95 96 97 98 99 100 101 102 103 104 105
  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()));
106
  args[0] = Val::ref(own<Ref>());
107 108 109 110 111 112
  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());

113 114 115 116 117 118 119
  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()));

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
  // 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);
146
  args[1] = Val::ref(own<Ref>());
147 148 149 150 151 152
  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());

153 154 155 156 157 158 159 160
  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()));

161
  // Interact with the Function.
162
  args[0] = Val::ref(own<Ref>());
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
  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