anyfunc.js 7 KB
Newer Older
1 2 3 4
// 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.

5
// Flags: --expose-wasm --experimental-wasm-reftypes --expose-gc
6

7
load('test/mjsunit/wasm/wasm-module-builder.js');
8

9
(function testAnyFuncIdentityFunction() {
10 11 12
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  builder.addFunction('main', kSig_a_a)
13
      .addBody([kExprLocalGet, 0])
14 15 16 17 18
      .exportFunc();

  const instance = builder.instantiate();

  assertThrows(() => instance.exports.main(print), TypeError);
19
  assertThrows(() => instance.exports.main({'hello': 'world'}), TypeError);
20 21 22 23
  assertSame(
      instance.exports.main, instance.exports.main(instance.exports.main));
})();

24
(function testPassAnyFuncToImportedFunction() {
25 26 27
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_v_a);
28
  const imp_index = builder.addImport('q', 'func', sig_index);
29
  builder.addFunction('main', sig_index)
30
      .addBody([kExprLocalGet, 0, kExprCallFunction, imp_index])
31 32 33 34 35 36 37 38 39 40
      .exportFunc();

  const main = builder.instantiate({q: {func: checkFunction}}).exports.main;

  function checkFunction(value) {
    assertSame(main, value);
  }

  main(main);
})();
41

42
(function testPassAnyFuncWithGCWithLocals() {
43 44 45 46
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const ref_sig = builder.addType(kSig_v_a);
  const void_sig = builder.addType(kSig_v_v);
47 48
  const imp_index = builder.addImport('q', 'func', ref_sig);
  const gc_index = builder.addImport('q', 'gc', void_sig);
49 50 51 52
  // First call the gc, then check if the object still exists.
  builder.addFunction('main', ref_sig)
      .addLocals({anyfunc_count: 10})
      .addBody([
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
        kExprLocalGet,     0,
        kExprLocalSet,     1,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     2,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     3,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     4,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     5,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     6,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     7,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     8,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     9,  // Set local
        kExprLocalGet,     0,
        kExprLocalSet,     10,        // Set local
73
        kExprCallFunction, gc_index,  // call gc
74
        kExprLocalGet,     9,
75
        kExprCallFunction, imp_index  // call import
76 77 78 79 80 81 82 83 84 85 86 87 88
      ])
      .exportFunc();

  const main =
      builder.instantiate({q: {func: checkFunction, gc: gc}}).exports.main;

  function checkFunction(value) {
    assertSame(main, value);
  }

  main(main);
})();

89
(function testPassAnyFuncWithGC() {
90 91 92 93
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const ref_sig = builder.addType(kSig_v_a);
  const void_sig = builder.addType(kSig_v_v);
94 95
  const imp_index = builder.addImport('q', 'func', ref_sig);
  const gc_index = builder.addImport('q', 'gc', void_sig);
96 97 98 99
  // First call the gc, then check if the object still exists.
  builder.addFunction('main', ref_sig)
      .addBody([
        kExprCallFunction, gc_index,                    // call gc
100
        kExprLocalGet, 0, kExprCallFunction, imp_index  // call import
101 102 103 104 105 106 107
      ])
      .exportFunc();

  function checkFunction(value) {
    assertSame(main, value);
  }

108 109
  const main =
      builder.instantiate({q: {func: checkFunction, gc: gc}}).exports.main;
110 111 112 113

  main(main);
})();

114
(function testPassAnyFuncWithGCInWrapper() {
115 116
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
117 118
  const kSig_a_iai =
      makeSig([kWasmI32, kWasmAnyFunc, kWasmI32], [kWasmAnyFunc]);
119 120
  const sig_index = builder.addType(kSig_a_iai);
  builder.addFunction('main', sig_index)
121
      .addBody([kExprLocalGet, 1])
122 123 124 125 126 127 128 129 130 131 132 133 134 135
      .exportFunc();

  const main = builder.instantiate().exports.main;

  const triggerGCParam = {
    valueOf: () => {
      gc();
      return 17;
    }
  };

  const result = main(triggerGCParam, main, triggerGCParam);
  assertSame(main, result);
})();
136 137 138 139 140 141 142

(function testAnyFuncDefaultValue() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_v);
  builder.addFunction('main', sig_index)
      .addLocals({anyfunc_count: 1})
143
      .addBody([kExprLocalGet, 0])
144 145 146 147 148
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();
149

150
(function testAssignNullToAnyFuncLocal() {
151 152 153 154
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_a);
  builder.addFunction('main', sig_index)
155
      .addBody([kExprRefNull, kWasmAnyFunc, kExprLocalSet, 0, kExprLocalGet, 0])
156 157 158 159 160 161
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main(main));
})();

162
(function testImplicitReturnNullAsAnyFunc() {
163 164 165
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_v);
166 167 168
  builder.addFunction('main', sig_index)
      .addBody([kExprRefNull, kWasmAnyFunc])
      .exportFunc();
169 170 171 172 173

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

174
(function testExplicitReturnNullAsAnyFunc() {
175 176 177 178
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_v);
  builder.addFunction('main', sig_index)
179
      .addBody([kExprRefNull, kWasmAnyFunc, kExprReturn])
180 181 182 183 184 185
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
(function testRefFuncOutOfBounds() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  builder.addFunction('main', kSig_a_v).addBody([kExprRefFunc, 10]);

  assertThrows(() => builder.toModule(), WebAssembly.CompileError);
})();

(function testRefFuncIsCallable() {
  print(arguments.callee.name);
  const expected = 54;
  const builder = new WasmModuleBuilder();
  const function_index = builder.addFunction('hidden', kSig_i_v)
                             .addBody([kExprI32Const, expected])
                             .index;
201
  builder.addDeclarativeElementSegment([function_index]);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
  builder.addFunction('main', kSig_a_v)
      .addBody([kExprRefFunc, function_index])
      .exportFunc();

  const instance = builder.instantiate();
  assertEquals(expected, instance.exports.main()());
})();

(function testRefFuncPreservesIdentity() {
  print(arguments.callee.name);
  const expected = 54;
  const builder = new WasmModuleBuilder();
  const foo = builder.addFunction('foo', kSig_i_v)
                  .addBody([kExprI32Const, expected])
                  .exportFunc();
217
  builder.addDeclarativeElementSegment([foo.index]);
218 219 220 221 222 223 224
  builder.addFunction('main', kSig_a_v)
      .addBody([kExprRefFunc, foo.index])
      .exportFunc();

  const instance = builder.instantiate();
  assertSame(instance.exports.foo, instance.exports.main());
})();