summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/simd/js-api.js
blob: 1bea3611edb4c76e52cd2bd0d312df70881ec787 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// |jit-test| test-also=--no-threads; skip-if: !wasmSimdEnabled()

// SIMD JS API
//
// As of 31 March 2020 the SIMD spec is very light on information about the JS
// API, and what it has is ridden with misspellings, grammatical errors, and
// apparent redundancies.  The rules below represent my best effort at
// understanding the intent of the spec.  As far as I can tell, the rules for
// v128 are intended to match the rules for i64 in the Wasm MVP.

// Hopefully, these are enough to test that various JIT stubs are generated and
// used if we run the tests in a loop.

setJitCompilerOption("baseline.warmup.trigger", 2);
setJitCompilerOption("ion.warmup.trigger", 4);

// RULE: v128 cannot cross the JS/wasm boundary as a function parameter.
//
// A wasm function that:
//  - takes or returns v128
//  - was imported into wasm
//  - is ultimately a JS function
// should always throw TypeError when called from wasm.
//
// Note, JIT exit stubs should be generated here because settings above should
// cause the JIT to tier up.

var ins = wasmEvalText(`
  (module
    (import "m" "v128_param" (func $f (param v128)))
    (import "m" "v128_return" (func $g (result v128)))
    (func (export "v128_param")
      (call $f (v128.const i32x4 0 0 0 0)))
    (func (export "v128_result")
      (drop (call $g))))`,
                       {m:{v128_param: (x) => 0,
                           v128_return: () => 0}});

function call_v128_param() { ins.exports.v128_param(); }
function call_v128_result() { ins.exports.v128_result(); }

for ( let i = 0 ; i < 100; i++ ) {
    assertErrorMessage(call_v128_param,
                       TypeError,
                       /cannot pass.*value.*to or from JS/);
    assertErrorMessage(call_v128_result,
                       TypeError,
                       /cannot pass.*value.*to or from JS/);
}

// RULE: v128 cannot cross the JS/wasm boundary as a function parameter.
//
// A wasm function that:
//  - takes or returns v128
//  - is exported from wasm
//  - is ultimately a true wasm function
// should always throw TypeError when called from JS.
//
// Note, JIT entry stubs should be generated here because settings above should
// cause the JIT to tier up.

var ins2 = wasmEvalText(`
  (module
    (func (export "v128_param") (param v128) (result i32)
      (i32.const 0))
    (func (export "v128_result") (result v128)
      (v128.const i32x4 0 0 0 0)))`);

function call_v128_param2() { ins2.exports.v128_param(); }
function call_v128_result2() { ins2.exports.v128_result(); }

for ( let i = 0 ; i < 100; i++ ) {
    assertErrorMessage(call_v128_param2,
                       TypeError,
                       /cannot pass.*value.*to or from JS/);
    assertErrorMessage(call_v128_result2,
                       TypeError,
                       /cannot pass.*value.*to or from JS/);
}

// RULE: The rules about v128 passing into or out of a function apply even when
// an imported JS function is re-exported and is then called.

var newfn = (x) => x;
var ins = wasmEvalText(`
  (module
    (import "m" "fn" (func $f (param v128) (result v128)))
    (export "newfn" (func $f)))`,
                                   {m:{fn: newfn}});
assertErrorMessage(() => ins.exports.newfn(3),
                   TypeError,
                   /cannot pass.*value.*to or from JS/);

// RULE: WebAssembly.Global of type v128 is constructable from JS with a default
// value.


// RULE: WebAssembly.Global constructor for type v128 is not constructable with
// or without a default value.

assertErrorMessage(() => new WebAssembly.Global({value: "v128"}, 37),
                   TypeError,
                   /cannot pass.*value.*to or from JS/);
assertErrorMessage(() => new WebAssembly.Global({value: "v128"}),
                   TypeError,
                   /cannot pass.*value.*to or from JS/);
assertErrorMessage(() => new WebAssembly.Global({value: "v128", mutable: true}),
                   TypeError,
                   /cannot pass.*value.*to or from JS/);

// RULE: WebAssembly.Global of type v128 have getters and setters that throw
// TypeError when called from JS.

let {gi, gm} = wasmEvalText(`
  (module
    (global (export "gi") v128 v128.const i64x2 0 0)
    (global (export "gm") (mut v128) v128.const i64x2 0 0)
  )`).exports;

assertErrorMessage(() => gi.value,
                   TypeError,
                   /cannot pass.*value.*to or from JS/);
assertErrorMessage(() => gi.valueOf(),
                   TypeError,
                   /cannot pass.*value.*to or from JS/);
assertErrorMessage(() => gm.value = 0,
                   TypeError,
                   /cannot pass.*value.*to or from JS/);