summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/TypedArray/sort_modifications_concurrent.js
blob: 99493df8004fa81f9620b1a7a650f816fca5040a (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// |reftest| skip-if(!xulRuntime.shell)

if (helperThreadCount() === 0) {
  if (typeof reportCompare === "function")
    reportCompare(true, true);
  quit();
}

const TAConstructors = [
  Int8Array,
  Uint8Array,
  Int16Array,
  Uint16Array,
  Int32Array,
  Uint32Array,
  Uint8ClampedArray,
  Float32Array,
  Float64Array,
  BigInt64Array,
  BigUint64Array,
];

// Use different size classes to catch any implementation-specific
// optimisations.
const sizes = [
  4, 8, 64, 128, 1024
];

function ToNumeric(TA) {
  if (TA === BigInt64Array || TA === BigUint64Array) {
    return BigInt;
  }
  return Number;
}

function ToAtomicTA(TA) {
  switch (TA) {
  case Int8Array:
  case Int16Array:
  case Int32Array:
  case Uint8Array:
  case Uint16Array:
  case Uint32Array:
  case BigInt64Array:
  case BigUint64Array:
    return TA;
  case Uint8ClampedArray:
    return Uint8Array;
  case Float32Array:
    return Uint32Array;
  case Float64Array:
    return BigUint64Array;
  }
  throw new Error("Invalid typed array kind");
}

function ascending(a, b) {
  return a < b ? -1 : a > b ? 1 : 0;
}

function descending(a, b) {
  return -ascending(a, b);
}

for (let TA of TAConstructors) {
  let toNumeric = ToNumeric(TA);
  for (let size of sizes) {
    let sorted = new TA(size);

    // Fill with |1..size| and then sort to account for wrap-arounds.
    for (let i = 0; i < size; ++i) {
      sorted[i] = toNumeric(i + 1);
    }
    sorted.sort();

    let extra = Math.max(TA.BYTES_PER_ELEMENT, Int32Array.BYTES_PER_ELEMENT);
    let buffer = new SharedArrayBuffer(size * TA.BYTES_PER_ELEMENT + extra);
    let controller = new Int32Array(buffer, 0, 1);

    // Create a copy in descending order.
    let ta = new TA(buffer, extra, size);
    ta.set(sorted)
    ta.sort(descending);

    // Worker code expects that the last element changes when sorted.
    assertEq(ta[size - 1] === sorted[size - 1], false);

    setSharedObject(buffer);

    evalInWorker(`
      const ToNumeric = ${ToNumeric};
      const ToAtomicTA = ${ToAtomicTA};
      const TA = ${TA.name};
      const AtomicTA = ToAtomicTA(TA);

      let size = ${size};
      let extra = ${extra};

      let toNumeric = ToNumeric(AtomicTA);
      let buffer = getSharedObject();
      let controller = new Int32Array(buffer, 0, 1);
      let ta = new AtomicTA(buffer, extra, size);

      let value = Atomics.load(ta, size - 1);

      // Coordinate with main thread.
      while (Atomics.notify(controller, 0, 1) < 1) ;

      // Wait until modification of the last element.
      //
      // Sorting writes in ascending indexed ordered, so when the last element
      // was modified, we know that the sort operation has finished.
      while (Atomics.load(ta, size - 1) === value) ;

      // Set all elements to zero.
      ta.fill(toNumeric(0));

      // Sleep for 50 ms.
      const amount = 0.05;

      // Coordinate with main thread.
      while (Atomics.notify(controller, 0, 1) < 1) {
        sleep(amount);
      }
    `);

    // Wait until worker is set-up.
    assertEq(Atomics.wait(controller, 0, 0), "ok");

    // Sort the array in ascending order.
    ta.sort();

    // Wait until worker has finished.
    assertEq(Atomics.wait(controller, 0, 0), "ok");

    // All elements have been set to zero.
    let zero = toNumeric(0);
    for (let i = 0; i < size; ++i) {
      assertEq(ta[i], zero, `${TA.name} at index ${i} for size ${size}`);
    }
  }
}

if (typeof reportCompare === "function")
  reportCompare(true, true);