summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/memory-cloning.js
blob: 12b05e4aab24ea92f80abe56dac9a72afe1bd41b (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
// |jit-test| skip-if: !wasmThreadsEnabled()

// Basic structured cloning tests (specific to SpiderMonkey shell)

var memtypes = wasmMemory64Enabled() ? ['i32', 'i64'] : [''];

function makeMemoryDesc(memtype, d) {
    if (memtype != '') {
        d.index = memtype;
    }
    return d;
}

function Zero(memtype) {
    return memtype == 'i64' ? 0n : 0;
}

// Should *not* be possible to serialize and deserialize memories that are not
// shared, whether we transfer them or not.

for ( let memtype of memtypes ) {
    let mem1 = new WebAssembly.Memory(makeMemoryDesc(memtype, {initial: 2, maximum: 4}));
    assertErrorMessage(() => serialize(mem1),
		       TypeError,
		       /unsupported type for structured data/);
    assertErrorMessage(() => serialize(mem1, [mem1]),
		       TypeError,
		       /invalid transferable array for structured clone/);
}

// Should be possible to serialize and deserialize memories that are shared, and
// observe shared effects.

for ( let memtype of memtypes ) {
    let ptrtype = memtype == 'i64' ? memtype : 'i32';
    let mem1 = new WebAssembly.Memory(makeMemoryDesc(memtype, {initial: 2, maximum: 4, shared: true}));
    let buf1 = mem1.buffer;

    // Serialization and deserialization of shared memories work:

    let mem2 = deserialize(serialize(mem1, [], {SharedArrayBuffer: 'allow'}), {SharedArrayBuffer: 'allow'});
    assertEq(mem2 instanceof WebAssembly.Memory, true);
    let buf2 = mem2.buffer;
    assertEq(buf2 instanceof SharedArrayBuffer, true);

    assertEq(buf1 !== buf2, true);
    assertEq(buf1.byteLength, buf2.byteLength);
    if (memtype != '' && mem2.type) {
        assertEq(mem2.type().index, memtype);
    }

    // Effects to one buffer must be reflected in the other:

    let v1 = new Int32Array(buf1);
    let v2 = new Int32Array(buf2);

    v1[37] = 0x12345678;
    assertEq(v2[37], 0x12345678);

    // Growth in a memory is reflected in its clone:

    let index = 2*65536 + 200;
    let access = wasmEvalText(`(module
				(memory (import "" "memory") ${memtype} 2 4 shared)
				(func (export "l") (result ${ptrtype})
				 (${ptrtype}.load (${ptrtype}.const ${index}))))`,
			      {"": {memory: mem2}}).exports.l;

    // initially mem2 cannot be accessed at index
    assertErrorMessage(access, WebAssembly.RuntimeError, /out of bounds/);

    // then we grow mem1
    wasmEvalText(`(module
		   (memory (import "" "memory") ${memtype} 2 4 shared)
		   (func (export "g") (drop (memory.grow (${ptrtype}.const 1)))))`,
		 {"": {memory: mem1}}).exports.g();

    // after growing mem1, mem2 can be accessed at index
    assertEq(access(), Zero(memtype));
}

// Should not be possible to transfer a shared memory

for ( let memtype of memtypes ) {
    let mem1 = new WebAssembly.Memory(makeMemoryDesc(memtype, {initial: 2, maximum: 4, shared: true}));
    assertErrorMessage(() => serialize(mem1, [mem1]),
		       TypeError,
		       /Shared memory objects must not be in the transfer list/);

}

// When serializing and deserializing a SAB extracted from a memory, the length
// of the SAB should not change even if the memory was grown after serialization
// and before deserialization.

for ( let memtype of memtypes ) {
    let mem = new WebAssembly.Memory(makeMemoryDesc(memtype, {initial: 2, maximum: 4, shared: true}));
    let buf = mem.buffer;
    let clonedbuf = serialize(buf, [], {SharedArrayBuffer: 'allow'});
    mem.grow(1);
    let buf2 = deserialize(clonedbuf, {SharedArrayBuffer: 'allow'});
    assertEq(buf.byteLength, buf2.byteLength);
}