growable-sab-memory-barrier-bytelength.js (1694B)
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) { 12 var ta = new Int32Array(gsab); 13 14 // Notify the main thread that the worker is ready. 15 Atomics.store(ta, 0, 1); 16 17 // Sleep to give the main thread time to execute and tier-up the loop. 18 Atomics.wait(ta, 1, 0, 500); 19 20 // Modify the memory read in the loop. 21 Atomics.store(ta, 2, 1); 22 23 // Sleep again to give the main thread time to execute the loop. 24 Atomics.wait(ta, 1, 0, 100); 25 26 // Grow the buffer. This modifies the loop condition. 27 gsab.grow(16); 28 } 29 30 var gsab = new SharedArrayBuffer(12, {maxByteLength: 16}); 31 32 // Pass |gsab| to the mailbox. 33 setSharedObject(gsab); 34 35 // Start the worker. 36 evalInWorker(` 37 (${worker})(getSharedObject()); 38 `); 39 40 // Wait until worker is ready. 41 var ta = new Int32Array(gsab); 42 while (Atomics.load(ta, 0) === 0); 43 44 return gsab; 45 } 46 47 function testGrowableSharedArrayBufferByteLength() { 48 var gsab = setup(); 49 var ta = new Int32Array(gsab); 50 var r = 0; 51 52 // |gsab.byteLength| is a seq-cst load, so it must prevent reordering any 53 // other loads, including unordered loads like |ta[2]|. 54 while (gsab.byteLength <= 12) { 55 // |ta[2]| is an unordered load, so it's hoistable by default. 56 r += ta[2]; 57 } 58 59 // The memory location is first modified and then the buffer is grown, so we 60 // must observe reads of the modified memory location before exiting the loop. 61 assertEq( 62 r > 0, 63 true, 64 "gsab.byteLength acts as a memory barrier, so ta[2] can't be hoisted" 65 ); 66 } 67 testGrowableSharedArrayBufferByteLength();