diff options
| -rw-r--r-- | Cargo.lock | 88 | ||||
| -rw-r--r-- | oryxc/Cargo.toml | 1 | ||||
| -rw-r--r-- | oryxc/src/compiler.rs | 105 |
3 files changed, 72 insertions, 122 deletions
@@ -53,18 +53,6 @@ dependencies = [ ] [[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] name = "clap" version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -136,32 +124,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -180,27 +148,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "803ec87c9cfb29b9d2633f20cba1f488db3fd53f2158b1024cbefb47ba05d413" [[package]] -name = "libc" -version = "0.2.182" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -212,26 +159,12 @@ version = "0.1.0" dependencies = [ "clap", "crossbeam-deque", - "dashmap", "phf", "soa-rs", "unicode-width", ] [[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] name = "phf" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -293,21 +226,6 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -343,12 +261,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] name = "soa-rs" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/oryxc/Cargo.toml b/oryxc/Cargo.toml index 4308b1a..267e889 100644 --- a/oryxc/Cargo.toml +++ b/oryxc/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] crossbeam-deque = "0.8.6" -dashmap = "6.1.0" # icu = { version = "2.1.1", features = ["compiled_data"] } clap = { version = "4", features = ["derive"] } # num-rational = "0.4.2" diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index 5a16356..2a0a3c9 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -1,6 +1,7 @@ use std::ffi::OsString; use std::io::{ self, + Read, Write, }; use std::iter::once; @@ -24,7 +25,6 @@ use crossbeam_deque::{ Stealer, Worker, }; -use dashmap::DashMap; use soa_rs::Soa; use crate::errors::OryxError; @@ -52,9 +52,12 @@ impl FileData { fn new(name: OsString) -> Result<Self, io::Error> { const PAD: [u8; 64] = [0; 64]; /* 512 bits */ + // Pre-allocate to avoid reallocation when appending padding. // Append extra data to the end so that we can safely read past - // instead of branching on length - let mut buffer = fs::read_to_string(&name)?; + // instead of branching on length. + let size = fs::metadata(&name)?.len() as usize; + let mut buffer = String::with_capacity(size + PAD.len()); + fs::File::open(&name)?.read_to_string(&mut buffer)?; buffer.push_str(unsafe { std::str::from_utf8_unchecked(&PAD) }); Ok(Self { @@ -75,31 +78,56 @@ pub enum Job { } pub struct CompilerState { - pub files: DashMap<FileId, Arc<FileData>>, - pub globalq: Injector<Job>, - pub njobs: AtomicUsize, - pub flags: Flags, + #[allow(dead_code)] + pub files: Vec<Arc<FileData>>, + pub globalq: Injector<Job>, + pub njobs: AtomicUsize, + pub flags: Flags, + pub worker_threads: OnceLock<Box<[thread::Thread]>>, +} + +impl CompilerState { + fn push_job(&self, queue: &Worker<Job>, job: Job) { + queue.push(job); + if let Some(threads) = self.worker_threads.get() { + for t in threads.iter() { + t.unpark(); + } + } + } } pub fn start<T>(paths: T, flags: Flags) where T: IntoIterator<Item = OsString>, { - let state = Arc::new(CompilerState { - files: DashMap::new(), - globalq: Injector::new(), - njobs: AtomicUsize::new(0), - flags, - }); + let mut files = Vec::new(); + let mut initial_jobs = Vec::new(); + for (i, path) in paths.into_iter().enumerate() { let id = FileId(i); + + // take ownership of the OsString so we can store it in FileData without + // cloning + let display = path.to_string_lossy().into_owned(); let fdata = Arc::new( - FileData::new(path.clone().into()) - .unwrap_or_else(|e| err!(e, "{}", path.display())), + FileData::new(path).unwrap_or_else(|e| err!(e, "{}", display)), ); - state.files.insert(id, Arc::clone(&fdata)); - state.njobs.fetch_add(1, Ordering::Relaxed); - state.globalq.push(Job::Lex { file: id, fdata }); + files.push(Arc::clone(&fdata)); + initial_jobs.push(Job::Lex { file: id, fdata }); + } + + let njobs = initial_jobs.len(); + let state = Arc::new(CompilerState { + files, + globalq: Injector::new(), + njobs: AtomicUsize::new(njobs), + flags, + worker_threads: OnceLock::new(), + }); + + for job in initial_jobs { + state.globalq.push(job); } let mut workers = Vec::with_capacity(flags.threads); @@ -110,19 +138,23 @@ where workers.push(w); } - let mut threads = Vec::with_capacity(flags.threads); let stealer_view: Arc<[_]> = Arc::from(stealers); + let handles: Vec<_> = workers + .into_iter() + .enumerate() + .map(|(id, w)| { + let stealer_view = Arc::clone(&stealer_view); + let state = Arc::clone(&state); + thread::spawn(move || worker_loop(id, state, w, stealer_view)) + }) + .collect(); - for (id, w) in workers.into_iter().enumerate() { - let stealer_view = Arc::clone(&stealer_view); - let state = Arc::clone(&state); - threads.push(thread::spawn(move || { - worker_loop(id, state, w, stealer_view) - })); - } + let worker_threads: Box<[thread::Thread]> = + handles.iter().map(|h| h.thread().clone()).collect(); + let _ = state.worker_threads.set(worker_threads); - for t in threads { - if let Err(e) = t.join() { + for h in handles { + if let Err(e) = h.join() { std::panic::resume_unwind(e) } } @@ -149,7 +181,7 @@ fn worker_loop( } let Some(job) = find_task(&queue, &state.globalq, &stealers) else { - thread::yield_now(); + thread::park(); continue; }; @@ -172,7 +204,7 @@ fn worker_loop( fdata.tokens.set(tokens).unwrap(); state.njobs.fetch_add(1, Ordering::Relaxed); - queue.push(Job::Parse { file, fdata }); + state.push_job(&queue, Job::Parse { file, fdata }); }, Job::Parse { file, fdata } => { let (ast, extra_data) = @@ -194,15 +226,22 @@ fn worker_loop( fdata.ast.set(ast).unwrap(); fdata.extra_data.set(extra_data).unwrap(); state.njobs.fetch_add(1, Ordering::Relaxed); - queue.push(Job::ResolveSymbols { file, fdata }); + state.push_job(&queue, Job::ResolveSymbols { file, fdata }); }, Job::ResolveSymbols { file: _, fdata: _ } => { err!("not implemented"); - // unimplemented!() }, } - state.njobs.fetch_sub(1, Ordering::Release); + if state.njobs.fetch_sub(1, Ordering::Release) == 1 { + // njobs is 0; wake all threads so they can observe the termination + // condition and exit. + if let Some(threads) = state.worker_threads.get() { + for t in threads.iter() { + t.unpark(); + } + } + } } } |