Commit 154ddde4 authored by pan.deng's avatar pan.deng Committed by Commit bot

Support offset-TypedArray in futex API

BUG=v8:4555
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#32142}
parent a1ba971c
...@@ -262,7 +262,8 @@ Object* FutexEmulation::NumWaitersForTesting(Isolate* isolate, ...@@ -262,7 +262,8 @@ Object* FutexEmulation::NumWaitersForTesting(Isolate* isolate,
int waiters = 0; int waiters = 0;
FutexWaitListNode* node = wait_list_.Pointer()->head_; FutexWaitListNode* node = wait_list_.Pointer()->head_;
while (node) { while (node) {
if (backing_store == node->backing_store_ && addr == node->wait_addr_) { if (backing_store == node->backing_store_ && addr == node->wait_addr_ &&
node->waiting_) {
waiters++; waiters++;
} }
......
...@@ -30,7 +30,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexWait) { ...@@ -30,7 +30,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexWait) {
RUNTIME_ASSERT(timeout == V8_INFINITY || !std::isnan(timeout)); RUNTIME_ASSERT(timeout == V8_INFINITY || !std::isnan(timeout));
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr = index << 2; size_t addr = (index << 2) + NumberToSize(isolate, sta->byte_offset());
return FutexEmulation::Wait(isolate, array_buffer, addr, value, timeout); return FutexEmulation::Wait(isolate, array_buffer, addr, value, timeout);
} }
...@@ -47,7 +47,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexWake) { ...@@ -47,7 +47,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexWake) {
RUNTIME_ASSERT(sta->type() == kExternalInt32Array); RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr = index << 2; size_t addr = (index << 2) + NumberToSize(isolate, sta->byte_offset());
return FutexEmulation::Wake(isolate, array_buffer, addr, count); return FutexEmulation::Wake(isolate, array_buffer, addr, count);
} }
...@@ -67,8 +67,8 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexWakeOrRequeue) { ...@@ -67,8 +67,8 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexWakeOrRequeue) {
RUNTIME_ASSERT(sta->type() == kExternalInt32Array); RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr1 = index1 << 2; size_t addr1 = (index1 << 2) + NumberToSize(isolate, sta->byte_offset());
size_t addr2 = index2 << 2; size_t addr2 = (index2 << 2) + NumberToSize(isolate, sta->byte_offset());
return FutexEmulation::WakeOrRequeue(isolate, array_buffer, addr1, count, return FutexEmulation::WakeOrRequeue(isolate, array_buffer, addr1, count,
value, addr2); value, addr2);
...@@ -85,7 +85,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexNumWaitersForTesting) { ...@@ -85,7 +85,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsFutexNumWaitersForTesting) {
RUNTIME_ASSERT(sta->type() == kExternalInt32Array); RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr = index << 2; size_t addr = (index << 2) + NumberToSize(isolate, sta->byte_offset());
return FutexEmulation::NumWaitersForTesting(isolate, array_buffer, addr); return FutexEmulation::NumWaitersForTesting(isolate, array_buffer, addr);
} }
......
...@@ -46,7 +46,8 @@ ...@@ -46,7 +46,8 @@
})(); })();
(function TestInvalidIndex() { (function TestInvalidIndex() {
var i32a = new Int32Array(new SharedArrayBuffer(16)); var sab = new SharedArrayBuffer(16);
var i32a = new Int32Array(sab);
// Valid indexes are 0-3. // Valid indexes are 0-3.
[-1, 4, 100].forEach(function(invalidIndex) { [-1, 4, 100].forEach(function(invalidIndex) {
...@@ -59,6 +60,16 @@ ...@@ -59,6 +60,16 @@
invalidIndex)); invalidIndex));
}); });
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));
var validIndex = 0;
assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, invalidIndex, 0, 0,
validIndex));
assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, validIndex, 0, 0,
invalidIndex));
});
})(); })();
(function TestWaitTimeout() { (function TestWaitTimeout() {
...@@ -71,8 +82,13 @@ ...@@ -71,8 +82,13 @@
})(); })();
(function TestWaitNotEqual() { (function TestWaitNotEqual() {
var i32a = new Int32Array(new SharedArrayBuffer(16)); var sab = new SharedArrayBuffer(16);
var i32a = new Int32Array(sab);
assertEquals(Atomics.NOTEQUAL, Atomics.futexWait(i32a, 0, 42)); assertEquals(Atomics.NOTEQUAL, Atomics.futexWait(i32a, 0, 42));
i32a = new Int32Array(sab, 8);
i32a[0] = 1;
assertEquals(Atomics.NOTEQUAL, Atomics.futexWait(i32a, 0, 0));
})(); })();
(function TestWaitNegativeTimeout() { (function TestWaitNegativeTimeout() {
...@@ -90,14 +106,14 @@ if (this.Worker) { ...@@ -90,14 +106,14 @@ if (this.Worker) {
var i32a = new Int32Array(sab); var i32a = new Int32Array(sab);
var workerScript = var workerScript =
`onmessage = function(sab) { `onmessage = function(msg) {
var i32a = new Int32Array(sab); var i32a = new Int32Array(msg.sab, msg.offset);
var result = Atomics.futexWait(i32a, 0, 0, ${timeout}); var result = Atomics.futexWait(i32a, 0, 0, ${timeout});
postMessage(result); postMessage(result);
};`; };`;
var worker = new Worker(workerScript); var worker = new Worker(workerScript);
worker.postMessage(sab, [sab]); worker.postMessage({sab: sab, offset: offset}, [sab]);
// Spin until the worker is waiting on the futex. // Spin until the worker is waiting on the futex.
while (%AtomicsFutexNumWaitersForTesting(i32a, 0) != 1) {} while (%AtomicsFutexNumWaitersForTesting(i32a, 0) != 1) {}
...@@ -105,6 +121,29 @@ if (this.Worker) { ...@@ -105,6 +121,29 @@ if (this.Worker) {
Atomics.futexWake(i32a, 0, 1); Atomics.futexWake(i32a, 0, 1);
assertEquals(Atomics.OK, worker.getMessage()); assertEquals(Atomics.OK, worker.getMessage());
worker.terminate(); worker.terminate();
var worker2 = new Worker(workerScript);
var offset = 8;
var i32a2 = new Int32Array(sab, offset);
worker2.postMessage({sab: sab, offset: offset}, [sab]);
// Spin until the worker is waiting on the futex.
while (%AtomicsFutexNumWaitersForTesting(i32a2, 0) != 1) {}
Atomics.futexWake(i32a2, 0, 1);
assertEquals(Atomics.OK, worker2.getMessage());
worker2.terminate();
// Futex should work when index and buffer views are different, but
// the real address is the same.
var worker3 = new Worker(workerScript);
i32a2 = new Int32Array(sab, 4);
worker3.postMessage({sab: sab, offset: 8}, [sab]);
// Spin until the worker is waiting on the futex.
while (%AtomicsFutexNumWaitersForTesting(i32a2, 1) != 1) {}
Atomics.futexWake(i32a2, 1, 1);
assertEquals(Atomics.OK, worker3.getMessage());
worker3.terminate();
}; };
// Test various infinite timeouts // Test various infinite timeouts
...@@ -264,6 +303,33 @@ if (this.Worker) { ...@@ -264,6 +303,33 @@ if (this.Worker) {
assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index1)); assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index1));
assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index2)); assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index2));
for (id = 0; id < 4; ++id) {
assertEquals(Atomics.OK, workers[id].getMessage());
}
// Test futexWakeOrRequeue on offset typed array
var offset = 16;
sab = new SharedArrayBuffer(24);
i32a = new Int32Array(sab);
var i32a2 = new Int32Array(sab, offset);
for (id = 0; id < 4; id++) {
workers[id].postMessage({sab: sab, id: id}, [sab]);
}
while (%AtomicsFutexNumWaitersForTesting(i32a2, 0) != 4) { }
index1 = 0;
index2 = 1;
assertEquals(4, %AtomicsFutexNumWaitersForTesting(i32a2, index1));
assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a2, index2));
assertEquals(2, Atomics.futexWakeOrRequeue(i32a2, index1, 2, 0, index2));
assertEquals(2, %AtomicsFutexNumWaitersForTesting(i32a2, index2));
assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a2, index1));
assertEquals(2, Atomics.futexWake(i32a2, index2, 2));
for (id = 0; id < 4; ++id) { for (id = 0; id < 4; ++id) {
assertEquals(Atomics.OK, workers[id].getMessage()); assertEquals(Atomics.OK, workers[id].getMessage());
workers[id].terminate(); workers[id].terminate();
......
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