Commit 88724ec4 authored by binji's avatar binji Committed by Commit bot

[Atomics] Fix atomic access index validation

BUG=v8:4737
LOG=n
R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1676613002

Cr-Commit-Position: refs/heads/master@{#35074}
parent d4a391bb
......@@ -12,12 +12,14 @@
// Imports
var GlobalObject = global.Object;
var MakeRangeError;
var MakeTypeError;
var MaxSimple;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) {
MakeTypeError = from.MakeTypeError;
MakeRangeError = from.MakeRangeError;
MaxSimple = from.MaxSimple;
});
......@@ -37,14 +39,24 @@ function CheckSharedInteger32TypedArray(ia) {
}
}
// https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
function ValidateIndex(index, length) {
var numberIndex = TO_NUMBER(index);
var accessIndex = TO_INTEGER(numberIndex);
if (numberIndex !== accessIndex) {
throw MakeRangeError(kInvalidAtomicAccessIndex);
}
if (accessIndex < 0 || accessIndex >= length) {
throw MakeRangeError(kInvalidAtomicAccessIndex);
}
return accessIndex;
}
//-------------------------------------------------------------------
function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
CheckSharedIntegerTypedArray(sta);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(sta)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(sta));
oldValue = TO_NUMBER(oldValue);
newValue = TO_NUMBER(newValue);
return %_AtomicsCompareExchange(sta, index, oldValue, newValue);
......@@ -52,79 +64,55 @@ function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
function AtomicsLoadJS(sta, index) {
CheckSharedIntegerTypedArray(sta);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(sta)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(sta));
return %_AtomicsLoad(sta, index);
}
function AtomicsStoreJS(sta, index, value) {
CheckSharedIntegerTypedArray(sta);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(sta)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(sta));
value = TO_NUMBER(value);
return %_AtomicsStore(sta, index, value);
}
function AtomicsAddJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
value = TO_NUMBER(value);
return %_AtomicsAdd(ia, index, value);
}
function AtomicsSubJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
value = TO_NUMBER(value);
return %_AtomicsSub(ia, index, value);
}
function AtomicsAndJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
value = TO_NUMBER(value);
return %_AtomicsAnd(ia, index, value);
}
function AtomicsOrJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
value = TO_NUMBER(value);
return %_AtomicsOr(ia, index, value);
}
function AtomicsXorJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
value = TO_NUMBER(value);
return %_AtomicsXor(ia, index, value);
}
function AtomicsExchangeJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
value = TO_NUMBER(value);
return %_AtomicsExchange(ia, index, value);
}
......@@ -137,10 +125,7 @@ function AtomicsIsLockFreeJS(size) {
function AtomicsFutexWaitJS(ia, index, value, timeout) {
CheckSharedInteger32TypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
if (IS_UNDEFINED(timeout)) {
timeout = INFINITY;
} else {
......@@ -156,20 +141,17 @@ function AtomicsFutexWaitJS(ia, index, value, timeout) {
function AtomicsFutexWakeJS(ia, index, count) {
CheckSharedInteger32TypedArray(ia);
index = TO_INTEGER(index);
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
}
index = ValidateIndex(index, %_TypedArrayGetLength(ia));
count = MaxSimple(0, TO_INTEGER(count));
return %AtomicsFutexWake(ia, index, count);
}
function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
CheckSharedInteger32TypedArray(ia);
index1 = TO_INTEGER(index1);
index1 = ValidateIndex(index1, %_TypedArrayGetLength(ia));
count = MaxSimple(0, TO_INTEGER(count));
value = TO_INT32(value);
index2 = TO_INTEGER(index2);
index2 = ValidateIndex(index2, %_TypedArrayGetLength(ia));
if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
index2 < 0 || index2 >= %_TypedArrayGetLength(ia)) {
return UNDEFINED;
......
......@@ -187,12 +187,14 @@ function PostNatives(utils) {
"GetMethod",
"IsNaN",
"MakeError",
"MakeRangeError",
"MakeTypeError",
"MapEntries",
"MapIterator",
"MapIteratorNext",
"MaxSimple",
"MinSimple",
"NumberIsInteger",
"ObjectDefineProperty",
"ObserveArrayMethods",
"ObserveObjectMethods",
......
......@@ -1095,6 +1095,7 @@ utils.Export(function(to) {
to.IsFinite = GlobalIsFinite;
to.IsNaN = GlobalIsNaN;
to.NumberIsNaN = NumberIsNaN;
to.NumberIsInteger = NumberIsInteger;
to.ObjectDefineProperties = ObjectDefineProperties;
to.ObjectDefineProperty = ObjectDefineProperty;
to.ObjectHasOwnProperty = GlobalObject.prototype.hasOwnProperty;
......
......@@ -336,6 +336,7 @@ class CallSite {
T(InvalidArrayBufferLength, "Invalid array buffer length") \
T(ArrayBufferAllocationFailed, "Array buffer allocation failed") \
T(InvalidArrayLength, "Invalid array length") \
T(InvalidAtomicAccessIndex, "Invalid atomic access index") \
T(InvalidCodePoint, "Invalid code point %") \
T(InvalidCountValue, "Invalid count value") \
T(InvalidCurrencyCode, "Invalid currency code: %") \
......
......@@ -78,8 +78,8 @@ function testElementType(taConstr, f, offset) {
assertEquals(10, f(0, 10), name);
assertEquals(20, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
......
......@@ -79,8 +79,8 @@ function testElementType(taConstr, f, offset) {
assertEquals(0xf, f(0, 0x19), name);
assertEquals(0x9, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
......
......@@ -86,8 +86,8 @@ function testElementType(taConstr, f, oobValue, offset) {
assertEquals(50, f(0, 0, 100), name);
assertEquals(50, ta[0]);
// out of bounds
assertEquals(oobValue, f(-1, 0, 0), name);
assertEquals(oobValue, f(ta.length, 0, 0), name);
assertThrows(function() { f(-1, 0, 0); });
assertThrows(function() { f(ta.length, 0, 0); });
}
function testElement(m, offset) {
......
......@@ -80,8 +80,8 @@ function testElementType(taConstr, f, offset) {
assertEquals(0x7f, f(0, 0xf), name);
assertEquals(0xf, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
......
......@@ -62,7 +62,7 @@ function clearArray() {
}
}
function testElementType(taConstr, f, oobValue, offset) {
function testElementType(taConstr, f, offset) {
clearArray();
var ta = new taConstr(sab, offset);
......@@ -71,17 +71,17 @@ function testElementType(taConstr, f, oobValue, offset) {
assertEquals(10, f(0), name);
assertEquals(0, f(1), name);
// out of bounds
assertEquals(oobValue, f(-1), name);
assertEquals(oobValue, f(ta.length), name);
assertThrows(function() { f(-1); });
assertThrows(function() { f(ta.length); });
}
function testElement(m, offset) {
testElementType(Int8Array, m.loadi8, 0, offset);
testElementType(Int16Array, m.loadi16, 0, offset);
testElementType(Int32Array, m.loadi32, 0, offset);
testElementType(Uint8Array, m.loadu8, 0, offset);
testElementType(Uint16Array, m.loadu16, 0, offset);
testElementType(Uint32Array, m.loadu32, 0, offset);
testElementType(Int8Array, m.loadi8, offset);
testElementType(Int16Array, m.loadi16, offset);
testElementType(Int32Array, m.loadi32, offset);
testElementType(Uint8Array, m.loadu8, offset);
testElementType(Uint16Array, m.loadu16, offset);
testElementType(Uint32Array, m.loadu32, offset);
}
var offset = 0;
......
......@@ -81,8 +81,8 @@ function testElementType(taConstr, f, offset) {
assertEquals(0xf, f(0, 0x11), name);
assertEquals(0x1f, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
......
......@@ -68,7 +68,7 @@ function clearArray() {
}
}
function testElementType(taConstr, f, oobValue, offset) {
function testElementType(taConstr, f, offset) {
clearArray();
var ta = new taConstr(sab, offset);
......@@ -76,17 +76,17 @@ function testElementType(taConstr, f, oobValue, offset) {
assertEquals(10, f(0, 10), name);
assertEquals(10, ta[0]);
// out of bounds
assertEquals(oobValue, f(-1, 0), name);
assertEquals(oobValue, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
testElementType(Int8Array, m.storei8, 0, offset);
testElementType(Int16Array, m.storei16, 0, offset);
testElementType(Int32Array, m.storei32, 0, offset);
testElementType(Uint8Array, m.storeu8, 0, offset);
testElementType(Uint16Array, m.storeu16, 0, offset);
testElementType(Uint32Array, m.storeu32, 0, offset);
testElementType(Int8Array, m.storei8, offset);
testElementType(Int16Array, m.storei16, offset);
testElementType(Int32Array, m.storei32, offset);
testElementType(Uint8Array, m.storeu8, offset);
testElementType(Uint16Array, m.storeu16, offset);
testElementType(Uint32Array, m.storeu32, offset);
}
var offset = 0;
......
......@@ -79,8 +79,8 @@ function testElementType(taConstr, f, offset) {
assertEquals(20, f(0, 10), name);
assertEquals(10, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
......
......@@ -78,8 +78,8 @@ function testElementType(taConstr, f, offset) {
assertEquals(0xf, f(0, 0x11), name);
assertEquals(0x1e, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
assertThrows(function() { f(-1, 0); });
assertThrows(function() { f(ta.length, 0); });
}
function testElement(m, offset) {
......
......@@ -60,83 +60,65 @@ var IntegerTypedArrayConstructors = [
});
})();
function testAtomicOp(op, ia, index, expectedIndex, name) {
for (var i = 0; i < ia.length; ++i)
ia[i] = 22;
ia[expectedIndex] = 0;
assertEquals(0, op(ia, index, 0, 0), name);
assertEquals(0, ia[expectedIndex], name);
for (var i = 0; i < ia.length; ++i) {
if (i == expectedIndex) continue;
assertEquals(22, ia[i], name);
}
}
(function TestBadIndex() {
var sab = new SharedArrayBuffer(8);
var si32a = new Int32Array(sab);
var si32a2 = new Int32Array(sab, 4);
// Non-integer indexes are converted to an integer first, so they should all
// operate on index 0.
[undefined, null, false, 'hi', {}].forEach(function(i) {
var name = String(i);
testAtomicOp(Atomics.compareExchange, si32a, i, 0, name);
testAtomicOp(Atomics.load, si32a, i, 0, name);
testAtomicOp(Atomics.store, si32a, i, 0, name);
testAtomicOp(Atomics.add, si32a, i, 0, name);
testAtomicOp(Atomics.sub, si32a, i, 0, name);
testAtomicOp(Atomics.and, si32a, i, 0, name);
testAtomicOp(Atomics.or, si32a, i, 0, name);
testAtomicOp(Atomics.xor, si32a, i, 0, name);
testAtomicOp(Atomics.exchange, si32a, i, 0, name);
});
// Out-of-bounds indexes should return undefined.
// TODO(binji): Should these throw RangeError instead?
// Non-integer indexes should throw RangeError.
var nonInteger = [1.4, '1.4', NaN, -Infinity, Infinity, undefined, 'hi', {}];
nonInteger.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) {
var name = String(i);
assertEquals(undefined, Atomics.compareExchange(si32a, i, 0, 0), name);
assertEquals(undefined, Atomics.load(si32a, i), name);
assertEquals(undefined, Atomics.store(si32a, i, 0), name);
assertEquals(undefined, Atomics.add(si32a, i, 0), name);
assertEquals(undefined, Atomics.sub(si32a, i, 0), name);
assertEquals(undefined, Atomics.and(si32a, i, 0), name);
assertEquals(undefined, Atomics.or(si32a, i, 0), name);
assertEquals(undefined, Atomics.xor(si32a, i, 0), name);
assertEquals(undefined, Atomics.exchange(si32a, i, 0), name);
});
// Out-of-bounds indexes for offset-array
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) {
var name = String(i);
assertEquals(undefined, Atomics.compareExchange(si32a2, i, 0, 0), name);
assertEquals(undefined, Atomics.load(si32a2, i), name);
assertEquals(undefined, Atomics.store(si32a2, i, 0), name);
assertEquals(undefined, Atomics.add(si32a2, i, 0), name);
assertEquals(undefined, Atomics.sub(si32a2, i, 0), name);
assertEquals(undefined, Atomics.and(si32a2, i, 0), name);
assertEquals(undefined, Atomics.or(si32a2, i, 0), name);
assertEquals(undefined, Atomics.xor(si32a2, i, 0), name);
assertEquals(undefined, Atomics.exchange(si32a2, i, 0), name);
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 return undefined.
// Monkey-patch length and make sure these functions still throw.
Object.defineProperty(si32a, 'length', {get: function() { return 1000; }});
[2, 100].forEach(function(i) {
var name = String(i);
assertEquals(undefined, Atomics.compareExchange(si32a, i, 0, 0), name);
assertEquals(undefined, Atomics.load(si32a, i), name);
assertEquals(undefined, Atomics.store(si32a, i, 0), name);
assertEquals(undefined, Atomics.add(si32a, i, 0), name);
assertEquals(undefined, Atomics.sub(si32a, i, 0), name);
assertEquals(undefined, Atomics.and(si32a, i, 0), name);
assertEquals(undefined, Atomics.or(si32a, i, 0), name);
assertEquals(undefined, Atomics.xor(si32a, i, 0), name);
assertEquals(undefined, Atomics.exchange(si32a, i, 0), name);
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); });
});
})();
......@@ -145,22 +127,52 @@ function testAtomicOp(op, ia, index, expectedIndex, name) {
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] = 22;
ia[expectedIndex] = 0;
assertEquals(0, op(ia, index, 0, 0), name);
assertEquals(0, ia[expectedIndex], name);
for (var i = 0; i < ia.length; ++i) {
if (i == expectedIndex) continue;
assertEquals(22, ia[i], name);
}
};
// These values all map to index 0
[-0, 0, 0.0, null, false].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.5, '3', '3.5', valueOf, toString].forEach(function(i) {
[3, 3.0, '3', '3.0', valueOf, toString].forEach(function(i) {
var name = String(i);
[si32a, si32a2].forEach(function(array) {
testAtomicOp(Atomics.compareExchange, array, i, 3, name);
testAtomicOp(Atomics.load, array, i, 3, name);
testAtomicOp(Atomics.store, array, i, 3, name);
testAtomicOp(Atomics.add, array, i, 3, name);
testAtomicOp(Atomics.sub, array, i, 3, name);
testAtomicOp(Atomics.and, array, i, 3, name);
testAtomicOp(Atomics.or, array, i, 3, name);
testAtomicOp(Atomics.xor, array, i, 3, name);
testAtomicOp(Atomics.exchange, array, i, 3, name);
})
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);
});
});
})();
......
......@@ -51,24 +51,36 @@
// Valid indexes are 0-3.
[-1, 4, 100].forEach(function(invalidIndex) {
assertEquals(undefined, Atomics.futexWait(i32a, invalidIndex, 0));
assertEquals(undefined, Atomics.futexWake(i32a, invalidIndex, 0));
assertThrows(function() {
Atomics.futexWait(i32a, invalidIndex, 0);
}, RangeError);
assertThrows(function() {
Atomics.futexWake(i32a, invalidIndex, 0);
}, RangeError);
var validIndex = 0;
assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, invalidIndex, 0, 0,
validIndex));
assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, validIndex, 0, 0,
invalidIndex));
assertThrows(function() {
Atomics.futexWakeOrRequeue(i32a, invalidIndex, 0, 0, validIndex);
}, RangeError);
assertThrows(function() {
Atomics.futexWakeOrRequeue(i32a, validIndex, 0, 0, invalidIndex);
}, RangeError);
});
i32a = new Int32Array(sab, 8);
[-1, 2, 100].forEach(function(invalidIndex) {
assertEquals(undefined, Atomics.futexWait(i32a, invalidIndex, 0));
assertEquals(undefined, Atomics.futexWake(i32a, invalidIndex, 0));
assertThrows(function() {
Atomics.futexWait(i32a, invalidIndex, 0);
}, RangeError);
assertThrows(function() {
Atomics.futexWake(i32a, invalidIndex, 0);
}, RangeError);
var validIndex = 0;
assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, invalidIndex, 0, 0,
validIndex));
assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, validIndex, 0, 0,
invalidIndex));
assertThrows(function() {
Atomics.futexWakeOrRequeue(i32a, invalidIndex, 0, 0, validIndex);
}, RangeError);
assertThrows(function() {
Atomics.futexWakeOrRequeue(i32a, validIndex, 0, 0, invalidIndex);
}, RangeError);
});
})();
......
......@@ -6,4 +6,6 @@
var sab = new SharedArrayBuffer(8);
var ta = new Int32Array(sab);
ta.__defineSetter__('length', function() {;});
Atomics.compareExchange(ta, 4294967295, 0, 0);
assertThrows(function() {
Atomics.compareExchange(ta, 4294967295, 0, 0);
}, RangeError);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment