OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Flags: --harmony-atomics --harmony-shared-typed-arrays |
| 6 // |
| 7 (function TestBadArray() { |
| 8 var ab = new ArrayBuffer(16); |
| 9 var u32a = new Uint32Array(16); |
| 10 var sab = new SharedArrayBuffer(16); |
| 11 var sf32a = new SharedFloat32Array(16); |
| 12 var sf64a = new SharedFloat64Array(16); |
| 13 |
| 14 // Atomic ops required shared typed arrays |
| 15 [undefined, 1, 'hi', 3.4, ab, u32a, sab].forEach(function(o) { |
| 16 assertThrows(function() { Atomics.compareExchange(o, 0, 0, 0); }, |
| 17 TypeError); |
| 18 assertThrows(function() { Atomics.load(o, 0); }, TypeError); |
| 19 assertThrows(function() { Atomics.store(o, 0, 0); }, TypeError); |
| 20 assertThrows(function() { Atomics.add(o, 0, 0); }, TypeError); |
| 21 assertThrows(function() { Atomics.sub(o, 0, 0); }, TypeError); |
| 22 assertThrows(function() { Atomics.and(o, 0, 0); }, TypeError); |
| 23 assertThrows(function() { Atomics.or(o, 0, 0); }, TypeError); |
| 24 assertThrows(function() { Atomics.xor(o, 0, 0); }, TypeError); |
| 25 assertThrows(function() { Atomics.exchange(o, 0, 0); }, TypeError); |
| 26 }); |
| 27 |
| 28 // Arithmetic atomic ops require integer shared arrays |
| 29 [sab, sf32a, sf64a].forEach(function(o) { |
| 30 assertThrows(function() { Atomics.add(o, 0, 0); }, TypeError); |
| 31 assertThrows(function() { Atomics.sub(o, 0, 0); }, TypeError); |
| 32 assertThrows(function() { Atomics.and(o, 0, 0); }, TypeError); |
| 33 assertThrows(function() { Atomics.or(o, 0, 0); }, TypeError); |
| 34 assertThrows(function() { Atomics.xor(o, 0, 0); }, TypeError); |
| 35 assertThrows(function() { Atomics.exchange(o, 0, 0); }, TypeError); |
| 36 }); |
| 37 })(); |
| 38 |
| 39 (function TestBadIndex() { |
| 40 var si32a = new SharedInt32Array(16); |
| 41 |
| 42 // TODO(binji): shouldn't work for 0.5 either, currently busted |
| 43 [undefined, null, false, 'hi', {}, -100, 17].forEach(function(i) { |
| 44 assertEquals(undefined, Atomics.compareExchange(si32a, i, 0, 0), i); |
| 45 assertEquals(undefined, Atomics.load(si32a, i), i); |
| 46 assertEquals(undefined, Atomics.store(si32a, i, 0), i); |
| 47 assertEquals(undefined, Atomics.add(si32a, i, 0), i); |
| 48 assertEquals(undefined, Atomics.sub(si32a, i, 0), i); |
| 49 assertEquals(undefined, Atomics.and(si32a, i, 0), i); |
| 50 assertEquals(undefined, Atomics.or(si32a, i, 0), i); |
| 51 assertEquals(undefined, Atomics.xor(si32a, i, 0), i); |
| 52 assertEquals(undefined, Atomics.exchange(si32a, i, 0), i); |
| 53 }); |
| 54 })(); |
| 55 |
| 56 (function TestGoodIndex() { |
| 57 var si32a = new SharedInt32Array(16); |
| 58 |
| 59 // TODO(binji): should work for new Number(5) too, currently busted |
| 60 // TODO(binji): should work for {valueOf:function(){return 3;}} too |
| 61 [0, 15, '10'].forEach(function(i) { |
| 62 assertEquals(0, Atomics.compareExchange(si32a, i, 0, 0), i); |
| 63 assertEquals(0, Atomics.load(si32a, i), i); |
| 64 assertEquals(0, Atomics.store(si32a, i, 0), i); |
| 65 assertEquals(0, Atomics.add(si32a, i, 0), i); |
| 66 assertEquals(0, Atomics.sub(si32a, i, 0), i); |
| 67 assertEquals(0, Atomics.and(si32a, i, 0), i); |
| 68 assertEquals(0, Atomics.or(si32a, i, 0), i); |
| 69 assertEquals(0, Atomics.xor(si32a, i, 0), i); |
| 70 /* |
| 71 assertEquals(0, Atomics.exchange(si32a, i, 0), i); |
| 72 */ |
| 73 }); |
| 74 })(); |
| 75 |
| 76 (function TestCompareExchange() { |
| 77 var si8a = new SharedInt8Array(10); |
| 78 var si16a = new SharedInt16Array(10); |
| 79 var si32a = new SharedInt32Array(10); |
| 80 var su8a = new SharedUint8Array(10); |
| 81 var su16a = new SharedUint16Array(10); |
| 82 var su32a = new SharedUint32Array(10); |
| 83 var sf32a = new SharedFloat32Array(10); |
| 84 var sf64a = new SharedFloat64Array(10); |
| 85 // TODO(binji): SharedUint8ClampedArray? |
| 86 |
| 87 [si8a, si16a, si32a, su8a, su16a, su32a, sf32a, sf64a].forEach(function(sta) { |
| 88 var name = Object.prototype.toString.call(sta); |
| 89 for (var i = 0; i < 10; ++i) { |
| 90 // sta[i] == 0, CAS will store |
| 91 assertEquals(0, Atomics.compareExchange(sta, i, 0, 50), name); |
| 92 assertEquals(50, sta[i], name); |
| 93 |
| 94 // sta[i] == 50, CAS will not store |
| 95 assertEquals(50, Atomics.compareExchange(sta, i, 0, 100), name); |
| 96 assertEquals(50, sta[i], name); |
| 97 } |
| 98 }); |
| 99 |
| 100 // Check out-of-range values (should wrap) |
| 101 var integerTypes = [ |
| 102 {a: si8a, min: -128, max: 127}, |
| 103 {a: si16a, min: -32768, max: 32767}, |
| 104 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 105 {a: su8a, min: 0, max: 255}, |
| 106 {a: su16a, min: 0, max: 65535}, |
| 107 {a: su32a, min: 0, max: 0xffffffff}, |
| 108 ]; |
| 109 |
| 110 integerTypes.forEach(function(t) { |
| 111 var name = Object.prototype.toString.call(t.a); |
| 112 var range = t.max - t.min + 1; |
| 113 var add; |
| 114 var oldVal, oldValWrapped; |
| 115 var newVal, newValWrapped; |
| 116 |
| 117 for (add = -range; add <= range; add += range) { |
| 118 t.a[0] = oldVal = 0; |
| 119 newVal = t.max + add + 1; |
| 120 newValWrapped = t.min; |
| 121 assertEquals(oldVal, |
| 122 Atomics.compareExchange(t.a, 0, oldVal, newVal), name); |
| 123 assertEquals(newValWrapped, t.a[0], name); |
| 124 |
| 125 oldVal = newVal; |
| 126 oldValWrapped = newValWrapped; |
| 127 newVal = t.min + add - 1; |
| 128 newValWrapped = t.max; |
| 129 assertEquals(oldValWrapped, |
| 130 Atomics.compareExchange(t.a, 0, oldVal, newVal), name); |
| 131 assertEquals(newValWrapped, t.a[0], name); |
| 132 } |
| 133 }); |
| 134 |
| 135 // * Exact float values should be OK |
| 136 // * Infinity, -Infinity should be OK (has exact representation) |
| 137 // * NaN is not OK, it has many representations, cannot ensure successful CAS |
| 138 // because it does a bitwise compare |
| 139 [1.5, 4.25, -1e8, -Infinity, Infinity].forEach(function(v) { |
| 140 sf32a[0] = 0; |
| 141 assertEquals(0, Atomics.compareExchange(sf32a, 0, 0, v)); |
| 142 assertEquals(v, sf32a[0]); |
| 143 assertEquals(v, Atomics.compareExchange(sf32a, 0, v, 0)); |
| 144 assertEquals(0, sf32a[0]); |
| 145 |
| 146 sf64a[0] = 0; |
| 147 assertEquals(0, Atomics.compareExchange(sf64a, 0, 0, v)); |
| 148 assertEquals(v, sf64a[0]); |
| 149 assertEquals(v, Atomics.compareExchange(sf64a, 0, v, 0)); |
| 150 assertEquals(0, sf64a[0]); |
| 151 }); |
| 152 })(); |
| 153 |
| 154 (function TestLoad() { |
| 155 var si8a = new SharedInt8Array(10); |
| 156 var si16a = new SharedInt16Array(10); |
| 157 var si32a = new SharedInt32Array(10); |
| 158 var su8a = new SharedUint8Array(10); |
| 159 var su16a = new SharedUint16Array(10); |
| 160 var su32a = new SharedUint32Array(10); |
| 161 var sf32a = new SharedFloat32Array(10); |
| 162 var sf64a = new SharedFloat64Array(10); |
| 163 // TODO(binji): SharedUint8ClampedArray? |
| 164 |
| 165 [si8a, si16a, si32a, su8a, su16a, su32a, sf32a, sf64a].forEach(function(sta) { |
| 166 for (var i = 0; i < 10; ++i) { |
| 167 var name = Object.prototype.toString.call(sta); |
| 168 sta[i] = 0; |
| 169 assertEquals(0, Atomics.load(sta, i), name); |
| 170 sta[i] = 50; |
| 171 assertEquals(50, Atomics.load(sta, i), name); |
| 172 } |
| 173 }); |
| 174 })(); |
| 175 |
| 176 (function TestStore() { |
| 177 var si8a = new SharedInt8Array(10); |
| 178 var si16a = new SharedInt16Array(10); |
| 179 var si32a = new SharedInt32Array(10); |
| 180 var su8a = new SharedUint8Array(10); |
| 181 var su16a = new SharedUint16Array(10); |
| 182 var su32a = new SharedUint32Array(10); |
| 183 var sf32a = new SharedFloat32Array(10); |
| 184 var sf64a = new SharedFloat64Array(10); |
| 185 // TODO(binji): SharedUint8ClampedArray? |
| 186 |
| 187 [si8a, si16a, si32a, su8a, su16a, su32a, sf32a, sf64a].forEach(function(sta) { |
| 188 var name = Object.prototype.toString.call(sta); |
| 189 for (var i = 0; i < 10; ++i) { |
| 190 assertEquals(50, Atomics.store(sta, i, 50), name); |
| 191 assertEquals(50, sta[i], name); |
| 192 |
| 193 assertEquals(100, Atomics.store(sta, i, 100), name); |
| 194 assertEquals(100, sta[i], name); |
| 195 } |
| 196 }); |
| 197 |
| 198 // Check out-of-range values (should wrap stored value, but not wrap the |
| 199 // returned value) |
| 200 var integerTypes = [ |
| 201 {a: si8a, min: -128, max: 127}, |
| 202 {a: si16a, min: -32768, max: 32767}, |
| 203 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 204 {a: su8a, min: 0, max: 255}, |
| 205 {a: su16a, min: 0, max: 65535}, |
| 206 {a: su32a, min: 0, max: 0xffffffff}, |
| 207 ]; |
| 208 |
| 209 integerTypes.forEach(function(t) { |
| 210 var name = Object.prototype.toString.call(t.a); |
| 211 var range = t.max - t.min + 1; |
| 212 var add; |
| 213 var val, valWrapped; |
| 214 |
| 215 for (add = -range; add <= range; add += range) { |
| 216 t.a[0] = 0; |
| 217 val = t.max + add + 1; |
| 218 valWrapped = t.min; |
| 219 assertEquals(val, Atomics.store(t.a, 0, val), name); |
| 220 assertEquals(valWrapped, t.a[0], name); |
| 221 |
| 222 val = t.min + add - 1; |
| 223 valWrapped = t.max; |
| 224 assertEquals(val, Atomics.store(t.a, 0, val), name); |
| 225 assertEquals(valWrapped, t.a[0], name); |
| 226 } |
| 227 }); |
| 228 |
| 229 [1.5, 4.25, -1e8, -Infinity, Infinity, NaN].forEach(function(v) { |
| 230 sf32a[0] = 0; |
| 231 assertEquals(v, Atomics.store(sf32a, 0, v)); |
| 232 assertEquals(v, sf32a[0]); |
| 233 |
| 234 sf64a[0] = 0; |
| 235 assertEquals(v, Atomics.store(sf64a, 0, v)); |
| 236 assertEquals(v, sf64a[0]); |
| 237 }); |
| 238 })(); |
| 239 |
| 240 (function TestAdd() { |
| 241 var si8a = new SharedInt8Array(10); |
| 242 var si16a = new SharedInt16Array(10); |
| 243 var si32a = new SharedInt32Array(10); |
| 244 var su8a = new SharedUint8Array(10); |
| 245 var su16a = new SharedUint16Array(10); |
| 246 var su32a = new SharedUint32Array(10); |
| 247 // TODO(binji): SharedUint8ClampedArray? |
| 248 |
| 249 [si8a, si16a, si32a, su8a, su16a, su32a].forEach(function(sta) { |
| 250 var name = Object.prototype.toString.call(sta); |
| 251 for (var i = 0; i < 10; ++i) { |
| 252 assertEquals(0, Atomics.add(sta, i, 50), name); |
| 253 assertEquals(50, sta[i], name); |
| 254 |
| 255 assertEquals(50, Atomics.add(sta, i, 70), name); |
| 256 assertEquals(120, sta[i], name); |
| 257 } |
| 258 }); |
| 259 |
| 260 // Check out-of-range values (should wrap stored value, but not wrap the |
| 261 // returned value) |
| 262 var integerTypes = [ |
| 263 {a: si8a, min: -128, max: 127}, |
| 264 {a: si16a, min: -32768, max: 32767}, |
| 265 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 266 {a: su8a, min: 0, max: 255}, |
| 267 {a: su16a, min: 0, max: 65535}, |
| 268 {a: su32a, min: 0, max: 0xffffffff}, |
| 269 ]; |
| 270 |
| 271 integerTypes.forEach(function(t) { |
| 272 var name = Object.prototype.toString.call(t.a); |
| 273 var range = t.max - t.min + 1; |
| 274 var add; |
| 275 |
| 276 for (add = -range; add <= range; add += range) { |
| 277 t.a[0] = t.max; |
| 278 valWrapped = t.min; |
| 279 assertEquals(t.max, Atomics.add(t.a, 0, add + 1), name); |
| 280 assertEquals(t.min, t.a[0], name); |
| 281 |
| 282 assertEquals(t.min, Atomics.add(t.a, 0, add - 1), name); |
| 283 assertEquals(t.max, t.a[0], name); |
| 284 } |
| 285 }); |
| 286 })(); |
| 287 |
| 288 (function TestSub() { |
| 289 var si8a = new SharedInt8Array(10); |
| 290 var si16a = new SharedInt16Array(10); |
| 291 var si32a = new SharedInt32Array(10); |
| 292 var su8a = new SharedUint8Array(10); |
| 293 var su16a = new SharedUint16Array(10); |
| 294 var su32a = new SharedUint32Array(10); |
| 295 // TODO(binji): SharedUint8ClampedArray? |
| 296 |
| 297 [si8a, si16a, si32a, su8a, su16a, su32a].forEach(function(sta) { |
| 298 var name = Object.prototype.toString.call(sta); |
| 299 for (var i = 0; i < 10; ++i) { |
| 300 sta[i] = 120; |
| 301 assertEquals(120, Atomics.sub(sta, i, 50), name); |
| 302 assertEquals(70, sta[i], name); |
| 303 |
| 304 assertEquals(70, Atomics.sub(sta, i, 70), name); |
| 305 assertEquals(0, sta[i], name); |
| 306 } |
| 307 }); |
| 308 |
| 309 // Check out-of-range values (should wrap stored value, but not wrap the |
| 310 // returned value) |
| 311 var integerTypes = [ |
| 312 {a: si8a, min: -128, max: 127}, |
| 313 {a: si16a, min: -32768, max: 32767}, |
| 314 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 315 {a: su8a, min: 0, max: 255}, |
| 316 {a: su16a, min: 0, max: 65535}, |
| 317 {a: su32a, min: 0, max: 0xffffffff}, |
| 318 ]; |
| 319 |
| 320 integerTypes.forEach(function(t) { |
| 321 var name = Object.prototype.toString.call(t.a); |
| 322 var range = t.max - t.min + 1; |
| 323 var add; |
| 324 |
| 325 for (add = -range; add <= range; add += range) { |
| 326 t.a[0] = t.max; |
| 327 valWrapped = t.min; |
| 328 assertEquals(t.max, Atomics.sub(t.a, 0, add - 1), name); |
| 329 assertEquals(t.min, t.a[0], name); |
| 330 |
| 331 assertEquals(t.min, Atomics.sub(t.a, 0, add + 1), name); |
| 332 assertEquals(t.max, t.a[0], name); |
| 333 } |
| 334 }); |
| 335 })(); |
| 336 |
| 337 (function TestAnd() { |
| 338 var si8a = new SharedInt8Array(10); |
| 339 var si16a = new SharedInt16Array(10); |
| 340 var si32a = new SharedInt32Array(10); |
| 341 var su8a = new SharedUint8Array(10); |
| 342 var su16a = new SharedUint16Array(10); |
| 343 var su32a = new SharedUint32Array(10); |
| 344 // TODO(binji): SharedUint8ClampedArray? |
| 345 |
| 346 [si8a, si16a, si32a, su8a, su16a, su32a].forEach(function(sta) { |
| 347 var name = Object.prototype.toString.call(sta); |
| 348 for (var i = 0; i < 10; ++i) { |
| 349 sta[i] = 0x3f; |
| 350 assertEquals(0x3f, Atomics.and(sta, i, 0x30), name); |
| 351 assertEquals(0x30, sta[i], name); |
| 352 |
| 353 assertEquals(0x30, Atomics.and(sta, i, 0x20), name); |
| 354 assertEquals(0x20, sta[i], name); |
| 355 } |
| 356 }); |
| 357 |
| 358 // Check out-of-range values (should wrap stored value, but not wrap the |
| 359 // returned value) |
| 360 var integerTypes = [ |
| 361 {a: si8a, min: -128, max: 127}, |
| 362 {a: si16a, min: -32768, max: 32767}, |
| 363 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 364 {a: su8a, min: 0, max: 255}, |
| 365 {a: su16a, min: 0, max: 65535}, |
| 366 {a: su32a, min: 0, max: 0xffffffff}, |
| 367 ]; |
| 368 |
| 369 integerTypes.forEach(function(t) { |
| 370 var name = Object.prototype.toString.call(t.a); |
| 371 var range = t.max - t.min + 1; |
| 372 var add; |
| 373 |
| 374 // There's no way to wrap results with logical operators, just test that |
| 375 // using an out-of-range value is properly masked. |
| 376 for (add = -range; add <= range; add += range) { |
| 377 t.a[0] = 0xf; |
| 378 assertEquals(0xf, Atomics.and(t.a, 0, 0x3 + add), name); |
| 379 assertEquals(0x3, t.a[0], name); |
| 380 } |
| 381 }); |
| 382 })(); |
| 383 |
| 384 (function TestOr() { |
| 385 var si8a = new SharedInt8Array(10); |
| 386 var si16a = new SharedInt16Array(10); |
| 387 var si32a = new SharedInt32Array(10); |
| 388 var su8a = new SharedUint8Array(10); |
| 389 var su16a = new SharedUint16Array(10); |
| 390 var su32a = new SharedUint32Array(10); |
| 391 // TODO(binji): SharedUint8ClampedArray? |
| 392 |
| 393 [si8a, si16a, si32a, su8a, su16a, su32a].forEach(function(sta) { |
| 394 var name = Object.prototype.toString.call(sta); |
| 395 for (var i = 0; i < 10; ++i) { |
| 396 sta[i] = 0x30; |
| 397 assertEquals(0x30, Atomics.or(sta, i, 0x1c), name); |
| 398 assertEquals(0x3c, sta[i], name); |
| 399 |
| 400 assertEquals(0x3c, Atomics.or(sta, i, 0x09), name); |
| 401 assertEquals(0x3d, sta[i], name); |
| 402 } |
| 403 }); |
| 404 |
| 405 // Check out-of-range values (should wrap stored value, but not wrap the |
| 406 // returned value) |
| 407 var integerTypes = [ |
| 408 {a: si8a, min: -128, max: 127}, |
| 409 {a: si16a, min: -32768, max: 32767}, |
| 410 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 411 {a: su8a, min: 0, max: 255}, |
| 412 {a: su16a, min: 0, max: 65535}, |
| 413 {a: su32a, min: 0, max: 0xffffffff}, |
| 414 ]; |
| 415 |
| 416 integerTypes.forEach(function(t) { |
| 417 var name = Object.prototype.toString.call(t.a); |
| 418 var range = t.max - t.min + 1; |
| 419 var add; |
| 420 |
| 421 // There's no way to wrap results with logical operators, just test that |
| 422 // using an out-of-range value is properly masked. |
| 423 for (add = -range; add <= range; add += range) { |
| 424 t.a[0] = 0x12; |
| 425 assertEquals(0x12, Atomics.or(t.a, 0, 0x22 + add), name); |
| 426 assertEquals(0x32, t.a[0], name); |
| 427 } |
| 428 }); |
| 429 })(); |
| 430 |
| 431 (function TestXor() { |
| 432 var si8a = new SharedInt8Array(10); |
| 433 var si16a = new SharedInt16Array(10); |
| 434 var si32a = new SharedInt32Array(10); |
| 435 var su8a = new SharedUint8Array(10); |
| 436 var su16a = new SharedUint16Array(10); |
| 437 var su32a = new SharedUint32Array(10); |
| 438 // TODO(binji): SharedUint8ClampedArray? |
| 439 |
| 440 [si8a, si16a, si32a, su8a, su16a, su32a].forEach(function(sta) { |
| 441 var name = Object.prototype.toString.call(sta); |
| 442 for (var i = 0; i < 10; ++i) { |
| 443 sta[i] = 0x30; |
| 444 assertEquals(0x30, Atomics.xor(sta, i, 0x1c), name); |
| 445 assertEquals(0x2c, sta[i], name); |
| 446 |
| 447 assertEquals(0x2c, Atomics.xor(sta, i, 0x09), name); |
| 448 assertEquals(0x25, sta[i], name); |
| 449 } |
| 450 }); |
| 451 |
| 452 // Check out-of-range values (should wrap stored value, but not wrap the |
| 453 // returned value) |
| 454 var integerTypes = [ |
| 455 {a: si8a, min: -128, max: 127}, |
| 456 {a: si16a, min: -32768, max: 32767}, |
| 457 {a: si32a, min: -0x80000000, max: 0x7fffffff}, |
| 458 {a: su8a, min: 0, max: 255}, |
| 459 {a: su16a, min: 0, max: 65535}, |
| 460 {a: su32a, min: 0, max: 0xffffffff}, |
| 461 ]; |
| 462 |
| 463 integerTypes.forEach(function(t) { |
| 464 var name = Object.prototype.toString.call(t.a); |
| 465 var range = t.max - t.min + 1; |
| 466 var add; |
| 467 |
| 468 // There's no way to wrap results with logical operators, just test that |
| 469 // using an out-of-range value is properly masked. |
| 470 for (add = -range; add <= range; add += range) { |
| 471 t.a[0] = 0x12; |
| 472 assertEquals(0x12, Atomics.xor(t.a, 0, 0x22 + add), name); |
| 473 assertEquals(0x30, t.a[0], name); |
| 474 } |
| 475 }); |
| 476 })(); |
OLD | NEW |