mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-25 17:53:53 +02:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			598 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			598 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2014 the V8 project authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| // Flags: --harmony-sharedarraybuffer
 | |
| //
 | |
| 
 | |
| function toRangeWrapped(value) {
 | |
|   var range = this.max - this.min + 1;
 | |
|   while (value < this.min) {
 | |
|     value += range;
 | |
|   }
 | |
|   while (value > this.max) {
 | |
|     value -= range;
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| 
 | |
| function makeConstructorObject(constr, min, max, toRange) {
 | |
|   var o = {constr: constr, min: min, max: max};
 | |
|   o.toRange = toRangeWrapped.bind(o);
 | |
|   return o;
 | |
| }
 | |
| 
 | |
| var IntegerTypedArrayConstructors = [
 | |
|   makeConstructorObject(Int8Array, -128, 127),
 | |
|   makeConstructorObject(Int16Array, -32768, 32767),
 | |
|   makeConstructorObject(Int32Array, -0x80000000, 0x7fffffff),
 | |
|   makeConstructorObject(Uint8Array, 0, 255),
 | |
|   makeConstructorObject(Uint16Array, 0, 65535),
 | |
|   makeConstructorObject(Uint32Array, 0, 0xffffffff),
 | |
| ];
 | |
| 
 | |
| (function TestBadArray() {
 | |
|   var ab = new ArrayBuffer(16);
 | |
|   var u32a = new Uint32Array(16);
 | |
|   var sab = new SharedArrayBuffer(128);
 | |
|   var sf32a = new Float32Array(sab);
 | |
|   var sf64a = new Float64Array(sab);
 | |
|   var u8ca = new Uint8ClampedArray(sab);
 | |
| 
 | |
|   // Atomic ops required integer shared typed arrays
 | |
|   var badArrayTypes = [
 | |
|     undefined, 1, 'hi', 3.4, ab, u32a, sab, sf32a, sf64a, u8ca
 | |
|   ];
 | |
|   badArrayTypes.forEach(function(o) {
 | |
|     assertThrows(function() { Atomics.compareExchange(o, 0, 0, 0); },
 | |
|                  TypeError);
 | |
|     assertThrows(function() { Atomics.load(o, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.store(o, 0, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.add(o, 0, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.sub(o, 0, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.and(o, 0, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.or(o, 0, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.xor(o, 0, 0); }, TypeError);
 | |
|     assertThrows(function() { Atomics.exchange(o, 0, 0); }, TypeError);
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestBadIndex() {
 | |
|   var sab = new SharedArrayBuffer(8);
 | |
|   var si32a = new Int32Array(sab);
 | |
|   var si32a2 = new Int32Array(sab, 4);
 | |
| 
 | |
|   // Indexes that are out of bounds when coerced via ToIndex should throw
 | |
|   // RangeError.
 | |
|   [-Infinity, Infinity].forEach(function(i) {
 | |
|     assertThrows(function() { Atomics.compareExchange(si32a, i, 0); },
 | |
|                  RangeError);
 | |
|     assertThrows(function() { Atomics.load(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.store(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.add(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.sub(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.and(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.or(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.xor(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.exchange(si32a, i, 0); }, RangeError);
 | |
|   }, RangeError);
 | |
| 
 | |
|   // Out-of-bounds indexes should throw RangeError.
 | |
|   [-1, 2, 100].forEach(function(i) {
 | |
|     assertThrows(function() { Atomics.compareExchange(si32a, i, 0, 0); },
 | |
|                  RangeError);
 | |
|     assertThrows(function() { Atomics.load(si32a, i); }, RangeError);
 | |
|     assertThrows(function() { Atomics.store(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.add(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.sub(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.and(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.or(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.xor(si32a, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.exchange(si32a, i, 0); }, RangeError);
 | |
|   }, RangeError);
 | |
| 
 | |
|   // Out-of-bounds indexes for array with offset should throw RangeError.
 | |
|   [-1, 1, 100].forEach(function(i) {
 | |
|     assertThrows(function() { Atomics.compareExchange(si32a2, i, 0, 0); });
 | |
|     assertThrows(function() { Atomics.load(si32a2, i); }, RangeError);
 | |
|     assertThrows(function() { Atomics.store(si32a2, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.add(si32a2, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.sub(si32a2, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.and(si32a2, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.or(si32a2, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.xor(si32a2, i, 0); }, RangeError);
 | |
|     assertThrows(function() { Atomics.exchange(si32a2, i, 0); }, RangeError);
 | |
|   });
 | |
| 
 | |
|   // Monkey-patch length and make sure these functions still throw.
 | |
|   Object.defineProperty(si32a, 'length', {get: function() { return 1000; }});
 | |
|   [2, 100].forEach(function(i) {
 | |
|     assertThrows(function() { Atomics.compareExchange(si32a, i, 0, 0); });
 | |
|     assertThrows(function() { Atomics.load(si32a, i); });
 | |
|     assertThrows(function() { Atomics.store(si32a, i, 0); });
 | |
|     assertThrows(function() { Atomics.add(si32a, i, 0); });
 | |
|     assertThrows(function() { Atomics.sub(si32a, i, 0); });
 | |
|     assertThrows(function() { Atomics.and(si32a, i, 0); });
 | |
|     assertThrows(function() { Atomics.or(si32a, i, 0); });
 | |
|     assertThrows(function() { Atomics.xor(si32a, i, 0); });
 | |
|     assertThrows(function() { Atomics.exchange(si32a, i, 0); });
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestGoodIndex() {
 | |
|   var sab = new SharedArrayBuffer(64);
 | |
|   var si32a = new Int32Array(sab);
 | |
|   var si32a2 = new Int32Array(sab, 32);
 | |
| 
 | |
|   var testOp = function(op, ia, index, expectedIndex, name) {
 | |
|     for (var i = 0; i < ia.length; ++i)
 | |
|       ia[i] = i * 2;
 | |
| 
 | |
|     ia[expectedIndex] = 0;
 | |
|     var result = op(ia, index, 0, 0);
 | |
|     assertEquals(0, result, name);
 | |
|     assertEquals(0, ia[expectedIndex], name);
 | |
| 
 | |
|     for (var i = 0; i < ia.length; ++i) {
 | |
|       if (i == expectedIndex) continue;
 | |
|       assertEquals(i * 2, ia[i], name);
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   // These values all map to index 0
 | |
|   [-0, 0, 0.0, null, false, NaN, {}, '0.2', 'hi', undefined].forEach(
 | |
|       function(i) {
 | |
|     var name = String(i);
 | |
|     [si32a, si32a2].forEach(function(array) {
 | |
|       testOp(Atomics.compareExchange, array, i, 0, name);
 | |
|       testOp(Atomics.load, array, i, 0, name);
 | |
|       testOp(Atomics.store, array, i, 0, name);
 | |
|       testOp(Atomics.add, array, i, 0, name);
 | |
|       testOp(Atomics.sub, array, i, 0, name);
 | |
|       testOp(Atomics.and, array, i, 0, name);
 | |
|       testOp(Atomics.or, array, i, 0, name);
 | |
|       testOp(Atomics.xor, array, i, 0, name);
 | |
|       testOp(Atomics.exchange, array, i, 0, name);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   // These values all map to index 3
 | |
|   var valueOf = {valueOf: function(){ return 3;}};
 | |
|   var toString = {toString: function(){ return '3';}};
 | |
|   [3, 3.0, '3', '3.0', valueOf, toString].forEach(function(i) {
 | |
|     var name = String(i);
 | |
|     [si32a, si32a2].forEach(function(array) {
 | |
|       testOp(Atomics.compareExchange, array, i, 3, name);
 | |
|       testOp(Atomics.load, array, i, 3, name);
 | |
|       testOp(Atomics.store, array, i, 3, name);
 | |
|       testOp(Atomics.add, array, i, 3, name);
 | |
|       testOp(Atomics.sub, array, i, 3, name);
 | |
|       testOp(Atomics.and, array, i, 3, name);
 | |
|       testOp(Atomics.or, array, i, 3, name);
 | |
|       testOp(Atomics.xor, array, i, 3, name);
 | |
|       testOp(Atomics.exchange, array, i, 3, name);
 | |
|     });
 | |
|   });
 | |
| })();
 | |
| 
 | |
| function clearArray(sab) {
 | |
|   var ui8 = new Uint8Array(sab);
 | |
|   for (var i = 0; i < sab.byteLength; ++i) {
 | |
|     ui8[i] = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| (function TestCompareExchange() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         // array[i] == 0, CAS will store
 | |
|         assertEquals(0, Atomics.compareExchange(array, i, 0, 50), name);
 | |
|         assertEquals(50, array[i], name);
 | |
| 
 | |
|         // array[i] == 50, CAS will not store
 | |
|         assertEquals(50, Atomics.compareExchange(array, i, 0, 100), name);
 | |
|         assertEquals(50, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestLoad() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         array[i] = 0;
 | |
|         assertEquals(0, Atomics.load(array, i), name);
 | |
|         array[i] = 50;
 | |
|         assertEquals(50, Atomics.load(array, i), name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| 
 | |
|   // Test Smi range
 | |
|   (function () {
 | |
|     var sab = new SharedArrayBuffer(4);
 | |
|     var i32 = new Int32Array(sab);
 | |
|     var u32 = new Uint32Array(sab);
 | |
| 
 | |
|     function testLoad(signedValue, unsignedValue) {
 | |
|       u32[0] = unsignedValue;
 | |
|       assertEquals(unsignedValue, Atomics.load(u32, 0));
 | |
|       assertEquals(signedValue, Atomics.load(i32, 0));
 | |
|     }
 | |
| 
 | |
|     testLoad(0x3fffffff,  0x3fffffff); // 2**30-1 (always smi)
 | |
|     testLoad(0x40000000,  0x40000000); // 2**30 (smi if signed and 32-bits)
 | |
|     testLoad(0x80000000, -0x80000000); // 2**31 (smi if signed and 32-bits)
 | |
|     testLoad(0xffffffff, -1);          // 2**31 (smi if signed)
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestStore() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         assertEquals(50, Atomics.store(array, i, 50), name);
 | |
|         assertEquals(50, array[i], name);
 | |
| 
 | |
|         assertEquals(100, Atomics.store(array, i, 100), name);
 | |
|         assertEquals(100, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestAdd() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         assertEquals(0, Atomics.add(array, i, 50), name);
 | |
|         assertEquals(50, array[i], name);
 | |
| 
 | |
|         assertEquals(50, Atomics.add(array, i, 70), name);
 | |
|         assertEquals(120, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestSub() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         array[i] = 120;
 | |
|         assertEquals(120, Atomics.sub(array, i, 50), name);
 | |
|         assertEquals(70, array[i], name);
 | |
| 
 | |
|         assertEquals(70, Atomics.sub(array, i, 70), name);
 | |
|         assertEquals(0, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestAnd() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(sta);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         array[i] = 0x3f;
 | |
|         assertEquals(0x3f, Atomics.and(array, i, 0x30), name);
 | |
|         assertEquals(0x30, array[i], name);
 | |
| 
 | |
|         assertEquals(0x30, Atomics.and(array, i, 0x20), name);
 | |
|         assertEquals(0x20, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestOr() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         array[i] = 0x30;
 | |
|         assertEquals(0x30, Atomics.or(array, i, 0x1c), name);
 | |
|         assertEquals(0x3c, array[i], name);
 | |
| 
 | |
|         assertEquals(0x3c, Atomics.or(array, i, 0x09), name);
 | |
|         assertEquals(0x3d, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestXor() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         array[i] = 0x30;
 | |
|         assertEquals(0x30, Atomics.xor(array, i, 0x1c), name);
 | |
|         assertEquals(0x2c, array[i], name);
 | |
| 
 | |
|         assertEquals(0x2c, Atomics.xor(array, i, 0x09), name);
 | |
|         assertEquals(0x25, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestExchange() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var sta2 = new t.constr(sab, 5 * t.constr.BYTES_PER_ELEMENT);
 | |
| 
 | |
|     [sta, sta2].forEach(function(array) {
 | |
|       clearArray(array.buffer);
 | |
|       var name = Object.prototype.toString.call(array);
 | |
|       for (var i = 0; i < array.length; ++i) {
 | |
|         array[i] = 0x30;
 | |
|         assertEquals(0x30, Atomics.exchange(array, i, 0x1c), name);
 | |
|         assertEquals(0x1c, array[i], name);
 | |
| 
 | |
|         assertEquals(0x1c, Atomics.exchange(array, i, 0x09), name);
 | |
|         assertEquals(0x09, array[i], name);
 | |
|       }
 | |
|     })
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestIsLockFree() {
 | |
|   // Various invalid cases.
 | |
|   var valueOf = {valueOf: function(){ return 3;}};
 | |
|   var toString = {toString: function(){ return '3';}};
 | |
|   var invalid = [3.14, 'foo', Infinity, NaN, false, undefined, valueOf,
 | |
|                  toString];
 | |
|   invalid.forEach(function(v) {
 | |
|     assertEquals(false, Atomics.isLockFree(v), JSON.stringify(v));
 | |
|   });
 | |
| 
 | |
|   // For all platforms we support, 1, 2 and 4 bytes should be lock-free.
 | |
|   assertEquals(true, Atomics.isLockFree(1));
 | |
|   assertEquals(true, Atomics.isLockFree(2));
 | |
|   assertEquals(true, Atomics.isLockFree(4));
 | |
| 
 | |
|   // Sizes that aren't equal to a typedarray BYTES_PER_ELEMENT always return
 | |
|   // false.
 | |
|   var validSizes = {};
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     validSizes[t.constr.BYTES_PER_ELEMENT] = true;
 | |
|   });
 | |
| 
 | |
|   for (var i = 0; i < 1000; ++i) {
 | |
|     if (!validSizes[i]) {
 | |
|       assertEquals(false, Atomics.isLockFree(i));
 | |
|     }
 | |
|   }
 | |
| })();
 | |
| 
 | |
| (function TestToNumber() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(1 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
| 
 | |
|     var valueOf = {valueOf: function(){ return 3;}};
 | |
|     var toString = {toString: function(){ return '3';}};
 | |
| 
 | |
|     [false, true, undefined, valueOf, toString].forEach(function(v) {
 | |
|       var name = Object.prototype.toString.call(sta) + ' - ' + v;
 | |
| 
 | |
|       // CompareExchange
 | |
|       sta[0] = 50;
 | |
|       assertEquals(50, Atomics.compareExchange(sta, 0, v, v), name);
 | |
| 
 | |
|       // Store
 | |
|       assertEquals(v|0, Atomics.store(sta, 0, v), name);
 | |
|       assertEquals(v|0, sta[0], name);
 | |
| 
 | |
|       // Add
 | |
|       sta[0] = 120;
 | |
|       assertEquals(120, Atomics.add(sta, 0, v), name);
 | |
|       assertEquals(120 + (v|0), sta[0], name);
 | |
| 
 | |
|       // Sub
 | |
|       sta[0] = 70;
 | |
|       assertEquals(70, Atomics.sub(sta, 0, v), name);
 | |
|       assertEquals(70 - (v|0), sta[0]);
 | |
| 
 | |
|       // And
 | |
|       sta[0] = 0x20;
 | |
|       assertEquals(0x20, Atomics.and(sta, 0, v), name);
 | |
|       assertEquals(0x20 & (v|0), sta[0]);
 | |
| 
 | |
|       // Or
 | |
|       sta[0] = 0x3d;
 | |
|       assertEquals(0x3d, Atomics.or(sta, 0, v), name);
 | |
|       assertEquals(0x3d | (v|0), sta[0]);
 | |
| 
 | |
|       // Xor
 | |
|       sta[0] = 0x25;
 | |
|       assertEquals(0x25, Atomics.xor(sta, 0, v), name);
 | |
|       assertEquals(0x25 ^ (v|0), sta[0]);
 | |
| 
 | |
|       // Exchange
 | |
|       sta[0] = 0x09;
 | |
|       assertEquals(0x09, Atomics.exchange(sta, 0, v), name);
 | |
|       assertEquals(v|0, sta[0]);
 | |
|     });
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestWrapping() {
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var name = Object.prototype.toString.call(sta);
 | |
|     var range = t.max - t.min + 1;
 | |
|     var offset;
 | |
|     var operand;
 | |
|     var val, newVal;
 | |
|     var valWrapped, newValWrapped;
 | |
| 
 | |
|     for (offset = -range; offset <= range; offset += range) {
 | |
|       // CompareExchange
 | |
|       sta[0] = val = 0;
 | |
|       newVal = val + offset + 1;
 | |
|       newValWrapped = t.toRange(newVal);
 | |
|       assertEquals(val, Atomics.compareExchange(sta, 0, val, newVal), name);
 | |
|       assertEquals(newValWrapped, sta[0], name);
 | |
| 
 | |
|       sta[0] = val = t.min;
 | |
|       newVal = val + offset - 1;
 | |
|       newValWrapped = t.toRange(newVal);
 | |
|       assertEquals(val, Atomics.compareExchange(sta, 0, val, newVal), name);
 | |
|       assertEquals(newValWrapped, sta[0], name);
 | |
| 
 | |
|       // Store
 | |
|       sta[0] = 0;
 | |
|       val = t.max + offset + 1;
 | |
|       valWrapped = t.toRange(val);
 | |
|       assertEquals(val, Atomics.store(sta, 0, val), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       sta[0] = val = t.min + offset - 1;
 | |
|       valWrapped = t.toRange(val);
 | |
|       assertEquals(val, Atomics.store(sta, 0, val), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       // Add
 | |
|       sta[0] = val = t.max;
 | |
|       operand = offset + 1;
 | |
|       valWrapped = t.toRange(val + operand);
 | |
|       assertEquals(val, Atomics.add(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       sta[0] = val = t.min;
 | |
|       operand = offset - 1;
 | |
|       valWrapped = t.toRange(val + operand);
 | |
|       assertEquals(val, Atomics.add(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       // Sub
 | |
|       sta[0] = val = t.max;
 | |
|       operand = offset - 1;
 | |
|       valWrapped = t.toRange(val - operand);
 | |
|       assertEquals(val, Atomics.sub(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       sta[0] = val = t.min;
 | |
|       operand = offset + 1;
 | |
|       valWrapped = t.toRange(val - operand);
 | |
|       assertEquals(val, Atomics.sub(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       // There's no way to wrap results with logical operators, just test that
 | |
|       // using an out-of-range value is properly wrapped/clamped when written
 | |
|       // to memory.
 | |
| 
 | |
|       // And
 | |
|       sta[0] = val = 0xf;
 | |
|       operand = 0x3 + offset;
 | |
|       valWrapped = t.toRange(val & operand);
 | |
|       assertEquals(val, Atomics.and(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       // Or
 | |
|       sta[0] = val = 0x12;
 | |
|       operand = 0x22 + offset;
 | |
|       valWrapped = t.toRange(val | operand);
 | |
|       assertEquals(val, Atomics.or(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       // Xor
 | |
|       sta[0] = val = 0x12;
 | |
|       operand = 0x22 + offset;
 | |
|       valWrapped = t.toRange(val ^ operand);
 | |
|       assertEquals(val, Atomics.xor(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
| 
 | |
|       // Exchange
 | |
|       sta[0] = val = 0x12;
 | |
|       operand = 0x22 + offset;
 | |
|       valWrapped = t.toRange(operand);
 | |
|       assertEquals(val, Atomics.exchange(sta, 0, operand), name);
 | |
|       assertEquals(valWrapped, sta[0], name);
 | |
|     }
 | |
| 
 | |
|   });
 | |
| })();
 | |
| 
 | |
| (function TestValidateIndexBeforeValue() {
 | |
|   var testOp = function(op, sta, name) {
 | |
|     var valueof_has_been_called = 0;
 | |
|     var value = {valueOf: function() { valueof_has_been_called = 1; return 0;}};
 | |
|     var index = -1;
 | |
| 
 | |
|     // The index should be checked before calling ToInteger on the value, so
 | |
|     // valueof_has_been_called should not be modified.
 | |
|     sta[0] = 0;
 | |
|     assertThrows(function() { op(sta, index, value, value); }, RangeError);
 | |
|     assertEquals(0, valueof_has_been_called);
 | |
|   };
 | |
| 
 | |
|   IntegerTypedArrayConstructors.forEach(function(t) {
 | |
|     var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT);
 | |
|     var sta = new t.constr(sab);
 | |
|     var name = Object.prototype.toString.call(sta);
 | |
| 
 | |
|     testOp(Atomics.compareExchange, sta, name);
 | |
|     testOp(Atomics.load, sta, name);
 | |
|     testOp(Atomics.store, sta, name);
 | |
|     testOp(Atomics.add, sta, name);
 | |
|     testOp(Atomics.sub, sta, name);
 | |
|     testOp(Atomics.and, sta, name);
 | |
|     testOp(Atomics.or, sta, name);
 | |
|     testOp(Atomics.xor, sta, name);
 | |
|     testOp(Atomics.exchange, sta, name);
 | |
|   });
 | |
| })();
 |