Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[JSC] Add support for Atomics.waitAsync
https://bugs.webkit.org/show_bug.cgi?id=241414 rdar://94655073 Reviewed by Yusuke Suzuki. Atomics.waitAsync() waits asynchronously on a shared array buffer and returns an object { async: bool, value: Promise }. Compare to Atomics.wait(), waitAsync is non-blocking and usable on the main thread. TC39 Spec: https://tc39.es/proposal-atomics-wait-async/ TC39 Proposal: https://github.com/tc39/proposal-atomics-wait-async MDN Web Doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/waitAsync * JSTests/stress/settimeout-starvation.js: Added. (let.promise.new.Promise): (wait): * JSTests/test262/config.yaml: * Source/JavaScriptCore/jsc.cpp: (JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/AtomicsObject.cpp: (JSC::atomicsWaitImpl): (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/Intrinsic.cpp: (JSC::intrinsicName): * Source/JavaScriptCore/runtime/Intrinsic.h: * Source/JavaScriptCore/runtime/JSArrayBufferView.h: (JSC::JSArrayBufferView::hasArrayBuffer const): * Source/JavaScriptCore/runtime/JSGlobalObject.h: * Source/JavaScriptCore/runtime/SimpleTypedArrayController.cpp: (JSC::SimpleTypedArrayController::isAtomicsWaitAsyncAllowedOnCurrentThread): * Source/JavaScriptCore/runtime/SimpleTypedArrayController.h: * Source/JavaScriptCore/runtime/TypedArrayController.h: * Source/JavaScriptCore/runtime/VM.cpp: (JSC::VM::~VM): * Source/JavaScriptCore/runtime/WaiterListsManager.h: Added. (JSC::Waiter::Waiter): (JSC::Waiter::isAsync const): (JSC::Waiter::getVM const): (JSC::Waiter::getPromise const): (JSC::Waiter::getTicket const): (JSC::Waiter::dump const): (JSC::WaiterList::enqueue): (JSC::WaiterList::dequeue): (JSC::WaiterList::takeFirst): (JSC::WaiterList::isEmpty): (JSC::WaiterList::dump const): (JSC::WaiterListsManager::singleton): (JSC::WaiterListsManager::addWaiter): (JSC::WaiterListsManager::notifyWaiter): (JSC::WaiterListsManager::timeoutAsyncWaiter): (JSC::WaiterListsManager::unregister): (JSC::WaiterListsManager::dump const): (JSC::WaiterListsManager::RegisteredVMs::add): (JSC::WaiterListsManager::RegisteredVMs::remove): (JSC::WaiterListsManager::RegisteredVMs::contains): (JSC::WaiterListsManager::RegisteredVMs::dump const): (JSC::WaiterListsManager::notifyWaiterImpl): (JSC::WaiterListsManager::add): (JSC::WaiterListsManager::find): * Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp: (WebCore::WebCoreTypedArrayController::isAtomicsWaitAsyncAllowedOnCurrentThread): * Source/WebCore/bindings/js/WebCoreTypedArrayController.h: Canonical link: https://commits.webkit.org/257061@main
- Loading branch information
Yijia Huang
committed
Nov 28, 2022
1 parent
c8bde1b
commit 7e3fb31
Showing
32 changed files
with
1,283 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
let promise = new Promise((resolve, _) => { | ||
setTimeout(() => { resolve("timed-out") }, 1); | ||
}); | ||
let outcome = null; | ||
|
||
(function wait() { | ||
if (outcome === "timed-out") { | ||
return; | ||
} | ||
setTimeout(wait, 0); | ||
})(); | ||
|
||
promise.then(result => { outcome = result; }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
var sab = new SharedArrayBuffer(3 * 4); | ||
var i32a = new Int32Array(sab); | ||
|
||
var numWorkers = 0; | ||
function startWorker(code) { | ||
numWorkers++; | ||
$.agent.start(code); | ||
} | ||
|
||
const WAIT_INDEX = 0; | ||
const READY_INDEX_A = 1; | ||
const READY_INDEX_B = 2; | ||
const NOTIFY_COUNT = 2; | ||
|
||
startWorker(` | ||
$.agent.receiveBroadcast(async (sab) => { | ||
var i32a = new Int32Array(sab); | ||
let p = Atomics.waitAsync(i32a, ${WAIT_INDEX}, 0, undefined).value; | ||
Atomics.store(i32a, ${READY_INDEX_A}, 1); | ||
Atomics.notify(i32a, ${READY_INDEX_A}); | ||
let res = await p; | ||
if (res !== 'ok') | ||
throw new Error("A resolve: " + res); | ||
$.agent.report("done"); | ||
}); | ||
`); | ||
|
||
startWorker(` | ||
$.agent.receiveBroadcast(async (sab) => { | ||
var i32a = new Int32Array(sab); | ||
let p = Atomics.waitAsync(i32a, ${WAIT_INDEX}, 0, undefined).value; | ||
Atomics.store(i32a, ${READY_INDEX_B}, 1); | ||
Atomics.notify(i32a, ${READY_INDEX_B}); | ||
let res = await p; | ||
if (res !== 'ok') | ||
throw new Error("B resolve: " + res); | ||
$.agent.report("done"); | ||
}); | ||
`); | ||
|
||
startWorker(` | ||
$.agent.receiveBroadcast((sab) => { | ||
var i32a = new Int32Array(sab); | ||
Atomics.wait(i32a, ${READY_INDEX_A}, 0); | ||
Atomics.wait(i32a, ${READY_INDEX_B}, 0); | ||
let res = Atomics.notify(i32a, ${WAIT_INDEX}, ${NOTIFY_COUNT}); | ||
if (res !== 2) | ||
throw new Error("C notified workers: " + res); | ||
$.agent.report("done"); | ||
}); | ||
`); | ||
|
||
$.agent.broadcast(sab); | ||
|
||
for (; ;) { | ||
var report = waitForReport(); | ||
if (report == "done") { | ||
if (!--numWorkers) { | ||
print("All workers done!"); | ||
break; | ||
} | ||
} else | ||
print("report: " + report); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
var sab = new SharedArrayBuffer(3 * 4); | ||
var i32a = new Int32Array(sab); | ||
|
||
var numWorkers = 0; | ||
function startWorker(code) { | ||
numWorkers++; | ||
$.agent.start(code); | ||
} | ||
|
||
const WAIT_INDEX = 0; | ||
const TOTAL_WAITER_COUNT = 1; | ||
|
||
startWorker(` | ||
$.agent.receiveBroadcast((sab) => { | ||
(function() { | ||
var i32a = new Int32Array(sab); | ||
Atomics.waitAsync(i32a, ${WAIT_INDEX}, 0, 100).value.then((value) => { | ||
$.agent.report("value " + value); | ||
$.agent.report("done"); | ||
}, | ||
() => { | ||
$.agent.report("error"); | ||
}); | ||
})(); | ||
gc(); | ||
}); | ||
`); | ||
|
||
$.agent.broadcast(sab); | ||
|
||
let waiters = 0; | ||
do { | ||
waiters = waiterListSize(i32a, WAIT_INDEX); | ||
} while (waiters != TOTAL_WAITER_COUNT); | ||
|
||
if (Atomics.notify(i32a, WAIT_INDEX, 1) != TOTAL_WAITER_COUNT) | ||
throw new Error(`Atomics.notify should return ${TOTAL_WAITER_COUNT}.`); | ||
|
||
for (; ;) { | ||
var report = waitForReport(); | ||
if (report == "done") { | ||
if (!--numWorkers) { | ||
print("All workers done!"); | ||
break; | ||
} | ||
} else if (report.startsWith('value')) { | ||
if (report != 'value ok') | ||
throw new Error("The promise should be resolved with ok"); | ||
} else | ||
print("report: " + report); | ||
} | ||
|
||
if (waiterListSize(i32a, WAIT_INDEX) != 0) | ||
throw new Error("The WaiterList should be empty."); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
var sab = new SharedArrayBuffer(3 * 4); | ||
var i32a = new Int32Array(sab); | ||
|
||
var numWorkers = 0; | ||
function startWorker(code) { | ||
numWorkers++; | ||
$.agent.start(code); | ||
} | ||
|
||
const WAIT_INDEX = 0; | ||
const TOTAL_WAITER_COUNT = 1; | ||
|
||
startWorker(` | ||
$.agent.receiveBroadcast((sab) => { | ||
(function() { | ||
var i32a = new Int32Array(sab); | ||
Atomics.waitAsync(i32a, ${WAIT_INDEX}, 0).value.then((value) => { | ||
$.agent.report("value " + value); | ||
$.agent.report("done"); | ||
}, | ||
() => { | ||
$.agent.report("error"); | ||
}); | ||
})(); | ||
gc(); | ||
}); | ||
`); | ||
|
||
$.agent.broadcast(sab); | ||
|
||
let waiters = 0; | ||
do { | ||
waiters = waiterListSize(i32a, WAIT_INDEX); | ||
} while (waiters != TOTAL_WAITER_COUNT); | ||
|
||
if (Atomics.notify(i32a, WAIT_INDEX, 1) != TOTAL_WAITER_COUNT) | ||
throw new Error(`Atomics.notify should return ${TOTAL_WAITER_COUNT}.`); | ||
|
||
for (; ;) { | ||
var report = waitForReport(); | ||
if (report == "done") { | ||
if (!--numWorkers) { | ||
print("All workers done!"); | ||
break; | ||
} | ||
} else if (report.startsWith('value')) { | ||
if (report != 'value ok') | ||
throw new Error("The promise should be resolved with ok"); | ||
} else | ||
print("report: " + report); | ||
} | ||
|
||
if (waiterListSize(i32a, WAIT_INDEX) != 0) | ||
throw new Error("The WaiterList should be empty."); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
var sab = new SharedArrayBuffer(3 * 4); | ||
var i32a = new Int32Array(sab); | ||
|
||
var numWorkers = 0; | ||
function startWorker(code) { | ||
numWorkers++; | ||
$.agent.start(code); | ||
} | ||
|
||
const WAIT_INDEX = 0; | ||
|
||
startWorker(` | ||
$.agent.receiveBroadcast((unused_sab) => { | ||
(function() { | ||
var sab = new SharedArrayBuffer(8 * 4); | ||
var i32a = new Int32Array(sab); | ||
Atomics.waitAsync(i32a, ${WAIT_INDEX}, 0, 1).value.then((value) => { | ||
$.agent.report("value " + value); | ||
$.agent.report("done"); | ||
}, | ||
() => { | ||
$.agent.report("error"); | ||
}); | ||
})(); | ||
gc(); | ||
}); | ||
`); | ||
|
||
$.agent.broadcast(sab); | ||
|
||
for (; ;) { | ||
var report = waitForReport(); | ||
if (report == "done") { | ||
if (!--numWorkers) { | ||
print("All workers done!"); | ||
break; | ||
} | ||
} else if (report.startsWith('value')) { | ||
if (report != 'value timed-out') | ||
throw new Error("The promise should be resolved with timed-out"); | ||
} else | ||
print("report: " + report); | ||
} | ||
|
||
if (waiterListSize(i32a, WAIT_INDEX) != 0) | ||
throw new Error("The WaiterList should be empty."); |
Oops, something went wrong.