growable-sab-memory-barrier-dataview-bytelength-with-non-growable-write.js (2649B)
1 // |jit-test| skip-if: helperThreadCount()===0 2 3 function setup() { 4 // Shared memory locations: 5 // 6 // 0: Lock 7 // 1: Sleep 8 // 2: Data 9 // 3: Unused 10 11 function worker(gsab, sab) { 12 var ta = new Int32Array(gsab); 13 var ta2 = new Int32Array(sab); 14 15 // Notify the main thread that the worker is ready. 16 Atomics.store(ta, 0, 1); 17 18 // Sleep to give the main thread time to execute and tier-up the loop. 19 Atomics.wait(ta, 1, 0, 500); 20 21 // Modify the memory read in the loop. 22 Atomics.store(ta2, 2, 1); 23 24 // Sleep again to give the main thread time to execute the loop. 25 Atomics.wait(ta, 1, 0, 100); 26 27 // Grow the buffer. This modifies the loop condition. 28 gsab.grow(16); 29 } 30 31 var gsab = new SharedArrayBuffer(12, {maxByteLength: 16}); 32 var sab = new SharedArrayBuffer(12); 33 34 // Start the worker. 35 { 36 let buffers = [gsab, sab]; 37 38 // Shared memory locations: 39 // 40 // 0: Number of buffers 41 // 1: Ready-Flag Worker 42 // 2: Ready-Flag Main 43 let sync = new Int32Array(new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT)); 44 sync[0] = buffers.length; 45 46 setSharedObject(sync.buffer); 47 48 evalInWorker(` 49 let buffers = []; 50 let sync = new Int32Array(getSharedObject()); 51 let n = sync[0]; 52 for (let i = 0; i < n; ++i) { 53 // Notify we're ready to receive. 54 Atomics.store(sync, 1, 1); 55 56 // Wait until buffer is in mailbox. 57 while (Atomics.compareExchange(sync, 2, 1, 0) !== 1); 58 59 buffers.push(getSharedObject()); 60 } 61 (${worker})(...buffers); 62 `); 63 64 for (let buffer of buffers) { 65 // Wait until worker is ready. 66 while (Atomics.compareExchange(sync, 1, 1, 0) !== 1); 67 68 setSharedObject(buffer); 69 70 // Notify buffer is in mailbox. 71 Atomics.store(sync, 2, 1); 72 } 73 } 74 75 // Wait until worker is ready. 76 var ta = new Int32Array(gsab); 77 while (Atomics.load(ta, 0) === 0); 78 79 return {gsab, sab}; 80 } 81 82 function testDataViewByteLength() { 83 var {gsab, sab} = setup(); 84 var dv = new DataView(gsab); 85 var ta2 = new Int32Array(sab); 86 var r = 0; 87 88 // |dv.byteLength| is a seq-cst load, so it must prevent reordering any other 89 // loads, including unordered loads like |ta2[2]|. 90 while (dv.byteLength <= 12) { 91 // |ta2[2]| is an unordered load, so it's hoistable by default. 92 r += ta2[2]; 93 } 94 95 // The memory location is first modified and then the buffer is grown, so we 96 // must observe reads of the modified memory location before exiting the loop. 97 assertEq( 98 r > 0, 99 true, 100 "dv.byteLength acts as a memory barrier, so ta2[2] can't be hoisted" 101 ); 102 } 103 testDataViewByteLength();