tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

growable-sab-memory-barrier-bytelength-with-non-growable-write.js (2658B)


      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 testGrowableSharedArrayBufferByteLength() {
     83  var {gsab, sab} = setup();
     84  var ta2 = new Int32Array(sab);
     85  var r = 0;
     86 
     87  // |gsab.byteLength| is a seq-cst load, so it must prevent reordering any
     88  // other loads, including unordered loads like |ta2[2]|.
     89  while (gsab.byteLength <= 12) {
     90    // |ta2[2]| is an unordered load, so it's hoistable by default.
     91    r += ta2[2];
     92  }
     93 
     94  // The memory location is first modified and then the buffer is grown, so we
     95  // must observe reads of the modified memory location before exiting the loop.
     96  assertEq(
     97    r > 0,
     98    true,
     99    "gsab.byteLength acts as a memory barrier, so ta2[2] can't be hoisted"
    100  );
    101 }
    102 testGrowableSharedArrayBufferByteLength();