Skip to content

Commit 4eea7c6

Browse files
komygaapoalas
andauthored
Remove OS Thread from Atomics Wait Async (#989)
Co-authored-by: Aapo Alasuutari <aapo.alasuutari@gmail.com>
1 parent bece61a commit 4eea7c6

15 files changed

Lines changed: 227 additions & 118 deletions

File tree

.github/workflows/ci.yml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,30 @@ jobs:
3737
- name: Install Rust toolchain
3838
uses: dtolnay/rust-toolchain@nightly
3939
with:
40-
toolchain: nightly-2025-10-31
40+
toolchain: nightly-2026-05-28
4141
components: rustfmt, clippy, llvm-tools-preview, rustc-dev
4242
- name: Cache on ${{ github.ref_name }}
4343
uses: Swatinem/rust-cache@v2
4444
with:
4545
shared-key: warm
46-
- name: Install Dylint
47-
uses: taiki-e/install-action@v2
46+
# Build Dylint from crates.io instead of using prebuilt binaries: the
47+
# binaries attached to dylint's GitHub releases (since v6.0.1) are built
48+
# inside the dylint repo and bake in a path dependency on
49+
# /home/runner/work/dylint/dylint/driver, which breaks driver builds.
50+
- name: Install cargo-dylint
51+
uses: taiki-e/cache-cargo-install-action@v2
4852
with:
49-
tool: cargo-dylint,dylint-link
53+
tool: cargo-dylint@6.0.1
54+
- name: Install dylint-link
55+
uses: taiki-e/cache-cargo-install-action@v2
56+
with:
57+
tool: dylint-link@6.0.1
5058
- name: Check formatting
5159
run: cargo fmt --check
5260
- name: Clippy
5361
run: |
5462
cargo +stable clippy --all-targets -- -D warnings
55-
cargo +nightly-2025-10-31 clippy --all-targets --all-features -- -D warnings
63+
cargo +nightly-2026-05-28 clippy --all-targets --all-features -- -D warnings
5664
- name: Dylint tests
5765
working-directory: nova_lint
5866
run: cargo test

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ console = "=0.16.3"
2222
ctrlc = "=3.5.2"
2323
ecmascript_atomics = { version = "=0.2.3" }
2424
fast-float = "=0.2.0"
25-
hashbrown = "=0.17.0"
25+
hashbrown = "=0.17.1"
2626
lexical = { version = "=7.0.5", default-features = false, features = [
2727
"std",
2828
"write-integers",

nova_cli/src/lib/child_hooks.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010
collections::VecDeque,
1111
sync::{atomic::AtomicBool, mpsc},
1212
thread,
13-
time::Duration,
13+
time::{Duration, Instant},
1414
};
1515

1616
use nova_vm::ecmascript::{HostHooks, Job};
@@ -19,7 +19,7 @@ use crate::{ChildToHostMessage, HostToChildMessage};
1919

2020
pub struct CliChildHooks {
2121
promise_job_queue: RefCell<VecDeque<Job>>,
22-
macrotask_queue: RefCell<Vec<Job>>,
22+
macrotask_queue: RefCell<Vec<(Option<Instant>, Job)>>,
2323
pub(crate) receiver: mpsc::Receiver<HostToChildMessage>,
2424
pub(crate) host_sender: mpsc::SyncSender<ChildToHostMessage>,
2525
ready_to_leave: AtomicBool,
@@ -78,9 +78,11 @@ impl CliChildHooks {
7878
let mut counter = 0u8;
7979
while !off_thread_job_queue.is_empty() {
8080
counter = counter.wrapping_add(1);
81-
for (i, job) in off_thread_job_queue.iter().enumerate() {
82-
if job.is_finished() {
83-
let job = off_thread_job_queue.swap_remove(i);
81+
let now = Instant::now();
82+
for (i, (deadline, job)) in off_thread_job_queue.iter().enumerate() {
83+
let deadline_reached = deadline.is_none_or(|d| now >= d);
84+
if deadline_reached && job.is_finished() {
85+
let (_, job) = off_thread_job_queue.swap_remove(i);
8486
return Some(job);
8587
}
8688
}
@@ -96,14 +98,19 @@ impl CliChildHooks {
9698

9799
impl HostHooks for CliChildHooks {
98100
fn enqueue_generic_job(&self, job: Job) {
99-
self.macrotask_queue.borrow_mut().push(job);
101+
self.macrotask_queue.borrow_mut().push((None, job));
100102
}
101103

102104
fn enqueue_promise_job(&self, job: Job) {
103105
self.promise_job_queue.borrow_mut().push_back(job);
104106
}
105107

106-
fn enqueue_timeout_job(&self, _timeout_job: Job, _milliseconds: u64) {}
108+
fn enqueue_timeout_job(&self, timeout_job: Job, milliseconds: u64) {
109+
let deadline = Instant::now() + Duration::from_millis(milliseconds);
110+
self.macrotask_queue
111+
.borrow_mut()
112+
.push((Some(deadline), timeout_job));
113+
}
107114

108115
fn get_host_data(&self) -> &dyn std::any::Any {
109116
self

nova_cli/src/lib/host_hooks.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
//! The [`HostHooks`] implementation for the main thread.
66
77
use std::{
8-
cell::RefCell, collections::VecDeque, fmt::Debug, path::PathBuf, rc::Rc, sync::mpsc, thread,
9-
time::Duration,
8+
cell::RefCell,
9+
collections::VecDeque,
10+
fmt::Debug,
11+
path::PathBuf,
12+
rc::Rc,
13+
sync::mpsc,
14+
thread,
15+
time::{Duration, Instant},
1016
};
1117

1218
use nova_vm::{
@@ -29,7 +35,7 @@ pub enum ChildToHostMessage {
2935

3036
pub struct CliHostHooks {
3137
promise_job_queue: RefCell<VecDeque<Job>>,
32-
macrotask_queue: RefCell<Vec<Job>>,
38+
macrotask_queue: RefCell<Vec<(Option<Instant>, Job)>>,
3339
pub(crate) receiver: mpsc::Receiver<ChildToHostMessage>,
3440
pub(crate) own_sender: mpsc::SyncSender<ChildToHostMessage>,
3541
pub(crate) child_senders: RefCell<Vec<mpsc::SyncSender<HostToChildMessage>>>,
@@ -83,9 +89,11 @@ impl CliHostHooks {
8389
let mut counter = 0u8;
8490
while !off_thread_job_queue.is_empty() {
8591
counter = counter.wrapping_add(1);
86-
for (i, job) in off_thread_job_queue.iter().enumerate() {
87-
if job.is_finished() {
88-
let job = off_thread_job_queue.swap_remove(i);
92+
let now = Instant::now();
93+
for (i, (deadline, job)) in off_thread_job_queue.iter().enumerate() {
94+
let deadline_reached = deadline.is_none_or(|d| now >= d);
95+
if deadline_reached && job.is_finished() {
96+
let (_, job) = off_thread_job_queue.swap_remove(i);
8997
return Some(job);
9098
}
9199
}
@@ -101,14 +109,19 @@ impl CliHostHooks {
101109

102110
impl HostHooks for CliHostHooks {
103111
fn enqueue_generic_job(&self, job: Job) {
104-
self.macrotask_queue.borrow_mut().push(job);
112+
self.macrotask_queue.borrow_mut().push((None, job));
105113
}
106114

107115
fn enqueue_promise_job(&self, job: Job) {
108116
self.promise_job_queue.borrow_mut().push_back(job);
109117
}
110118

111-
fn enqueue_timeout_job(&self, _timeout_job: Job, _milliseconds: u64) {}
119+
fn enqueue_timeout_job(&self, timeout_job: Job, milliseconds: u64) {
120+
let deadline = Instant::now() + Duration::from_millis(milliseconds);
121+
self.macrotask_queue
122+
.borrow_mut()
123+
.push((Some(deadline), timeout_job));
124+
}
112125

113126
fn load_imported_module<'gc>(
114127
&self,

nova_lint/Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ name = "spec_header_level"
4545
path = "ui/spec_header_level.rs"
4646

4747
[dependencies]
48-
clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "c936595d17413c1f08e162e117e504fb4ed126e4" }
49-
dylint_linting = { version = "5.0.0", features = ["constituent"] }
48+
# Must match the nightly toolchain pinned in .github/workflows/ci.yml: each
49+
# clippy_utils release only builds with its contemporary nightly.
50+
clippy_utils = "0.1.98"
51+
dylint_linting = { version = "6.0.1", features = ["constituent"] }
5052
regex = "1"
5153

5254
[dev-dependencies]
53-
dylint_testing = "5.0.0"
55+
dylint_testing = "6.0.1"
5456
nova_vm = { path = "../nova_vm" }
5557

5658
[package.metadata.rust-analyzer]

nova_lint/rust-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
2-
channel = "nightly-2025-10-31"
2+
channel = "nightly-2026-05-28"
33
components = ["llvm-tools-preview", "rustc-dev"]

nova_lint/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub fn match_def_paths(cx: &LateContext<'_>, did: DefId, syms: &[&[&str]]) -> bo
5151

5252
pub fn is_trait_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
5353
if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
54-
matches!(item.kind, ItemKind::Trait(..))
54+
matches!(item.kind, ItemKind::Trait { .. })
5555
} else {
5656
false
5757
}

0 commit comments

Comments
 (0)