growable-sab-memory-barrier-dataview-bytelength.js (1685B)
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 testDataViewByteLength() { 48 var gsab = setup(); 49 var ta = new Int32Array(gsab); 50 var dv = new DataView(gsab); 51 var r = 0; 52 53 // |dv.byteLength| is a seq-cst load, so it must prevent reordering any other 54 // loads, including unordered loads like |ta[2]|. 55 while (dv.byteLength <= 12) { 56 // |ta[2]| is an unordered load, so it's hoistable by default. 57 r += ta[2]; 58 } 59 60 // The memory location is first modified and then the buffer is grown, so we 61 // must observe reads of the modified memory location before exiting the loop. 62 assertEq( 63 r > 0, 64 true, 65 "dv.byteLength acts as a memory barrier, so ta[2] can't be hoisted" 66 ); 67 } 68 testDataViewByteLength();