From 76f243b200437074df7dc2ab775aa394a2f55cae Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 29 Jul 2025 02:31:51 +0700 Subject: [PATCH 01/21] . --- runtime/src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index fb39644..21f2344 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -20,16 +20,24 @@ mod alloca; // } // } + + type reg = usize; -pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg), - r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { - func(r1, r2, r3, r4, r5); +pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg, reg), + r1: reg, r2: reg, r3: reg, r4: reg, r5: reg, r6: reg) { + func(r1, r2, r3, r4, r5, r6); } +pub extern "C" fn switch2native() {} + +pub extern "C" fn switch2nop() {} + + #[cfg(test)] mod tests { use super::*; + #[test] fn it_works() { From fb44358949767cb0906ec63f86dd23e5d9e0a29f Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Thu, 7 Aug 2025 13:30:30 +0700 Subject: [PATCH 02/21] threads 0 --- runtime/Cargo.lock | 314 +++++------------------------- runtime/Cargo.toml | 3 +- runtime/src/lib.nasm | 15 ++ runtime/src/lib.rs | 20 +- runtime/src/nni/mod.rs | 0 runtime/src/threads/mod.rs | 33 ++++ runtime/src/threads/nthread.rs | 31 +++ runtime/src/threads/threadpool.rs | 84 ++++++++ runtime/src/utils/mod.rs | 5 + runtime/src/utils/treeheap.rs | 32 +++ 10 files changed, 259 insertions(+), 278 deletions(-) create mode 100644 runtime/src/lib.nasm create mode 100644 runtime/src/nni/mod.rs create mode 100644 runtime/src/threads/mod.rs create mode 100644 runtime/src/threads/nthread.rs create mode 100644 runtime/src/threads/threadpool.rs create mode 100644 runtime/src/utils/mod.rs create mode 100644 runtime/src/utils/treeheap.rs diff --git a/runtime/Cargo.lock b/runtime/Cargo.lock index 9ebfa90..bf845f6 100644 --- a/runtime/Cargo.lock +++ b/runtime/Cargo.lock @@ -8,30 +8,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - [[package]] name = "cfg-if" version = "1.0.1" @@ -39,32 +21,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] -name = "combine" -version = "4.6.7" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "enum-as-inner" -version = "0.6.1" +name = "dashmap" +version = "7.0.0-rc2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +checksum = "e4a1e35a65fe0538a60167f0ada6e195ad5d477f6ddae273943596d4a1a5730b" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", + "cfg-if", + "crossbeam-utils", + "equivalent", + "hashbrown", + "lock_api", + "parking_lot_core", ] [[package]] -name = "heck" -version = "0.5.0" +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "hashbrown" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "libc" @@ -79,218 +65,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7222002e5385b4d9327755661e3847c970e8fbf9dea6da8c57f16e8cfbff53a8" [[package]] -name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc 0.2.174", -] - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "memmap2" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" -dependencies = [ - "libc 0.2.174", -] - -[[package]] -name = "memoffset" -version = "0.7.1" +name = "lock_api" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", + "scopeguard", ] [[package]] -name = "mmap-rs" -version = "0.6.1" +name = "parking_lot_core" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86968d85441db75203c34deefd0c88032f275aaa85cee19a1dcfff6ae9df56da" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ - "bitflags 1.3.2", - "combine", - "libc 0.2.174", - "mach2", - "nix", - "sysctl", - "thiserror", - "widestring", - "windows", -] - -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", "cfg-if", "libc 0.2.174", - "memoffset", - "pin-utils", -] - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", + "redox_syscall", + "smallvec", + "windows-targets", ] [[package]] -name = "quote" -version = "1.0.40" +name = "redox_syscall" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "proc-macro2", + "bitflags", ] [[package]] name = "runtime" version = "0.1.0" dependencies = [ + "dashmap", "libc 1.0.0-alpha.1", - "memmap2", - "mmap-rs", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sysctl" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea" -dependencies = [ - "bitflags 2.9.1", - "byteorder", - "enum-as-inner", - "libc 0.2.174", - "thiserror", - "walkdir", ] [[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "widestring" +name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "smallvec" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "windows-targets" @@ -298,46 +122,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -350,48 +156,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 0a80828..9fb5eae 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -5,5 +5,4 @@ edition = "2024" [dependencies] libc = "1.0.0-alpha.1" -mmap-rs = "0.6.1" -memmap2 = "0.9.7" +dashmap = "7.0.0-rc2" diff --git a/runtime/src/lib.nasm b/runtime/src/lib.nasm new file mode 100644 index 0000000..0dc554b --- /dev/null +++ b/runtime/src/lib.nasm @@ -0,0 +1,15 @@ + +extern go_native +extern go_back + +section .text + +unsafe_state: + mov rdi, rbp + mov rsi, rsp + call go_native + ret + +safe_state: + call go_back + ret diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 21f2344..3f8c49b 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,10 +1,14 @@ #![feature(let_chains)] mod alloca; +mod nni; +mod threads; +mod utils; +use utils::*; // static mut ALLOCA: Option> = None; -// pub extern "C" fn init(main: fn()) { +// pub extern "C" fn init(main: fn(), stw: &'static bool) { // unsafe { // ALLOCA = Some(alloca::ArenaAllocator3::new(8 << 40)); // } @@ -20,18 +24,14 @@ mod alloca; // } // } +// static mut THREADS: Option = None; - -type reg = usize; - -pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg, reg), - r1: reg, r2: reg, r3: reg, r4: reg, r5: reg, r6: reg) { - func(r1, r2, r3, r4, r5, r6); +pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg), + r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { + func(r1, r2, r3, r4, r5); } -pub extern "C" fn switch2native() {} - -pub extern "C" fn switch2nop() {} +// pub extern "C" fn go_gc() {} #[cfg(test)] diff --git a/runtime/src/nni/mod.rs b/runtime/src/nni/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/runtime/src/threads/mod.rs b/runtime/src/threads/mod.rs new file mode 100644 index 0000000..bdbcb80 --- /dev/null +++ b/runtime/src/threads/mod.rs @@ -0,0 +1,33 @@ +use std::sync::atomic::{AtomicBool, Ordering}; +use crate::threads::threadpool::ThreadPool; +use crate::utils::*; +mod nthread; +mod threadpool; + +pub(crate) struct Threads { + pool: ThreadPool, + stw: &'static bool +} + +impl Threads { + pub fn new(stw: &'static bool) -> Self { + Self { + pool: ThreadPool::new(), + stw + } + } + + pub fn append(&mut self, func: fn(reg, reg, reg, reg, reg), r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { + self.pool.append(func, r1, r2, r3, r4, r5); + } + + pub fn go_native(&mut self, rbp: reg, rsp: reg) { + self.pool.go_native(rbp, rsp); + } + + pub fn go_back(&mut self) { + while self.stw {} + + self.pool.go_back(); + } +} \ No newline at end of file diff --git a/runtime/src/threads/nthread.rs b/runtime/src/threads/nthread.rs new file mode 100644 index 0000000..9578e34 --- /dev/null +++ b/runtime/src/threads/nthread.rs @@ -0,0 +1,31 @@ +use std::sync::{Arc, RwLock}; +use crate::utils::reg; + +pub(crate) struct NThread { + pub(crate) routine: std::thread::JoinHandle<()>, + pub(crate) state: Arc>, + pub(crate) phase: ThreadPhase +} + +pub(crate) enum ThreadPhase { + Nop, + Native(ThreadCntxt) +} + +impl ThreadPhase { + pub fn new(rbp: reg, rsp: reg) -> Self { + ThreadPhase::Native(ThreadCntxt {rbp, rsp}) + } +} + +struct ThreadCntxt { + pub(crate) rbp: reg, + pub(crate) rsp: reg +} + +pub(crate) enum ThreadState { + Runnable, + Waiting, + Blocked, + Terminated +} \ No newline at end of file diff --git a/runtime/src/threads/threadpool.rs b/runtime/src/threads/threadpool.rs new file mode 100644 index 0000000..0fe5650 --- /dev/null +++ b/runtime/src/threads/threadpool.rs @@ -0,0 +1,84 @@ +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use std::thread::ThreadId; +use crate::threads::nthread::{NThread, ThreadPhase, ThreadState}; +use crate::utils::reg; +use dashmap::DashMap; +use crate::THREADS; + +pub struct ThreadPool { + thread_map: Arc>, + count_nop: AtomicUsize +} + +impl ThreadPool { + pub fn new() -> ThreadPool { + Self { + thread_map: Arc::new(DashMap::new()), + count_nop: AtomicUsize::new(0) + } + } + + pub fn append(&mut self, func: fn(reg, reg, reg, reg, reg), r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { + let i = std::thread::current().id(); + let id = Arc::new(std::sync::Mutex::new(i)); + let id2 = Arc::clone(&id); + + let main_in_process = Arc::new(AtomicBool::new(true)); + let main_in_process2 = Arc::clone(&main_in_process); + + let routine = std::thread::spawn(move || { + *id2.lock().unwrap() = std::thread::current().id(); + + while main_in_process2.load(Ordering::SeqCst) {} + func(r1, r2, r3, r4, r5); + }); + + while i == *id.lock().unwrap() {} + self.count_nop.fetch_add(1, Ordering::Relaxed); + self.thread_map.insert(*id.lock().unwrap(), NThread { + routine, + state: Arc::new(std::sync::RwLock::new(ThreadState::Runnable)), + phase: ThreadPhase::Nop, + }); + + main_in_process.store(false, Ordering::SeqCst); + } + + pub fn go_native(&mut self, rbp: reg, rsp: reg) { + assert_ne!(self.count_nop.load(Ordering::Relaxed), 0); + self.count_nop.fetch_sub(1, Ordering::Relaxed); + + self.thread_map + .get_mut(&std::thread::current().id()) + .expect("fantom thread") + .phase = ThreadPhase::new(rbp, rsp); + } + + pub fn go_back(&mut self) { + self.count_nop.fetch_add(1, Ordering::Relaxed); + + self.thread_map + .get_mut(&std::thread::current().id()) + .expect("fantom thread") + .phase = ThreadPhase::Nop + } +} + +extern "C" fn go_native(rbp: reg, rsp: reg) { + unsafe { + match THREADS.as_mut() { + None => { panic!("THREADS is not set")} + Some(mut threads) => { threads.go_native(rbp, rsp)} + } + } +} + +extern "C" fn go_back() { + unsafe { + match THREADS.as_mut() { + None => { panic!("THREADS is not set") } + Some(mut threads) => { threads.go_back()} + } + } +} \ No newline at end of file diff --git a/runtime/src/utils/mod.rs b/runtime/src/utils/mod.rs new file mode 100644 index 0000000..0418d3d --- /dev/null +++ b/runtime/src/utils/mod.rs @@ -0,0 +1,5 @@ +mod treeheap; + +pub type reg = usize; + +pub use treeheap::*; \ No newline at end of file diff --git a/runtime/src/utils/treeheap.rs b/runtime/src/utils/treeheap.rs new file mode 100644 index 0000000..6ac9454 --- /dev/null +++ b/runtime/src/utils/treeheap.rs @@ -0,0 +1,32 @@ +use std::collections::BTreeSet; + +pub(crate) trait KeyFromUsize { + fn from_usize(n: usize) -> Self; +} + +#[derive(Debug)] +pub(crate) struct TreeHeap { + pub items: std::sync::RwLock>, +} + +impl TreeHeap { + pub fn new() -> Self { + Self { + items: std::sync::RwLock::new(BTreeSet::new()), + } + } + + pub fn insert(&self, item: T) { + self.items.write().unwrap().insert(item); + } + + pub fn get_min_more_than(&self, n: usize) -> Option { + let etalon = T::from_usize(n - 1); + + let mut guarded = self.items.read().unwrap(); + + let key = guarded.range(etalon..).next()?.clone(); + + Some(guarded.take(&key).expect("Never fails in treeheap")) + } +} From df86370e28c8f3b31681f057388c0d0f7176f7f5 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Sun, 17 Aug 2025 22:11:03 +0700 Subject: [PATCH 03/21] gc 0.0 --- runtime/src/alloca/allocator.rs | 2 +- runtime/src/alloca/hallocator.rs | 14 ++- runtime/src/alloca/hedgearena.rs | 5 +- runtime/src/alloca/mod.rs | 16 ++++ runtime/src/gc/mod.rs | 152 ++++++++++++++++++++++++++++++ runtime/src/lib.nasm | 105 +++++++++++++++++++++ runtime/src/lib.rs | 81 ++++++++++++---- runtime/src/threads/mod.rs | 15 +-- runtime/src/threads/nthread.rs | 23 ++--- runtime/src/threads/threadpool.rs | 44 +++------ 10 files changed, 381 insertions(+), 76 deletions(-) create mode 100644 runtime/src/gc/mod.rs diff --git a/runtime/src/alloca/allocator.rs b/runtime/src/alloca/allocator.rs index 48acfd3..ca63b8f 100644 --- a/runtime/src/alloca/allocator.rs +++ b/runtime/src/alloca/allocator.rs @@ -12,7 +12,7 @@ pub trait ArenaAllocator3 { fn new(max_size: usize) -> Self; - fn alloc(&mut self, o: &T) -> ptr; + fn alloc(&mut self, o: &T) -> (ptr, bool); fn mark_white(&mut self); diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index f7f6d28..5256b0e 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -5,7 +5,7 @@ use crate::alloca::allocator::ArenaAllocator3; use crate::alloca::arena::Arena3; use crate::alloca::heapedarena::{Heap, HeapedArena}; -pub(crate) struct HAllocator { +pub struct HAllocator { start: ptr, max_size: usize, used_memory: AtomicUsize, @@ -97,7 +97,7 @@ impl ArenaAllocator3 for HAllocator { } - fn alloc(&mut self, o: &T) -> ptr { + fn alloc(&mut self, o: &T) -> (ptr, bool) { let mut maybe_heaped_arena = self.heap.get_min_more_then(o.size()); if maybe_heaped_arena.is_none() { @@ -134,10 +134,14 @@ impl ArenaAllocator3 for HAllocator { } } } - - self.used_memory.fetch_add(o.size(), Ordering::Relaxed); self.heap.insert(heaped_arena); - ptr + + let used = self.used_memory.load(Ordering::Relaxed); + if used > self.max_size { + (ptr, true) + } else { + (ptr, false) + } } fn mark_white(&mut self) { diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 024da5f..2916789 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -4,7 +4,7 @@ use crate::alloca::ptr; use crate::alloca::arena::Arena3; #[derive(Debug)] -pub(crate) struct HedgeArena { +pub struct HedgeArena { start: ptr, cur: ptr, size: usize, // = 32x @@ -57,7 +57,7 @@ impl Arena3 for HedgeArena { } fn black_map(&self) -> (ptr, usize) { - (self.start + self.size >> 6, self.size >> 6) + (self.start + (self.size >> 6), self.size >> 6) } fn clear_mark(&mut self) { @@ -82,7 +82,6 @@ impl Arena3 for HedgeArena { -1, 0); assert_ne!(res, libc::MAP_FAILED); } - unsafe { *(self.start as *mut u8) = 1 }; self.clear_mark(); } diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 5dd1fc7..4e8a4f8 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -3,6 +3,8 @@ mod arena; mod hallocator; mod hedgearena; mod heapedarena; +pub use hedgearena::HedgeArena; +pub use hallocator::HAllocator; pub(crate) type ptr = usize; @@ -11,6 +13,20 @@ pub trait Object { fn get_bitset_of_ref(&self) -> &'static [u8]; } +pub struct ObjectImpl { + size: usize, + bitset: &'static [u8], +} + +impl Object for ObjectImpl { + fn size(&self) -> usize { + self.size + } + + fn get_bitset_of_ref(&self) -> &'static [u8] { + self.bitset + } +} #[cfg(test)] mod tests { diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs new file mode 100644 index 0000000..c423cf2 --- /dev/null +++ b/runtime/src/gc/mod.rs @@ -0,0 +1,152 @@ +use std::cmp::min; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread; +use std::thread::JoinHandle; +use crate::{alloca, threads}; +use crate::threads::ThreadPhase; +use crate::utils::reg; + +pub struct Gc { + threads: Arc, + + stw_is_done: Mutex, + stw_cv: std::sync::Condvar, + + heap_is_done: Mutex, + heap_cv: std::sync::Condvar, + + mark_is_done: Mutex, + mark_cv: std::sync::Condvar, + + root_is_done: Mutex, + root_cv: std::sync::Condvar, + + work_is_done: Mutex, + work_cv: std::sync::Condvar, + workers: Vec>, + count_active_workers: AtomicUsize, + + root: Vec, +} + +impl Gc { + + pub fn new(threads: Arc) -> Self { + Self { + threads, + stw_is_done: Mutex::new(false), + stw_cv: Default::default(), + + heap_is_done: Mutex::new(false), + heap_cv: Default::default(), + + mark_is_done: Mutex::new(false), + mark_cv: Default::default(), + + work_is_done: Mutex::new(false), + work_cv: Default::default(), + + workers: Vec::with_capacity(count_worker), + count_active_workers: AtomicUsize::new(0), + + root: Vec::new(), + } + } + + pub fn init_workers(&mut self, count: usize) { + assert_ne!(self.workers.len(), 0); + + self.count_active_workers = AtomicUsize::from(count); + + for i in 0..count { + self.workers.push(thread::spawn(move || { + loop { + { + let mut root_is_done_flag = self.root_is_done.lock().unwrap(); + + while !*root_is_done_flag { + root_is_done_flag = self.stw_cv.wait(root_is_done_flag).unwrap() + } + } + + let count_for_scan = self.root.len() / count + 1; + for j in min(i*count_for_scan, self.root.len())..self.root.len() { + + } + // TODO WORK + + { + if self.count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { + + let mut root_is_done_flag = self.stw_is_done.lock().unwrap(); + self.root = Vec::new(); + *root_is_done_flag = false; + + let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + assert!(!*work_is_done_flag); + *work_is_done_flag = true; + + self.work_cv.notify_all(); + } else { + + let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + while !*work_is_done_flag { + work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() + } + } + } + + } + })) + } + } + + pub fn go_gc(&mut self, rbp: reg) { + self.threads.go_immut(rbp); + + + let mut root_is_done_flag = self.stw_is_done.lock().unwrap(); + while !*root_is_done_flag { + root_is_done_flag = self.stw_cv.wait(root_is_done_flag).unwrap() + } + + // TODO + } + + pub fn master(&mut self) { + + let mut heap_is_done_flag = self.heap_is_done.lock().unwrap(); + while !*heap_is_done_flag { + heap_is_done_flag = self.heap_cv.wait(heap_is_done_flag).unwrap() + } + + for item in self.threads.pool.thread_map.iter() { + let nthread = item.value(); + match nthread.phase { + ThreadPhase::Mutable => { + unreachable!(); + } + ThreadPhase::Immutable(cntxt) => { + self.add_to_root(cntxt.rbp); + } + } + } + + *(self.stw_is_done) = true; + self.stw_cv.notify_all(); + } + + pub fn notify_master(&mut self) { + *(self.heap_is_done) = true; + self.heap_cv.notify_all(); + } + + fn add_to_root(&mut self, rbp: reg) { + // TODO + } + + fn mark(&mut self) { + + } +} \ No newline at end of file diff --git a/runtime/src/lib.nasm b/runtime/src/lib.nasm index 0dc554b..968578c 100644 --- a/runtime/src/lib.nasm +++ b/runtime/src/lib.nasm @@ -13,3 +13,108 @@ unsafe_state: safe_state: call go_back ret + + + + + + + + + +seq: + + push rbp + mov rbp, rsp + sub rsp, 32 + mov DWORD PTR [rbp-20], edi + mov edi, 4 + call malloc + mov QWORD PTR [rbp-8], rax + mov eax, DWORD PTR [rbp-20] + sub eax, 1 + mov edi, eax + call seq + mov rdx, QWORD PTR [rbp-8] + mov DWORD PTR [rdx], eax + mov rax, QWORD PTR [rbp-8] + mov edx, DWORD PTR [rax] + mov eax, DWORD PTR [rbp-20] + add eax, edx + leave + safepoint //rbp сейчас + + ret + + +фрейм функции +--------------- +/ число +/ птр +/ ra +/ число +/ птр + + + + + +func: + push 0b1010 + + push rbp + mov rbp, rsp + mov [rbp], число + call alloc + mov [rbp-8], ptr + sub rsp, 16 + call foo + + +foo: + push 0 + push 0 + push rbp + mov rbp, rsp + leave + ret + + + + + + + + + + + +/ old_rbp /8 +/ edi /4 -4 +/ nop /4 -8 +/ ptr /8 -16 + +sseq: + push 0 + push 16 + push rbp + mov rbp, rsp + sub rsp, 16 + mov dword ptr [rbp - 4], edi + cmp dword ptr [rbp - 4], 5 + jle .LBB0_2 + mov edi, 4 + call malloc@PLT + mov qword ptr [rbp - 16], rax + mov [rbp+...], + .LBB0_2: + mov rax, qword ptr [rbp - 16] + cmp + add rsp, 16 + pop rbp + ret + + + + + diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 3f8c49b..e3983c8 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -4,35 +4,76 @@ mod alloca; mod nni; mod threads; mod utils; +mod gc; +use std::sync::Arc; use utils::*; -// static mut ALLOCA: Option> = None; - -// pub extern "C" fn init(main: fn(), stw: &'static bool) { -// unsafe { -// ALLOCA = Some(alloca::ArenaAllocator3::new(8 << 40)); -// } -// main(); -// } -// -// pub extern "C" fn alloc(t: &dyn alloca::Object) -> alloca::ptr { -// unsafe { -// match ALLOCA.as_mut() { -// None => { panic!("ALLOCA is None")} -// Some(mut alloca) => { alloca.alloc(t)} -// } -// } -// } - -// static mut THREADS: Option = None; + +static mut ALLOCA: Option> = None; + +pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { + unsafe { + ALLOCA = Some(alloca::HAllocator:: + :: + new(8 << 40)); + + THREADS = Some(Arc::new(threads::Threads::new(stw))); + + THREADS.as_mut() + .unwrap() + .append(main, 0, 0, 0, 0, 0); + + GC.as_mut() + .unwrap() + .master() + } +} + +pub extern "C" fn alloc(t: &dyn alloca::Object) -> alloca::ptr { + unsafe { + match ALLOCA.as_mut() { + None => { panic!("ALLOCA is None")} + Some(mut alloca) => { + let (ptr, heap_is_overflow) = alloca.alloc(t); + if heap_is_overflow { + GC.as_mut().unwrap().notify_master(); + } + ptr + } + } + } +} + +static mut THREADS: Option> = None; +static mut GC: Option = None; pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg), r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { func(r1, r2, r3, r4, r5); } -// pub extern "C" fn go_gc() {} +extern "C" unsafe fn go_gc(rbp: reg, rsp: reg) { + gc::go_gc(rbp, rsp, &(THREADS.as_mut().unwrap())); +} + +extern "C" fn go_native(rbp: reg, rsp: reg) { + unsafe { + match THREADS.as_mut() { + None => { panic!("THREADS is not set")} + Some(mut threads) => { threads.go_native(rbp, rsp)} + } + } +} +extern "C" fn go_back() { + unsafe { + match THREADS.as_mut() { + None => { panic!("THREADS is not set") } + Some(mut threads) => { threads.go_back()} + } + } +} #[cfg(test)] mod tests { diff --git a/runtime/src/threads/mod.rs b/runtime/src/threads/mod.rs index bdbcb80..d866180 100644 --- a/runtime/src/threads/mod.rs +++ b/runtime/src/threads/mod.rs @@ -1,11 +1,14 @@ use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread::ThreadId; +use crate::threads::nthread::NThread; use crate::threads::threadpool::ThreadPool; use crate::utils::*; mod nthread; mod threadpool; +pub use nthread::ThreadPhase; -pub(crate) struct Threads { - pool: ThreadPool, +pub struct Threads { + pub pool: ThreadPool, stw: &'static bool } @@ -21,13 +24,13 @@ impl Threads { self.pool.append(func, r1, r2, r3, r4, r5); } - pub fn go_native(&mut self, rbp: reg, rsp: reg) { - self.pool.go_native(rbp, rsp); + pub fn go_immut(&mut self, rbp: reg) { + self.pool.go_immut(rbp); } - pub fn go_back(&mut self) { + pub fn go_mut(&mut self) { while self.stw {} - self.pool.go_back(); + self.pool.go_mut(); } } \ No newline at end of file diff --git a/runtime/src/threads/nthread.rs b/runtime/src/threads/nthread.rs index 9578e34..a484ec8 100644 --- a/runtime/src/threads/nthread.rs +++ b/runtime/src/threads/nthread.rs @@ -1,26 +1,27 @@ use std::sync::{Arc, RwLock}; use crate::utils::reg; -pub(crate) struct NThread { - pub(crate) routine: std::thread::JoinHandle<()>, - pub(crate) state: Arc>, - pub(crate) phase: ThreadPhase +pub struct NThread { + pub routine: std::thread::JoinHandle<()>, + pub state: Arc>, // i guess arc or rw or rw and arc id redundant + pub phase: ThreadPhase } -pub(crate) enum ThreadPhase { - Nop, - Native(ThreadCntxt) +#[derive(Debug, Clone, Copy)] +pub enum ThreadPhase { + Mutable, + Immutable(ThreadCntxt) } impl ThreadPhase { - pub fn new(rbp: reg, rsp: reg) -> Self { - ThreadPhase::Native(ThreadCntxt {rbp, rsp}) + pub fn new(rbp: reg) -> Self { + ThreadPhase::Immutable(ThreadCntxt {rbp}) } } +#[derive(Debug, Clone, Copy)] struct ThreadCntxt { - pub(crate) rbp: reg, - pub(crate) rsp: reg + pub rbp: reg, } pub(crate) enum ThreadState { diff --git a/runtime/src/threads/threadpool.rs b/runtime/src/threads/threadpool.rs index 0fe5650..5f3fc3e 100644 --- a/runtime/src/threads/threadpool.rs +++ b/runtime/src/threads/threadpool.rs @@ -4,18 +4,17 @@ use std::thread::ThreadId; use crate::threads::nthread::{NThread, ThreadPhase, ThreadState}; use crate::utils::reg; use dashmap::DashMap; -use crate::THREADS; pub struct ThreadPool { - thread_map: Arc>, - count_nop: AtomicUsize + pub thread_map: Arc>, + pub count_of_mutable: AtomicUsize, } impl ThreadPool { pub fn new() -> ThreadPool { Self { thread_map: Arc::new(DashMap::new()), - count_nop: AtomicUsize::new(0) + count_of_mutable: AtomicUsize::new(0) } } @@ -35,50 +34,35 @@ impl ThreadPool { }); while i == *id.lock().unwrap() {} - self.count_nop.fetch_add(1, Ordering::Relaxed); + self.count_of_mutable.fetch_add(1, Ordering::Relaxed); self.thread_map.insert(*id.lock().unwrap(), NThread { routine, state: Arc::new(std::sync::RwLock::new(ThreadState::Runnable)), - phase: ThreadPhase::Nop, + phase: ThreadPhase::Mutable, }); main_in_process.store(false, Ordering::SeqCst); } - pub fn go_native(&mut self, rbp: reg, rsp: reg) { - assert_ne!(self.count_nop.load(Ordering::Relaxed), 0); - self.count_nop.fetch_sub(1, Ordering::Relaxed); + pub fn go_immut(&mut self, rbp: reg) { + assert_ne!(self.count_of_mutable.load(Ordering::Relaxed), 0); self.thread_map .get_mut(&std::thread::current().id()) .expect("fantom thread") - .phase = ThreadPhase::new(rbp, rsp); + .phase = ThreadPhase::new(rbp); + + self.count_of_mutable.fetch_sub(1, Ordering::Relaxed); } - pub fn go_back(&mut self) { - self.count_nop.fetch_add(1, Ordering::Relaxed); + pub fn go_mut(&mut self) { self.thread_map .get_mut(&std::thread::current().id()) .expect("fantom thread") - .phase = ThreadPhase::Nop + .phase = ThreadPhase::Mutable; + + self.count_of_mutable.fetch_add(1, Ordering::Relaxed); } } -extern "C" fn go_native(rbp: reg, rsp: reg) { - unsafe { - match THREADS.as_mut() { - None => { panic!("THREADS is not set")} - Some(mut threads) => { threads.go_native(rbp, rsp)} - } - } -} - -extern "C" fn go_back() { - unsafe { - match THREADS.as_mut() { - None => { panic!("THREADS is not set") } - Some(mut threads) => { threads.go_back()} - } - } -} \ No newline at end of file From 9c5adacc4ae6c814c08fcca4945adf0104e67a3a Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 02:19:29 +0700 Subject: [PATCH 04/21] add markqueue --- runtime/src/alloca/heapedarena.rs | 8 +++---- runtime/src/alloca/mod.rs | 1 + runtime/src/gc/markqueue.rs | 39 +++++++++++++++++++++++++++++++ runtime/src/gc/mod.rs | 15 +++++++++--- 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 runtime/src/gc/markqueue.rs diff --git a/runtime/src/alloca/heapedarena.rs b/runtime/src/alloca/heapedarena.rs index cc98541..2e7011d 100644 --- a/runtime/src/alloca/heapedarena.rs +++ b/runtime/src/alloca/heapedarena.rs @@ -2,10 +2,10 @@ use std::sync::Mutex; use crate::alloca::arena::Arena3; #[derive(Debug, Clone, Copy)] -pub(crate) struct HeapedArena { - pub(crate) num_of_block: usize, - pub(crate) num_of_arena: usize, - pub(crate) param: usize +pub struct HeapedArena { + pub num_of_block: usize, + pub num_of_arena: usize, + pub param: usize } impl Eq for HeapedArena {} diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 4e8a4f8..47cf868 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -5,6 +5,7 @@ mod hedgearena; mod heapedarena; pub use hedgearena::HedgeArena; pub use hallocator::HAllocator; +pub use arena::Arena3; pub(crate) type ptr = usize; diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs new file mode 100644 index 0000000..f5337f9 --- /dev/null +++ b/runtime/src/gc/markqueue.rs @@ -0,0 +1,39 @@ +use std::cmp::min; +pub use crate::alloca::*; +use std::sync::Arc; + +pub enum MarkQueueElement<'a, T: Arena3> { + arena(&'a mut T), + object(Arc) +} + +pub struct MarkQueue<'a, T: Arena3> { + queue: std::sync::Mutex>>, +} + +impl<'a, T: Arena3> MarkQueue<'a, T> { + pub fn new() -> MarkQueue<'a, T> { + Self { + queue: std::sync::Mutex::new(vec![]), + } + } + + pub fn pushn(&mut self, elements: Vec>) { + self.queue + .lock() + .expect("pushn") + .extend(elements); + } + + pub fn popn(&mut self, n: usize) -> Vec> { + let mut lock = self.queue + .lock() + .expect("popn"); + let bound = min(lock.len(), n); + let mut result = vec![]; + for _ in 0..bound { + result.push(lock.pop().expect("popn copy")); + } + result + } +} \ No newline at end of file diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index c423cf2..e38390b 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -1,13 +1,17 @@ +mod markqueue; + use std::cmp::min; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use std::thread::JoinHandle; use crate::{alloca, threads}; +use crate::alloca::Arena3; +use crate::gc::markqueue::MarkQueue; use crate::threads::ThreadPhase; use crate::utils::reg; -pub struct Gc { +pub struct Gc<'a, T: Arena3> { threads: Arc, stw_is_done: Mutex, @@ -28,9 +32,10 @@ pub struct Gc { count_active_workers: AtomicUsize, root: Vec, + mark_queue: MarkQueue<'a, T>, } -impl Gc { +impl Gc { pub fn new(threads: Arc) -> Self { Self { @@ -44,13 +49,17 @@ impl Gc { mark_is_done: Mutex::new(false), mark_cv: Default::default(), + root_is_done: Mutex::new(false), + root_cv: Default::default(), + work_is_done: Mutex::new(false), work_cv: Default::default(), - workers: Vec::with_capacity(count_worker), + workers: Vec::new(), count_active_workers: AtomicUsize::new(0), root: Vec::new(), + mark_queue: MarkQueue::new(), } } From bf2714b81b4583a4fcd630e36b0e93e1b8602f8d Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 03:09:50 +0700 Subject: [PATCH 05/21] rewrite mark colors --- runtime/src/alloca/allocator.rs | 3 ++- runtime/src/alloca/hallocator.rs | 45 +++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/runtime/src/alloca/allocator.rs b/runtime/src/alloca/allocator.rs index ca63b8f..4fb7d35 100644 --- a/runtime/src/alloca/allocator.rs +++ b/runtime/src/alloca/allocator.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; use crate::alloca::{ptr, Object}; use crate::alloca::arena::Arena3; @@ -16,7 +17,7 @@ pub trait ArenaAllocator3 { fn mark_white(&mut self); - fn arena_by_ptr(&mut self, ptr: usize) -> &mut U; + fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U>; fn mark_gray(&mut self, ptr: ptr); diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index 5256b0e..ad6ec30 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -1,3 +1,4 @@ +use std::collections::LinkedList; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use crate::alloca::{ptr, Object}; @@ -14,19 +15,17 @@ pub struct HAllocator { blocks: Box<[Option>]>, count_of_blocks: AtomicUsize, - large_objects: Vec>, + large_objects: LinkedList, _marker: std::marker::PhantomData, } impl HAllocator { - fn block_by_ptr(&mut self, ptr: ptr) -> &mut HedgeBlock { + fn block_by_ptr(&mut self, ptr: ptr) -> Option<&mut HedgeBlock> { assert!(self.start <= ptr); assert!(ptr < self.start + (1 << Self::LOG_CAPACITY_SIZE)); self.blocks[ptr >> Self::LOG_BLOCK_SIZE] .as_mut() - .expect(&format!("block_by_ptr: \ - index: {}\n", ptr >> Self::LOG_BLOCK_SIZE)) } fn add_new_needed_block(&mut self, size: usize) -> &mut HedgeBlock { @@ -89,7 +88,7 @@ impl ArenaAllocator3 for HAllocator { heap: Heap::new(), blocks: Box::new([const {None}; 1 << (>::LOG_CAPACITY_SIZE - >::LOG_BLOCK_SIZE)]), count_of_blocks: AtomicUsize::new(0), - large_objects: vec![], + large_objects: LinkedList::new(), _marker: Default::default(), } } @@ -117,7 +116,8 @@ impl ArenaAllocator3 for HAllocator { let ptr = ref_arena.cur(); if ptr == ref_arena.start() { - let mut block = self.block_by_ptr(ptr); + let mut block = self.block_by_ptr(ptr) + .expect("hz"); match block.slots.pop() { Some(heaped_arena_from_slots) => { self.arena_by_heaped(heaped_arena_from_slots).on(); @@ -152,23 +152,42 @@ impl ArenaAllocator3 for HAllocator { if let arena = self.arena_by_heaped(heaped_arena_from_slots.clone()) && arena.live() { arena.clear_mark(); } - }; + } + + for large in self.large_objects.iter_mut() { + *large >>= 2; + *large <<= 2; + } } - fn arena_by_ptr(&mut self, ptr: usize) -> &mut U { + fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { self.block_by_ptr(ptr) - .arena_by_ptr(ptr) + .map(|block| block.arena_by_ptr(ptr)) } fn mark_gray(&mut self, ptr: ptr) { - self.arena_by_ptr(ptr) - .mark_gray(ptr); + match self.arena_by_ptr(ptr) { + Some(arena) => { + arena.mark_gray(ptr); + } + None => { + *self.large_objects.iter_mut() + .find(|p| (**p >> 2) == (ptr >> 2)) |= 1;; + } + } } fn mark_black(&mut self, ptr: ptr) { - self.arena_by_ptr(ptr) - .mark_black(ptr); + match self.arena_by_ptr(ptr) { + Some(arena) => { + arena.mark_gray(ptr); + } + None => { + *self.large_objects.iter_mut() + .find(|p| (**p >> 2) == (ptr >> 2)) |= 2; + } + } } } From d1ff91989ac647433d27ed56c75972834e96f2fd Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 03:42:21 +0700 Subject: [PATCH 06/21] add flag in queue in Arena3 --- runtime/src/alloca/arena.rs | 2 ++ runtime/src/alloca/hedgearena.rs | 9 ++++++++- runtime/src/gc/markqueue.rs | 3 +-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/runtime/src/alloca/arena.rs b/runtime/src/alloca/arena.rs index 9e25d22..4d43261 100644 --- a/runtime/src/alloca/arena.rs +++ b/runtime/src/alloca/arena.rs @@ -28,4 +28,6 @@ pub trait Arena3 { fn mark_gray(&mut self, ptr: ptr); fn mark_black(&mut self, ptr: ptr); + + fn fetch_and_add_in_queue(&mut self) -> bool; } \ No newline at end of file diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 2916789..77584c9 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -18,6 +18,8 @@ pub struct HedgeArena { /// dbg only objects: Vec, + + in_queue: AtomicBool, } impl Arena3 for HedgeArena { @@ -28,7 +30,8 @@ impl Arena3 for HedgeArena { size, span_start: start + (size >> 5), live: Default::default(), - objects: vec![] + objects: vec![], + in_queue: Default::default(), } } @@ -104,6 +107,10 @@ impl Arena3 for HedgeArena { std::ptr::write(((self.start + self.span_start >> 1) + (index >> 3)) as *mut u8, (index % 8) as u8); } } + + fn fetch_and_add_in_queue(&mut self) -> bool { + self.in_queue.fetch_not(Ordering::SeqCst) + } } impl Eq for HedgeArena {} diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs index f5337f9..55b44c5 100644 --- a/runtime/src/gc/markqueue.rs +++ b/runtime/src/gc/markqueue.rs @@ -1,10 +1,9 @@ use std::cmp::min; pub use crate::alloca::*; -use std::sync::Arc; pub enum MarkQueueElement<'a, T: Arena3> { arena(&'a mut T), - object(Arc) + object(ptr) } pub struct MarkQueue<'a, T: Arena3> { From b9b5b082ece5c0c0c8153cf89de57e97c119021a Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 04:35:30 +0700 Subject: [PATCH 07/21] refactoring lib.rs --- runtime/src/gc/mod.rs | 15 +++++++----- runtime/src/lib.rs | 56 +++++++++++++++++++------------------------ 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index e38390b..e8f9fdb 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -6,12 +6,14 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use std::thread::JoinHandle; use crate::{alloca, threads}; -use crate::alloca::Arena3; +use crate::alloca::{Arena3, Object}; use crate::gc::markqueue::MarkQueue; use crate::threads::ThreadPhase; use crate::utils::reg; -pub struct Gc<'a, T: Arena3> { +pub struct Gc<'a, T: Object, U: Arena3> { + pub alloca: alloca::HAllocator, + threads: Arc, stw_is_done: Mutex, @@ -32,13 +34,14 @@ pub struct Gc<'a, T: Arena3> { count_active_workers: AtomicUsize, root: Vec, - mark_queue: MarkQueue<'a, T>, + mark_queue: MarkQueue<'a, U>, } -impl Gc { +impl Gc { - pub fn new(threads: Arc) -> Self { + pub fn new(threads: Arc, max_size: usize) -> Self { Self { + alloca: alloca::HAllocator::::new(max_size), threads, stw_is_done: Mutex::new(false), stw_cv: Default::default(), @@ -81,7 +84,7 @@ impl Gc { let count_for_scan = self.root.len() / count + 1; for j in min(i*count_for_scan, self.root.len())..self.root.len() { - + match { } } // TODO WORK diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e3983c8..500cf4e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(let_chains)] - mod alloca; mod nni; mod threads; @@ -9,16 +7,16 @@ mod gc; use std::sync::Arc; use utils::*; -static mut ALLOCA: Option> = None; +static mut THREADS: Option> = None; + +static mut GC: Option> = None; pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { unsafe { - ALLOCA = Some(alloca::HAllocator:: - :: - new(8 << 40)); + let athreads = Arc::new(threads::Threads::new(stw)); + THREADS = Some(athreads.clone()); - THREADS = Some(Arc::new(threads::Threads::new(stw))); + GC = Some(gc::Gc::new(athreads, 8 << 40)); THREADS.as_mut() .unwrap() @@ -32,46 +30,42 @@ pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { pub extern "C" fn alloc(t: &dyn alloca::Object) -> alloca::ptr { unsafe { - match ALLOCA.as_mut() { - None => { panic!("ALLOCA is None")} - Some(mut alloca) => { - let (ptr, heap_is_overflow) = alloca.alloc(t); - if heap_is_overflow { - GC.as_mut().unwrap().notify_master(); - } - ptr - } + let gc = GC.as_mut().expect("gc is none (alloc)"); + let (ptr, heap_is_overflow) = gc.alloca.alloc(t);; + if heap_is_overflow { + gc.notify_master(); } + ptr } } -static mut THREADS: Option> = None; -static mut GC: Option = None; pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg), r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { func(r1, r2, r3, r4, r5); } -extern "C" unsafe fn go_gc(rbp: reg, rsp: reg) { - gc::go_gc(rbp, rsp, &(THREADS.as_mut().unwrap())); +pub extern "C" fn go_gc(rbp: reg) { + unsafe { + GC.as_mut() + .expect("gc is None") + .go_gc(rbp); + } } -extern "C" fn go_native(rbp: reg, rsp: reg) { +pub extern "C" fn go_native(rbp: reg) { unsafe { - match THREADS.as_mut() { - None => { panic!("THREADS is not set")} - Some(mut threads) => { threads.go_native(rbp, rsp)} - } + THREADS.as_mut() + .expect("thrds is None") + .go_immut(rbp); } } -extern "C" fn go_back() { +pub extern "C" fn go_back() { unsafe { - match THREADS.as_mut() { - None => { panic!("THREADS is not set") } - Some(mut threads) => { threads.go_back()} - } + THREADS.as_mut() + .expect("thrds is None") + .go_mut(); } } From d1be98c2b964fbdaa231351e6d3eb0347a26ba90 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 05:34:58 +0700 Subject: [PATCH 08/21] progress in gc/mod.rs --- runtime/src/alloca/arena.rs | 2 ++ runtime/src/alloca/hallocator.rs | 10 +++++++--- runtime/src/alloca/hedgearena.rs | 6 +++++- runtime/src/gc/markqueue.rs | 2 +- runtime/src/gc/mod.rs | 31 +++++++++++++++++++++++++++---- runtime/src/lib.rs | 2 ++ 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/runtime/src/alloca/arena.rs b/runtime/src/alloca/arena.rs index 4d43261..f64dbda 100644 --- a/runtime/src/alloca/arena.rs +++ b/runtime/src/alloca/arena.rs @@ -30,4 +30,6 @@ pub trait Arena3 { fn mark_black(&mut self, ptr: ptr); fn fetch_and_add_in_queue(&mut self) -> bool; + + fn fetch_and_take_from_queue(&mut self) -> bool; } \ No newline at end of file diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index ad6ec30..f078267 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -166,26 +166,30 @@ impl ArenaAllocator3 for HAllocator { } - fn mark_gray(&mut self, ptr: ptr) { + fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U> { match self.arena_by_ptr(ptr) { Some(arena) => { arena.mark_gray(ptr); + Some(arena) } None => { *self.large_objects.iter_mut() - .find(|p| (**p >> 2) == (ptr >> 2)) |= 1;; + .find(|p| (**p >> 2) == (ptr >> 2)) |= 1; + None } } } - fn mark_black(&mut self, ptr: ptr) { + fn mark_black(&mut self, ptr: ptr) -> Option<&mut U> { match self.arena_by_ptr(ptr) { Some(arena) => { arena.mark_gray(ptr); + Some(arena) } None => { *self.large_objects.iter_mut() .find(|p| (**p >> 2) == (ptr >> 2)) |= 2; + None } } } diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 77584c9..1b4e507 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -109,7 +109,11 @@ impl Arena3 for HedgeArena { } fn fetch_and_add_in_queue(&mut self) -> bool { - self.in_queue.fetch_not(Ordering::SeqCst) + self.in_queue.fetch_or(true, Ordering::SeqCst) + } + + fn fetch_and_take_from_queue(&mut self) -> bool { + self.in_queue.fetch_and(false, Ordering::SeqCst) } } diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs index 55b44c5..91d5f94 100644 --- a/runtime/src/gc/markqueue.rs +++ b/runtime/src/gc/markqueue.rs @@ -17,7 +17,7 @@ impl<'a, T: Arena3> MarkQueue<'a, T> { } } - pub fn pushn(&mut self, elements: Vec>) { + pub fn pushn(&mut self, elements: &mut Vec>) { self.queue .lock() .expect("pushn") diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index e8f9fdb..63a3bfe 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -7,7 +7,7 @@ use std::thread; use std::thread::JoinHandle; use crate::{alloca, threads}; use crate::alloca::{Arena3, Object}; -use crate::gc::markqueue::MarkQueue; +use crate::gc::markqueue::{MarkQueue, MarkQueueElement}; use crate::threads::ThreadPhase; use crate::utils::reg; @@ -81,11 +81,34 @@ impl Gc { root_is_done_flag = self.stw_cv.wait(root_is_done_flag).unwrap() } } + let mut local_queue = vec![]; let count_for_scan = self.root.len() / count + 1; for j in min(i*count_for_scan, self.root.len())..self.root.len() { - match { } + match self.alloca.mark_gray(self.root[j]) { + None => { + local_queue.push(MarkQueueElement::object(self.root[j])) + } + Some(a) => { + if !a.fetch_and_add_in_queue() { + local_queue.push(MarkQueueElement::arena(a)) + } + } + } + if !(local_queue.len() & 15) { // TODO: make somethink like cfg + self.mark_queue.pushn(&mut local_queue); + } + } + + loop { + + + while local_queue.len() > 0 { + self.mark(local_queue.pop().unwrap()); + } + } + // TODO WORK { @@ -158,7 +181,7 @@ impl Gc { // TODO } - fn mark(&mut self) { - + fn mark(&mut self, el: MarkQueueElement) { + // TODO } } \ No newline at end of file diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 500cf4e..287223f 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(let_chains)] + mod alloca; mod nni; mod threads; From aa7c9d09c1b9f4216711b7364142960b53ce0b0b Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 15:28:43 +0700 Subject: [PATCH 09/21] start -> span_start --- runtime/src/alloca/arena.rs | 2 +- runtime/src/alloca/hallocator.rs | 2 +- runtime/src/alloca/hedgearena.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runtime/src/alloca/arena.rs b/runtime/src/alloca/arena.rs index f64dbda..11bc001 100644 --- a/runtime/src/alloca/arena.rs +++ b/runtime/src/alloca/arena.rs @@ -3,7 +3,7 @@ use crate::alloca::ptr; pub trait Arena3 { fn new(start: ptr, size: usize) -> Self; - fn start(&self) -> ptr; + fn span_start(&self) -> ptr; fn cur(&self) -> ptr; diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index f078267..7807a9c 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -115,7 +115,7 @@ impl ArenaAllocator3 for HAllocator { ref_arena.add(o.size()); let ptr = ref_arena.cur(); - if ptr == ref_arena.start() { + if ptr == ref_arena.span_start() { let mut block = self.block_by_ptr(ptr) .expect("hz"); match block.slots.pop() { diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 1b4e507..28e6bcf 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -35,8 +35,8 @@ impl Arena3 for HedgeArena { } } - fn start(&self) -> ptr { - self.start + fn span_start(&self) -> ptr { + self.span_start } fn cur(&self) -> ptr { @@ -134,7 +134,7 @@ impl PartialOrd for HedgeArena { impl Ord for HedgeArena { fn cmp(&self, other: &Self) -> std::cmp::Ordering { if self.how_much() == other.how_much() { - self.start().cmp(&other.start()) + self.span_start().cmp(&other.span_start()) } else { self.how_much().cmp(&other.how_much()) } From 75f3f4897ab10941bac9349fdc3538bf84718558 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 16:48:42 +0700 Subject: [PATCH 10/21] progress in the gc module --- runtime/src/alloca/mod.rs | 3 +- runtime/src/gc/mod.rs | 63 ++++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 47cf868..19178c9 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -61,7 +61,8 @@ mod tests { let inst_1 = TestObj { size: 24 }; unsafe { - let ptr = aa.alloc(&inst_1); + let (ptr, pred) = aa.alloc(&inst_1); + assert_eq!(pred, false); assert_ne!(ptr, 0); std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); } diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 63a3bfe..0a36daa 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -6,7 +6,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use std::thread::JoinHandle; use crate::{alloca, threads}; -use crate::alloca::{Arena3, Object}; +use crate::alloca::{ptr, Arena3, Object}; use crate::gc::markqueue::{MarkQueue, MarkQueueElement}; use crate::threads::ThreadPhase; use crate::utils::reg; @@ -85,16 +85,8 @@ impl Gc { let count_for_scan = self.root.len() / count + 1; for j in min(i*count_for_scan, self.root.len())..self.root.len() { - match self.alloca.mark_gray(self.root[j]) { - None => { - local_queue.push(MarkQueueElement::object(self.root[j])) - } - Some(a) => { - if !a.fetch_and_add_in_queue() { - local_queue.push(MarkQueueElement::arena(a)) - } - } - } + self.mark_gray_el_from_ptr(self.root[j], &mut local_queue); + if !(local_queue.len() & 15) { // TODO: make somethink like cfg self.mark_queue.pushn(&mut local_queue); } @@ -183,5 +175,54 @@ impl Gc { fn mark(&mut self, el: MarkQueueElement) { // TODO + let mut local_queue = vec![]; + match el { + MarkQueueElement::arena(arena) => { + let (black, size) = arena.black_map(); + let (gray, size) = arena.gray_map(); + let mut diff_bits = vec![]; + // byte-iter + for i in (0..size).step_by(8) { + unsafe { + diff_bits.push(*((gray + i) as *u64) ^ *((black + i) as *u64)); + } + } + // bit-iter + for i in 0..(size * 8) { + if diff_bits[i / 64] & (1 << (i % 64)) { + unsafe { + *((black + (i / 64)) as *mut u64) |= (1 << (i % 64)); + } + let ptr_to_obj = arena.span_start() + i * 8; + let ptr_to_header = (ptr_to_obj - 8) as * dyn Object; + let size_of_object = ptr_to_header.size(); + for j in 0..size / 8 { + if ptr_to_header.get_bitset_of_ref()[j / 8] & (1 << (j % 8)) { + let field_ptr = ptr_to_obj + j * 8; + self.mark_gray_el_from_ptr(field_ptr, &mut local_queue); + } + } + } + } + } + MarkQueueElement::object(ptr) => { + todo!(); + // делать мне нехуй чтоли + // TODO + } + } + } + + fn mark_gray_el_from_ptr(&mut self, ptr: ptr, source: &mut Vec>) { + match self.alloca.mark_gray(ptr) { + None => { + source.push(MarkQueueElement::object(ptr)) + } + Some(a) => { + if !a.fetch_and_add_in_queue() { + source.push(MarkQueueElement::arena(a)) + } + } + } } } \ No newline at end of file From 8935849dfd34a5c1a74e8b5381f5f9a27aae2343 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 16:49:11 +0700 Subject: [PATCH 11/21] misstake --- runtime/src/gc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 0a36daa..1bc0f3b 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -196,7 +196,7 @@ impl Gc { let ptr_to_obj = arena.span_start() + i * 8; let ptr_to_header = (ptr_to_obj - 8) as * dyn Object; let size_of_object = ptr_to_header.size(); - for j in 0..size / 8 { + for j in 0..size_of_object / 8 { if ptr_to_header.get_bitset_of_ref()[j / 8] & (1 << (j % 8)) { let field_ptr = ptr_to_obj + j * 8; self.mark_gray_el_from_ptr(field_ptr, &mut local_queue); From 0fd414430f0590dfd7c7e391ea3a42accdaf1faf Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 19:21:20 +0700 Subject: [PATCH 12/21] fix misstakes --- runtime/src/gc/markqueue.rs | 17 +++-- runtime/src/gc/mod.rs | 122 ++++++++++++++++++++++-------------- runtime/src/nni/mod.rs | 1 + 3 files changed, 89 insertions(+), 51 deletions(-) diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs index 91d5f94..497962e 100644 --- a/runtime/src/gc/markqueue.rs +++ b/runtime/src/gc/markqueue.rs @@ -3,30 +3,31 @@ pub use crate::alloca::*; pub enum MarkQueueElement<'a, T: Arena3> { arena(&'a mut T), - object(ptr) + object(ptr), + End } pub struct MarkQueue<'a, T: Arena3> { - queue: std::sync::Mutex>>, + queue: std::sync::RwLock>>, } impl<'a, T: Arena3> MarkQueue<'a, T> { pub fn new() -> MarkQueue<'a, T> { Self { - queue: std::sync::Mutex::new(vec![]), + queue: std::sync::RwLock::new(vec![]), } } pub fn pushn(&mut self, elements: &mut Vec>) { self.queue - .lock() + .write() .expect("pushn") .extend(elements); } pub fn popn(&mut self, n: usize) -> Vec> { let mut lock = self.queue - .lock() + .write() .expect("popn"); let bound = min(lock.len(), n); let mut result = vec![]; @@ -35,4 +36,10 @@ impl<'a, T: Arena3> MarkQueue<'a, T> { } result } + + pub fn check(&self) -> Option<&MarkQueueElement<'a, T>> { + self.queue.read() + .expect("check") + .last() + } } \ No newline at end of file diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 1bc0f3b..46e1471 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -1,6 +1,7 @@ mod markqueue; use std::cmp::min; +use std::os::unix::process::parent_id; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; @@ -33,7 +34,7 @@ pub struct Gc<'a, T: Object, U: Arena3> { workers: Vec>, count_active_workers: AtomicUsize, - root: Vec, + root: Vec, mark_queue: MarkQueue<'a, U>, } @@ -92,38 +93,55 @@ impl Gc { } } - loop { - + 'external: loop { while local_queue.len() > 0 { self.mark(local_queue.pop().unwrap()); } - } - - // TODO WORK - - { - if self.count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { - - let mut root_is_done_flag = self.stw_is_done.lock().unwrap(); - self.root = Vec::new(); - *root_is_done_flag = false; - - let mut work_is_done_flag = self.work_is_done.lock().unwrap(); - assert!(!*work_is_done_flag); - *work_is_done_flag = true; - - self.work_cv.notify_all(); - } else { - - let mut work_is_done_flag = self.work_is_done.lock().unwrap(); - while !*work_is_done_flag { - work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() + local_queue = self.mark_queue.popn(16); + if local_queue.len() == 0 { + if self.count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { + self.mark_queue.pushn(&mut vec![MarkQueueElement::End]); + + { + let mut root_is_done_flag = self.stw_is_done.lock().unwrap(); + self.root = Vec::new(); + *root_is_done_flag = false; + + let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + assert!(!*work_is_done_flag); + *work_is_done_flag = true; + + self.work_cv.notify_all(); + } + + break 'external; // for better reading + } else { + loop { + if let last = self.mark_queue.check() + && last.is_some() { + if last.unwrap() == MarkQueueElement::End { + self.count_active_workers.fetch_add(1, Ordering::SeqCst); + + { + let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + while !*work_is_done_flag { + work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() + } + } + break 'external; + } + else { + local_queue = self.mark_queue.popn(16); + break; + } + } + } } } } - + // TODO WORK } })) } @@ -133,35 +151,45 @@ impl Gc { self.threads.go_immut(rbp); - let mut root_is_done_flag = self.stw_is_done.lock().unwrap(); - while !*root_is_done_flag { - root_is_done_flag = self.stw_cv.wait(root_is_done_flag).unwrap() + let mut stw_is_done_flag = self.stw_is_done.lock().unwrap(); + while !*stw_is_done_flag { + stw_is_done_flag = self.stw_cv.wait(stw_is_done_flag).unwrap() } + // TODO } pub fn master(&mut self) { - - let mut heap_is_done_flag = self.heap_is_done.lock().unwrap(); - while !*heap_is_done_flag { - heap_is_done_flag = self.heap_cv.wait(heap_is_done_flag).unwrap() - } - - for item in self.threads.pool.thread_map.iter() { - let nthread = item.value(); - match nthread.phase { - ThreadPhase::Mutable => { - unreachable!(); - } - ThreadPhase::Immutable(cntxt) => { - self.add_to_root(cntxt.rbp); + loop { + + let mut heap_is_done_flag = self.heap_is_done.lock().unwrap(); + while !*heap_is_done_flag { + heap_is_done_flag = self.heap_cv.wait(heap_is_done_flag).unwrap() + } + + for item in self.threads.pool.thread_map.iter() { + let nthread = item.value(); + match nthread.phase { + ThreadPhase::Mutable => { + unreachable!(); + } + ThreadPhase::Immutable(cntxt) => { + self.add_to_root(cntxt.rbp); + } } } + + *(self.stw_is_done) = true; + self.stw_cv.notify_all(); + + *(self.heap_is_done) = false; + + let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + while !*work_is_done_flag { + work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() + } } - - *(self.stw_is_done) = true; - self.stw_cv.notify_all(); } pub fn notify_master(&mut self) { @@ -174,7 +202,6 @@ impl Gc { } fn mark(&mut self, el: MarkQueueElement) { - // TODO let mut local_queue = vec![]; match el { MarkQueueElement::arena(arena) => { @@ -210,6 +237,9 @@ impl Gc { // делать мне нехуй чтоли // TODO } + MarkQueueElement::End() => { + panic!("something went wrong in mark"); + } } } diff --git a/runtime/src/nni/mod.rs b/runtime/src/nni/mod.rs index e69de29..136d063 100644 --- a/runtime/src/nni/mod.rs +++ b/runtime/src/nni/mod.rs @@ -0,0 +1 @@ + \ No newline at end of file From 9c42cf0601e6da5a3c679e90ef14b339283a336f Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 20:29:01 +0700 Subject: [PATCH 13/21] sweep complete --- runtime/src/alloca/allocator.rs | 2 ++ runtime/src/alloca/arena.rs | 4 +++ runtime/src/alloca/hallocator.rs | 42 ++++++++++++++++++++++++++------ runtime/src/alloca/hedgearena.rs | 15 ++++++++++-- runtime/src/gc/mod.rs | 2 ++ 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/runtime/src/alloca/allocator.rs b/runtime/src/alloca/allocator.rs index 4fb7d35..470681c 100644 --- a/runtime/src/alloca/allocator.rs +++ b/runtime/src/alloca/allocator.rs @@ -22,4 +22,6 @@ pub trait ArenaAllocator3 { fn mark_gray(&mut self, ptr: ptr); fn mark_black(&mut self, ptr: ptr); + + fn sweep(&mut self); } \ No newline at end of file diff --git a/runtime/src/alloca/arena.rs b/runtime/src/alloca/arena.rs index 11bc001..45cc5fd 100644 --- a/runtime/src/alloca/arena.rs +++ b/runtime/src/alloca/arena.rs @@ -21,6 +21,10 @@ pub trait Arena3 { fn live(&self) -> bool; + fn alive(&mut self); + + fn kill(&mut self); + fn on(&mut self); fn off(&mut self); diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index 7807a9c..d3b3dfc 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -108,7 +108,7 @@ impl ArenaAllocator3 for HAllocator { .pop() .expect("In new needed_block len(slots)==0\n"); - self.arena_by_heaped(heaped_version_of_first_arena).on(); + self.arena_by_heaped(heaped_version_of_first_arena).alive(); heaped_version_of_first_arena }); let ref_arena = self.arena_by_heaped(heaped_arena); @@ -120,7 +120,7 @@ impl ArenaAllocator3 for HAllocator { .expect("hz"); match block.slots.pop() { Some(heaped_arena_from_slots) => { - self.arena_by_heaped(heaped_arena_from_slots).on(); + self.arena_by_heaped(heaped_arena_from_slots).alive(); self.heap.insert(heaped_arena_from_slots); } None => { @@ -129,7 +129,7 @@ impl ArenaAllocator3 for HAllocator { .slots .pop() .expect("In new needed_block (when a last arena of the block is not empty) len(slots)==0\n"); - self.arena_by_heaped(new_heaped_arena).on(); + self.arena_by_heaped(new_heaped_arena).alive(); self.heap.insert(new_heaped_arena); } } @@ -146,11 +146,16 @@ impl ArenaAllocator3 for HAllocator { fn mark_white(&mut self) { let locked = self.heap.items.lock().expect("lock in white"); - let copy = locked.clone(); - drop(locked); - for heaped_arena_from_slots in copy.iter() { - if let arena = self.arena_by_heaped(heaped_arena_from_slots.clone()) && arena.live() { + + for heaped_arena_from_slots in locked.iter() { + let arena = &mut self.blocks[heaped_arena_from_slots.num_of_block] + .as_mut() + .expect("arena_by_heaped") + .items[heaped_arena_from_slots.num_of_arena]; + + if arena.live() { arena.clear_mark(); + arena.kill() } } @@ -158,6 +163,7 @@ impl ArenaAllocator3 for HAllocator { *large >>= 2; *large <<= 2; } + } fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { @@ -193,6 +199,28 @@ impl ArenaAllocator3 for HAllocator { } } } + + fn sweep(&mut self) { + + let mut locked = self.heap.items.lock().expect("lock in white"); + let mut trash = vec![]; + + for heaped_arena_from_slots in locked.iter() { + let arena = &mut self.blocks[heaped_arena_from_slots.num_of_block] + .as_mut() + .expect("arena_by_heaped") + .items[heaped_arena_from_slots.num_of_arena]; + + if !arena.live() { + arena.kill(); + trash.push(heaped_arena_from_slots) + } + } + + for t in trash.iter_mut() { + locked.remove(t); + } + } } #[derive(Debug)] diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 28e6bcf..6deb28d 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -75,8 +75,8 @@ impl Arena3 for HedgeArena { self.live.load(Ordering::Relaxed) } - fn on(&mut self) { - self.live.store(true, Ordering::Relaxed); + fn alive(&mut self) { + self.on(); unsafe { let res = libc::mmap(self.start as *mut c_void, self.size, @@ -88,6 +88,17 @@ impl Arena3 for HedgeArena { self.clear_mark(); } + fn kill(&mut self) { + unsafe { + let res = libc::munmap(self.start as *mut c_void, self.size); + assert_eq!(res, 0); + } + } + + fn on(&mut self) { + self.live.store(true, Ordering::Relaxed); + } + fn off(&mut self) { self.live.store(false, Ordering::Relaxed); } diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 46e1471..7207ede 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -188,6 +188,7 @@ impl Gc { let mut work_is_done_flag = self.work_is_done.lock().unwrap(); while !*work_is_done_flag { work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() + } } } @@ -205,6 +206,7 @@ impl Gc { let mut local_queue = vec![]; match el { MarkQueueElement::arena(arena) => { + arena.on() let (black, size) = arena.black_map(); let (gray, size) = arena.gray_map(); let mut diff_bits = vec![]; From 230c05eb561d1eec2918c79678685280147a03f6 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 19 Aug 2025 20:40:10 +0700 Subject: [PATCH 14/21] ; --- runtime/src/gc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 7207ede..f14f8fc 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -206,7 +206,7 @@ impl Gc { let mut local_queue = vec![]; match el { MarkQueueElement::arena(arena) => { - arena.on() + arena.on(); let (black, size) = arena.black_map(); let (gray, size) = arena.gray_map(); let mut diff_bits = vec![]; From 6b9b56924f2f2e3db519661b898b790fee10e84c Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Wed, 20 Aug 2025 05:57:51 +0700 Subject: [PATCH 15/21] rewrite alloca --- runtime/src/alloca/allocator.rs | 16 +- runtime/src/alloca/arena.rs | 4 +- runtime/src/alloca/cfg.rs | 38 +++++ runtime/src/alloca/hallocator.rs | 261 +++++++++++++++++------------- runtime/src/alloca/heapedarena.rs | 63 -------- runtime/src/alloca/hedgearena.rs | 7 +- runtime/src/alloca/mod.rs | 28 +++- runtime/src/gc/mod.rs | 25 ++- runtime/src/threads/mod.rs | 2 +- 9 files changed, 230 insertions(+), 214 deletions(-) create mode 100644 runtime/src/alloca/cfg.rs delete mode 100644 runtime/src/alloca/heapedarena.rs diff --git a/runtime/src/alloca/allocator.rs b/runtime/src/alloca/allocator.rs index 470681c..492818d 100644 --- a/runtime/src/alloca/allocator.rs +++ b/runtime/src/alloca/allocator.rs @@ -1,17 +1,9 @@ use std::sync::Arc; -use crate::alloca::{ptr, Object}; +use crate::alloca::{ptr, Cfg, Object}; use crate::alloca::arena::Arena3; pub trait ArenaAllocator3 { - const LOG_CAPACITY_SIZE: usize; - - const LOG_BLOCK_SIZE: usize; - - const LOG_START_ARENA_SIZE: usize; - - const LOG_MAX_ARENA_SIZE: usize; - - fn new(max_size: usize) -> Self; + fn new(config: Cfg) -> Self; fn alloc(&mut self, o: &T) -> (ptr, bool); @@ -19,9 +11,9 @@ pub trait ArenaAllocator3 { fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U>; - fn mark_gray(&mut self, ptr: ptr); + fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U>; - fn mark_black(&mut self, ptr: ptr); + fn mark_black(&mut self, ptr: ptr) -> Option<&mut U>; fn sweep(&mut self); } \ No newline at end of file diff --git a/runtime/src/alloca/arena.rs b/runtime/src/alloca/arena.rs index 45cc5fd..84ba34a 100644 --- a/runtime/src/alloca/arena.rs +++ b/runtime/src/alloca/arena.rs @@ -25,9 +25,9 @@ pub trait Arena3 { fn kill(&mut self); - fn on(&mut self); + fn make_live(&mut self); - fn off(&mut self); + fn temp_kill(&mut self); fn mark_gray(&mut self, ptr: ptr); diff --git a/runtime/src/alloca/cfg.rs b/runtime/src/alloca/cfg.rs new file mode 100644 index 0000000..070ac97 --- /dev/null +++ b/runtime/src/alloca/cfg.rs @@ -0,0 +1,38 @@ + +pub struct Cfg { + pub log_capacity_size: usize, + pub log_block_size: usize, + pub log_start_arena_size: usize, + pub step_arena_size: usize, + pub log_max_arena_size: usize, + pub count_of_tiers: usize, + pub max_size: usize, + pub max_object_size_by_size: fn(usize) -> usize, +} + +impl Cfg { + pub fn new(log_capacity_size: usize, + log_block_size: usize, + log_start_arena_size: usize, + log_max_arena_size: usize, + step_arena_size: usize, + max_size: usize, + max_object_size_by_size: fn(usize) -> usize) -> Self { + + assert!(log_capacity_size > log_block_size); + assert!(log_block_size > log_max_arena_size); + assert!(log_max_arena_size > log_start_arena_size); + assert!(step_arena_size < log_max_arena_size - log_start_arena_size); + + Self { + log_capacity_size, + log_block_size, + log_start_arena_size, + step_arena_size, + log_max_arena_size, + count_of_tiers: ((log_max_arena_size - log_start_arena_size) / step_arena_size) + 1, + max_size, + max_object_size_by_size, + } + } +} \ No newline at end of file diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index d3b3dfc..38d2b65 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -1,75 +1,113 @@ use std::collections::LinkedList; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use crate::alloca::{ptr, Object}; use crate::alloca::allocator::ArenaAllocator3; use crate::alloca::arena::Arena3; -use crate::alloca::heapedarena::{Heap, HeapedArena}; +use crate::alloca::cfg::Cfg; pub struct HAllocator { start: ptr, - max_size: usize, used_memory: AtomicUsize, - heap: Heap, + blocks: Vec>, + num_of_blocks_by_tier: Box<[Box<[usize]>]>, - blocks: Box<[Option>]>, count_of_blocks: AtomicUsize, large_objects: LinkedList, _marker: std::marker::PhantomData, + + + log_capacity_size: usize, + log_block_size: usize, + log_start_arena_size: usize, + step_arena_size: usize, + log_max_arena_size: usize, + count_of_tiers: usize, + max_size: usize, + max_object_size_by_tier: Box usize>, } impl HAllocator { fn block_by_ptr(&mut self, ptr: ptr) -> Option<&mut HedgeBlock> { - assert!(self.start <= ptr); - assert!(ptr < self.start + (1 << Self::LOG_CAPACITY_SIZE)); - self.blocks[ptr >> Self::LOG_BLOCK_SIZE] - .as_mut() + if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { + None + } else { + Some(&mut self.blocks[ptr >> self.log_block_size]) + } } - fn add_new_needed_block(&mut self, size: usize) -> &mut HedgeBlock { - for power in (Self::LOG_START_ARENA_SIZE..=Self::LOG_MAX_ARENA_SIZE).step_by(2) { - if 1 << power > size { + fn add_new_needed_block(&mut self, size: usize) -> &mut U { + for tier in 0..self.count_of_tiers { + if (self.max_object_size_by_tier)(tier) >= size { + let index = self.count_of_blocks.fetch_add(1, Ordering::Relaxed); - self.blocks[index] = Some(HedgeBlock::new - (self.start + (index << Self::LOG_BLOCK_SIZE), - 1 << Self::LOG_BLOCK_SIZE, power, index)); + let mut new_block = HedgeBlock::new( + self.start + (index << self.log_block_size), + 1 << self.log_block_size, + self.log_start_arena_size + tier * self.step_arena_size, + index, // number_of_block + tier, // tier + (self.max_object_size_by_tier)(tier)); + + let index_of_new_arena = new_block.archive.pop().unwrap(); + let ref_arena: &mut U = new_block.items + .get_mut(index_of_new_arena.num_of_arena) + .expect("index out of bounds in add_new_needed_block"); + ref_arena.alive(); + new_block.current = Some(index_of_new_arena); - return self.blocks[index] - .as_mut() - .expect(&format!("arena_by_heaped:\n\ - num_of_block: {}\n", index)); + self.blocks.push(new_block); + return ref_arena + } + } + unreachable!(); + } + + fn arena_tier_by_size(&self, size: usize) -> usize { + for tier in 1..self.count_of_tiers { + if (self.max_object_size_by_tier)(tier) > size { + return tier - 1 } } unreachable!(); } - fn arena_by_heaped(&mut self, arena_from_heap: HeapedArena) -> &mut U { - &mut self.blocks[arena_from_heap.num_of_block] - .as_mut() - .expect(&format!("arena_by_heaped:\n\ - num_of_block: {}\n", arena_from_heap.num_of_block)) - .items[arena_from_heap.num_of_arena] + fn find(&mut self, size: usize) -> Option<&mut U> { + let tier = self.arena_tier_by_size(size); + for num_of_block in self.num_of_blocks_by_tier[tier].iter() { + let mut block = &self.blocks[*num_of_block]; + if block.current.is_some() { + Some(&mut block.items[block.current.unwrap().num_of_arena]); + } + } + None + } + + fn for_each_arena(&mut self, mut f: F) + where + F: FnMut(&mut U), + { + let current_count = self.count_of_blocks.load(Ordering::Relaxed); + + for i in 0..current_count { + let mut block = &self.blocks[i]; + for index_arena in block.active.iter() { + let arena = &mut block.items[index_arena.num_of_arena]; + f(arena); + } + } } } impl ArenaAllocator3 for HAllocator { - const LOG_CAPACITY_SIZE: usize = 37; - const LOG_BLOCK_SIZE: usize = 26; - const LOG_START_ARENA_SIZE: usize = 12; - const LOG_MAX_ARENA_SIZE: usize = 16; - - fn new(max_size: usize) -> Self { - assert!(Self::LOG_CAPACITY_SIZE > Self::LOG_BLOCK_SIZE); - assert!(Self::LOG_BLOCK_SIZE > Self::LOG_MAX_ARENA_SIZE); - assert!(Self::LOG_MAX_ARENA_SIZE > Self::LOG_START_ARENA_SIZE); - + fn new(config: Cfg) -> Self { + unsafe { let start = libc::mmap( std::ptr::null_mut(), - 1 << Self::LOG_CAPACITY_SIZE, + 1 << config.log_capacity_size, libc::PROT_NONE, libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, -1, @@ -83,58 +121,54 @@ impl ArenaAllocator3 for HAllocator { Self { start, - max_size, + max_size: config.max_size, used_memory: AtomicUsize::new(0), - heap: Heap::new(), - blocks: Box::new([const {None}; 1 << (>::LOG_CAPACITY_SIZE - >::LOG_BLOCK_SIZE)]), + blocks: Vec::new(), + num_of_blocks_by_tier: Box::new([]), count_of_blocks: AtomicUsize::new(0), large_objects: LinkedList::new(), _marker: Default::default(), + + log_capacity_size: config.log_capacity_size, + log_block_size: config.log_block_size, + log_start_arena_size: config.log_start_arena_size, + step_arena_size: config.step_arena_size, + log_max_arena_size: config.log_max_arena_size, + count_of_tiers: config.count_of_tiers, + max_object_size_by_tier: Box::new(move |tier| { + (config.max_object_size_by_size)( + 1 << (config.log_start_arena_size + config.step_arena_size * tier) + )}), } } - } + fn alloc(&mut self, o: &T) -> (ptr, bool) { - let mut maybe_heaped_arena = self.heap.get_min_more_then(o.size()); - if maybe_heaped_arena.is_none() { + let real_size = o.size() + 8; - } - let heaped_arena = maybe_heaped_arena.unwrap_or_else(|| { - let heaped_version_of_first_arena = self - .add_new_needed_block(o.size()) - .slots - .pop() - .expect("In new needed_block len(slots)==0\n"); + let mut maybe_ref_arena = self.find(real_size); - self.arena_by_heaped(heaped_version_of_first_arena).alive(); - heaped_version_of_first_arena + let ref_arena = maybe_ref_arena.unwrap_or_else(|| { + self.add_new_needed_block(o.size()) }); - let ref_arena = self.arena_by_heaped(heaped_arena); - ref_arena.add(o.size()); let ptr = ref_arena.cur(); - if ptr == ref_arena.span_start() { - let mut block = self.block_by_ptr(ptr) - .expect("hz"); - match block.slots.pop() { - Some(heaped_arena_from_slots) => { - self.arena_by_heaped(heaped_arena_from_slots).alive(); - self.heap.insert(heaped_arena_from_slots); - } - None => { - let new_heaped_arena = self - .add_new_needed_block(o.size()) - .slots - .pop() - .expect("In new needed_block (when a last arena of the block is not empty) len(slots)==0\n"); - self.arena_by_heaped(new_heaped_arena).alive(); - self.heap.insert(new_heaped_arena); - } - } + ref_arena.add(real_size); + let block_of_arena: &mut HedgeBlock = self + .block_by_ptr(ref_arena.cur()) + .expect("something went wrong"); + + if ref_arena.how_much() < block_of_arena.tier { + block_of_arena.active + .push(block_of_arena.current.unwrap()); + block_of_arena.current = block_of_arena.archive.pop(); + } + + unsafe { + *(ptr as *mut *const T) = o as *const T; } - self.heap.insert(heaped_arena); let used = self.used_memory.load(Ordering::Relaxed); if used > self.max_size { @@ -145,20 +179,10 @@ impl ArenaAllocator3 for HAllocator { } fn mark_white(&mut self) { - let locked = self.heap.items.lock().expect("lock in white"); - - for heaped_arena_from_slots in locked.iter() { - let arena = &mut self.blocks[heaped_arena_from_slots.num_of_block] - .as_mut() - .expect("arena_by_heaped") - .items[heaped_arena_from_slots.num_of_arena]; - - if arena.live() { - arena.clear_mark(); - arena.kill() - } - } - + self.for_each_arena(|arena| { + arena.temp_kill(); + }); + for large in self.large_objects.iter_mut() { *large >>= 2; *large <<= 2; @@ -167,8 +191,8 @@ impl ArenaAllocator3 for HAllocator { } fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { - self.block_by_ptr(ptr) - .map(|block| block.arena_by_ptr(ptr)) + Some(self.block_by_ptr(ptr)? + .arena_by_ptr(ptr)) } @@ -180,7 +204,9 @@ impl ArenaAllocator3 for HAllocator { } None => { *self.large_objects.iter_mut() - .find(|p| (**p >> 2) == (ptr >> 2)) |= 1; + .find(|p| (**p >> 2) == (ptr >> 2)) + .expect("mark_gray") + |= 1; None } } @@ -194,75 +220,82 @@ impl ArenaAllocator3 for HAllocator { } None => { *self.large_objects.iter_mut() - .find(|p| (**p >> 2) == (ptr >> 2)) |= 2; + .find(|p| (**p >> 2) == (ptr >> 2)) + .expect("mark_black") + |= 2; None } } } fn sweep(&mut self) { - - let mut locked = self.heap.items.lock().expect("lock in white"); - let mut trash = vec![]; - - for heaped_arena_from_slots in locked.iter() { - let arena = &mut self.blocks[heaped_arena_from_slots.num_of_block] - .as_mut() - .expect("arena_by_heaped") - .items[heaped_arena_from_slots.num_of_arena]; - + self.for_each_arena(|arena| { if !arena.live() { arena.kill(); - trash.push(heaped_arena_from_slots) - } - } - - for t in trash.iter_mut() { - locked.remove(t); - } + }; + }); } } +#[derive(Debug, Clone, Copy)] +pub struct IndexArena { + pub num_of_block: usize, + pub num_of_arena: usize, +} + #[derive(Debug)] struct HedgeBlock { start: ptr, size: usize, + tier: usize, // the tier define log_arena_size and max_object_size + log_arena_size: usize, + max_object_size: usize, // only for find object by ref. // const items: Box<[U]>, // dynamic - slots: Vec, + archive: Vec, + current: Option, + active: Vec, } impl HedgeBlock { - fn new(start: ptr, size: usize, log_arena_size: usize, number_of_block: usize) -> Self { + fn new(start: ptr, + size: usize, + log_arena_size: usize, + number_of_block: usize, + tier: usize, + max_object_size: usize) -> Self { + let count = size >> log_arena_size; let mut arenas = Vec::with_capacity(count); - let mut slots = Vec::with_capacity(count); + let mut archive = Vec::with_capacity(count); for i in 0..count { arenas.push(U::new(start + (i << log_arena_size), 1 << log_arena_size)); - slots.push(HeapedArena { + archive.push(IndexArena { num_of_block: number_of_block, num_of_arena: i, - param: 1 << log_arena_size, }) } let box_arenas = arenas.into_boxed_slice(); - Self { start, size, + tier, log_arena_size, + max_object_size, items: box_arenas, - slots, + archive, + current: None, + active: Vec::new(), } } diff --git a/runtime/src/alloca/heapedarena.rs b/runtime/src/alloca/heapedarena.rs deleted file mode 100644 index 2e7011d..0000000 --- a/runtime/src/alloca/heapedarena.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::sync::Mutex; -use crate::alloca::arena::Arena3; - -#[derive(Debug, Clone, Copy)] -pub struct HeapedArena { - pub num_of_block: usize, - pub num_of_arena: usize, - pub param: usize -} - -impl Eq for HeapedArena {} - -impl PartialEq for HeapedArena { - fn eq(&self, other: &Self) -> bool { - false - } -} - -impl PartialOrd for HeapedArena { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for HeapedArena { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.param.cmp(&other.param) - } -} - - -pub(crate) struct Heap { - pub(crate) items: Mutex> -} - -impl Heap { - pub(crate) fn new() -> Self { - Self { - items: Mutex::new(std::collections::BTreeSet::new()) - } - } - - pub(crate) fn insert(&mut self, item: HeapedArena) { - self.items.lock().unwrap().insert(item); - } - - - pub(crate) fn get_min_more_then(&mut self, n: usize) -> Option { - assert!(n > 0); - - let etalon = HeapedArena { - num_of_block: 0, - num_of_arena: 0, - param: n - 1, - }; - - let mut guarded = self.items.lock().expect("lock poisoned"); - - let key = guarded.range(etalon..).next().map(|k| k.clone())?; - - Some(guarded.take(&key).expect("error take\n")) - } -} diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 6deb28d..410355c 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -76,7 +76,7 @@ impl Arena3 for HedgeArena { } fn alive(&mut self) { - self.on(); + self.make_live(); unsafe { let res = libc::mmap(self.start as *mut c_void, self.size, @@ -95,12 +95,13 @@ impl Arena3 for HedgeArena { } } - fn on(&mut self) { + fn make_live(&mut self) { self.live.store(true, Ordering::Relaxed); } - fn off(&mut self) { + fn temp_kill(&mut self) { self.live.store(false, Ordering::Relaxed); + self.clear_mark(); } fn mark_gray(&mut self, ptr: ptr) { diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 19178c9..b62ef25 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -2,10 +2,12 @@ mod allocator; mod arena; mod hallocator; mod hedgearena; -mod heapedarena; +mod cfg; + pub use hedgearena::HedgeArena; pub use hallocator::HAllocator; pub use arena::Arena3; +pub use cfg::Cfg; pub(crate) type ptr = usize; @@ -32,6 +34,7 @@ impl Object for ObjectImpl { #[cfg(test)] mod tests { use crate::alloca::allocator::ArenaAllocator3; + use crate::alloca::cfg::Cfg; use crate::alloca::hallocator::HAllocator; use crate::alloca::hedgearena::HedgeArena; use super::*; @@ -50,14 +53,27 @@ mod tests { } } + fn config1() -> Cfg { + Cfg::new( + 37, + 26, + 12, + 20, + 0, + 0, + |size| { + size / 64 + }) + } + #[test] fn create_allocator() { - let aa: HAllocator = HAllocator::new(1<<30); + let aa: HAllocator = HAllocator::new(config1()); } #[test] fn first_alloc() { - let mut aa: HAllocator = HAllocator::new(1<<30); + let mut aa: HAllocator = HAllocator::new(config1()); let inst_1 = TestObj { size: 24 }; unsafe { @@ -71,16 +87,16 @@ mod tests { #[test] fn alloc2() { - let mut aa: HAllocator = HAllocator::new(1<<30); + let mut aa: HAllocator = HAllocator::new(config1()); let inst_1 = TestObj { size: 1024 }; let inst_2 = TestObj { size: 512 }; unsafe { - let ptr = aa.alloc(&inst_1); + let (ptr, _) = aa.alloc(&inst_1); assert_ne!(ptr, 0); std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); - let ptr = aa.alloc(&inst_2); + let (ptr, _) = aa.alloc(&inst_2); assert_ne!(ptr, 0); std::ptr::write_bytes(ptr as *mut u8, 126, inst_2.size / 8); } diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index f14f8fc..46ef781 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -1,16 +1,15 @@ mod markqueue; use std::cmp::min; -use std::os::unix::process::parent_id; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use std::thread::JoinHandle; -use crate::{alloca, threads}; -use crate::alloca::{ptr, Arena3, Object}; -use crate::gc::markqueue::{MarkQueue, MarkQueueElement}; -use crate::threads::ThreadPhase; -use crate::utils::reg; +use crate::{alloca, threads, gc, utils}; +use alloca::{ptr, Arena3, Object, Cfg}; +use threads::ThreadPhase; +use gc::markqueue::{MarkQueue, MarkQueueElement}; +use utils::reg; pub struct Gc<'a, T: Object, U: Arena3> { pub alloca: alloca::HAllocator, @@ -38,11 +37,11 @@ pub struct Gc<'a, T: Object, U: Arena3> { mark_queue: MarkQueue<'a, U>, } -impl Gc { +impl Gc<'_, T, U> { - pub fn new(threads: Arc, max_size: usize) -> Self { + pub fn new(threads: Arc, config: Cfg) -> Self { Self { - alloca: alloca::HAllocator::::new(max_size), + alloca: alloca::HAllocator::::new(config), threads, stw_is_done: Mutex::new(false), stw_cv: Default::default(), @@ -206,14 +205,14 @@ impl Gc { let mut local_queue = vec![]; match el { MarkQueueElement::arena(arena) => { - arena.on(); + arena.make_live(); let (black, size) = arena.black_map(); let (gray, size) = arena.gray_map(); let mut diff_bits = vec![]; // byte-iter for i in (0..size).step_by(8) { unsafe { - diff_bits.push(*((gray + i) as *u64) ^ *((black + i) as *u64)); + diff_bits.push(*((gray + i) as *const u64) ^ *((black + i) as *const u64)); } } // bit-iter @@ -223,7 +222,7 @@ impl Gc { *((black + (i / 64)) as *mut u64) |= (1 << (i % 64)); } let ptr_to_obj = arena.span_start() + i * 8; - let ptr_to_header = (ptr_to_obj - 8) as * dyn Object; + let ptr_to_header = (ptr_to_obj - 8) as *const dyn Object; let size_of_object = ptr_to_header.size(); for j in 0..size_of_object / 8 { if ptr_to_header.get_bitset_of_ref()[j / 8] & (1 << (j % 8)) { @@ -239,7 +238,7 @@ impl Gc { // делать мне нехуй чтоли // TODO } - MarkQueueElement::End() => { + MarkQueueElement::End => { panic!("something went wrong in mark"); } } diff --git a/runtime/src/threads/mod.rs b/runtime/src/threads/mod.rs index d866180..9fd2781 100644 --- a/runtime/src/threads/mod.rs +++ b/runtime/src/threads/mod.rs @@ -29,7 +29,7 @@ impl Threads { } pub fn go_mut(&mut self) { - while self.stw {} + while *self.stw {} self.pool.go_mut(); } From 2ba2994b0fc42b5c70d0087ecc403c62166de9c2 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Fri, 22 Aug 2025 06:00:37 +0700 Subject: [PATCH 16/21] the worst commit ever, dont check please, rust issue --- runtime/src/alloca/allocator.rs | 12 ++- runtime/src/alloca/hallocator.rs | 98 ++++++++++++------ runtime/src/alloca/mod.rs | 50 ++------- runtime/src/gc/markqueue.rs | 29 +++--- runtime/src/gc/mod.rs | 167 +++++++++++++++++-------------- runtime/src/lib.rs | 21 +++- runtime/src/utils/mod.rs | 4 +- runtime/src/utils/object.rs | 5 + runtime/src/utils/treeheap.rs | 32 ------ 9 files changed, 212 insertions(+), 206 deletions(-) create mode 100644 runtime/src/utils/object.rs delete mode 100644 runtime/src/utils/treeheap.rs diff --git a/runtime/src/alloca/allocator.rs b/runtime/src/alloca/allocator.rs index 492818d..2cdddb8 100644 --- a/runtime/src/alloca/allocator.rs +++ b/runtime/src/alloca/allocator.rs @@ -1,15 +1,17 @@ -use std::sync::Arc; -use crate::alloca::{ptr, Cfg, Object}; +use crate::alloca::{ptr, Cfg}; use crate::alloca::arena::Arena3; +use crate::utils::Object; -pub trait ArenaAllocator3 { +pub trait ArenaAllocator3 { fn new(config: Cfg) -> Self; - fn alloc(&mut self, o: &T) -> (ptr, bool); + fn alloc(&mut self, o: &Object) -> (ptr, bool); fn mark_white(&mut self); - fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U>; + fn arena_by_ptr(&self, ptr: usize) -> Option<&U>; + + fn mut_arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U>; fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U>; diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index 38d2b65..b89acd1 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -1,22 +1,20 @@ use std::collections::LinkedList; use std::sync::atomic::{AtomicUsize, Ordering}; -use crate::alloca::{ptr, Object}; +use crate::alloca::ptr; use crate::alloca::allocator::ArenaAllocator3; use crate::alloca::arena::Arena3; use crate::alloca::cfg::Cfg; +use crate::utils::Object; -pub struct HAllocator { +pub struct HAllocator { start: ptr, used_memory: AtomicUsize, blocks: Vec>, - num_of_blocks_by_tier: Box<[Box<[usize]>]>, + num_of_blocks_by_tier: Vec>, - count_of_blocks: AtomicUsize, large_objects: LinkedList, - _marker: std::marker::PhantomData, - log_capacity_size: usize, log_block_size: usize, @@ -25,11 +23,19 @@ pub struct HAllocator { log_max_arena_size: usize, count_of_tiers: usize, max_size: usize, - max_object_size_by_tier: Box usize>, + max_object_size_by_tier: Box usize + Send + Sync>, } -impl HAllocator { - fn block_by_ptr(&mut self, ptr: ptr) -> Option<&mut HedgeBlock> { +impl HAllocator { + fn block_by_ptr(&self, ptr: ptr) -> Option<&HedgeBlock> { + if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { + None + } else { + Some(&self.blocks[ptr >> self.log_block_size]) + } + } + + fn mut_block_by_ptr(&mut self, ptr: ptr) -> Option<&mut HedgeBlock> { if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { None } else { @@ -41,7 +47,7 @@ impl HAllocator { for tier in 0..self.count_of_tiers { if (self.max_object_size_by_tier)(tier) >= size { - let index = self.count_of_blocks.fetch_add(1, Ordering::Relaxed); + let index = self.blocks.len(); let mut new_block = HedgeBlock::new( self.start + (index << self.log_block_size), 1 << self.log_block_size, @@ -50,6 +56,9 @@ impl HAllocator { tier, // tier (self.max_object_size_by_tier)(tier)); + self.blocks.push(new_block); + + let mut new_block = self.blocks.last_mut().unwrap(); let index_of_new_arena = new_block.archive.pop().unwrap(); let ref_arena: &mut U = new_block.items .get_mut(index_of_new_arena.num_of_arena) @@ -57,7 +66,7 @@ impl HAllocator { ref_arena.alive(); new_block.current = Some(index_of_new_arena); - self.blocks.push(new_block); + self.num_of_blocks_by_tier[tier].push(index); return ref_arena } } @@ -76,7 +85,7 @@ impl HAllocator { fn find(&mut self, size: usize) -> Option<&mut U> { let tier = self.arena_tier_by_size(size); for num_of_block in self.num_of_blocks_by_tier[tier].iter() { - let mut block = &self.blocks[*num_of_block]; + let mut block = &mut self.blocks[*num_of_block]; if block.current.is_some() { Some(&mut block.items[block.current.unwrap().num_of_arena]); } @@ -88,10 +97,10 @@ impl HAllocator { where F: FnMut(&mut U), { - let current_count = self.count_of_blocks.load(Ordering::Relaxed); + let current_count = self.blocks.len(); for i in 0..current_count { - let mut block = &self.blocks[i]; + let mut block = &mut self.blocks[i]; for index_arena in block.active.iter() { let arena = &mut block.items[index_arena.num_of_arena]; f(arena); @@ -101,7 +110,7 @@ impl HAllocator { } -impl ArenaAllocator3 for HAllocator { +impl ArenaAllocator3 for HAllocator { fn new(config: Cfg) -> Self { unsafe { @@ -124,10 +133,8 @@ impl ArenaAllocator3 for HAllocator { max_size: config.max_size, used_memory: AtomicUsize::new(0), blocks: Vec::new(), - num_of_blocks_by_tier: Box::new([]), - count_of_blocks: AtomicUsize::new(0), + num_of_blocks_by_tier: vec![Vec::new(); config.count_of_tiers], large_objects: LinkedList::new(), - _marker: Default::default(), log_capacity_size: config.log_capacity_size, log_block_size: config.log_block_size, @@ -145,29 +152,43 @@ impl ArenaAllocator3 for HAllocator { - fn alloc(&mut self, o: &T) -> (ptr, bool) { - let real_size = o.size() + 8; + fn alloc(&mut self, o: &Object) -> (ptr, bool) { + let real_size = o.size + 8; - let mut maybe_ref_arena = self.find(real_size); + // let mut maybe_ref_arena = self.find(real_size); + // + // // let ref_arena = maybe_ref_arena.unwrap_or(self.add_new_needed_block(real_size)); + // let ref_arena = match maybe_ref_arena { + // Some(a) => a, + // None => self.add_new_needed_block(real_size), + // }; + + let ref_arena = { + let maybe_ref_arena = self.find(real_size); + match maybe_ref_arena { + Some(a) => a, + None => self.add_new_needed_block(real_size), + } + }; - let ref_arena = maybe_ref_arena.unwrap_or_else(|| { - self.add_new_needed_block(o.size()) - }); let ptr = ref_arena.cur(); ref_arena.add(real_size); - let block_of_arena: &mut HedgeBlock = self - .block_by_ptr(ref_arena.cur()) + let cur = ref_arena.cur(); + let empty_space = ref_arena.how_much(); + + let block_of_arena= self + .mut_block_by_ptr(cur) .expect("something went wrong"); - if ref_arena.how_much() < block_of_arena.tier { + if empty_space < block_of_arena.tier { block_of_arena.active .push(block_of_arena.current.unwrap()); block_of_arena.current = block_of_arena.archive.pop(); } unsafe { - *(ptr as *mut *const T) = o as *const T; + *(ptr as *mut *const Object) = o as *const Object; } let used = self.used_memory.load(Ordering::Relaxed); @@ -190,15 +211,20 @@ impl ArenaAllocator3 for HAllocator { } - fn arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { + fn arena_by_ptr(&self, ptr: usize) -> Option<&U> { Some(self.block_by_ptr(ptr)? .arena_by_ptr(ptr)) } + fn mut_arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { + Some(self.mut_block_by_ptr(ptr)? + .mut_arena_by_ptr(ptr)) + } fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U> { match self.arena_by_ptr(ptr) { - Some(arena) => { + Some(_) => { + let arena = self.mut_arena_by_ptr(ptr).unwrap(); arena.mark_gray(ptr); Some(arena) } @@ -214,7 +240,8 @@ impl ArenaAllocator3 for HAllocator { fn mark_black(&mut self, ptr: ptr) -> Option<&mut U> { match self.arena_by_ptr(ptr) { - Some(arena) => { + Some(_) => { + let arena = self.mut_arena_by_ptr(ptr).unwrap(); arena.mark_gray(ptr); Some(arena) } @@ -299,10 +326,17 @@ impl HedgeBlock { } } - fn arena_by_ptr(&mut self, ptr: ptr) -> &mut U { + fn mut_arena_by_ptr(&mut self, ptr: ptr) -> &mut U { assert!(self.log_arena_size > 0); assert!(self.start <= ptr); assert!(ptr < self.start + self.size); &mut self.items[(ptr - self.start) >> self.log_arena_size] } + + fn arena_by_ptr(&self, ptr: ptr) -> &U { + assert!(self.log_arena_size > 0); + assert!(self.start <= ptr); + assert!(ptr < self.start + self.size); + &self.items[(ptr - self.start) >> self.log_arena_size] + } } diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index b62ef25..c38eab5 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -5,54 +5,22 @@ mod hedgearena; mod cfg; pub use hedgearena::HedgeArena; -pub use hallocator::HAllocator; +pub use hallocator::{HAllocator, IndexArena}; pub use arena::Arena3; +pub use allocator::ArenaAllocator3; pub use cfg::Cfg; pub(crate) type ptr = usize; -pub trait Object { - fn size(&self) -> usize; - fn get_bitset_of_ref(&self) -> &'static [u8]; -} - -pub struct ObjectImpl { - size: usize, - bitset: &'static [u8], -} - -impl Object for ObjectImpl { - fn size(&self) -> usize { - self.size - } - - fn get_bitset_of_ref(&self) -> &'static [u8] { - self.bitset - } -} - #[cfg(test)] mod tests { use crate::alloca::allocator::ArenaAllocator3; use crate::alloca::cfg::Cfg; use crate::alloca::hallocator::HAllocator; use crate::alloca::hedgearena::HedgeArena; + use crate::utils::Object; use super::*; - struct TestObj { - size: usize, - } - - impl Object for TestObj { - fn size(&self) -> usize { - self.size - } - - fn get_bitset_of_ref(&self) -> &'static [u8] { - todo!() - } - } - fn config1() -> Cfg { Cfg::new( 37, @@ -68,14 +36,14 @@ mod tests { #[test] fn create_allocator() { - let aa: HAllocator = HAllocator::new(config1()); + let aa: HAllocator = HAllocator::new(config1()); } #[test] fn first_alloc() { - let mut aa: HAllocator = HAllocator::new(config1()); + let mut aa: HAllocator = HAllocator::new(config1()); - let inst_1 = TestObj { size: 24 }; + let inst_1 = Object { size: 24, bitset: &[0] }; unsafe { let (ptr, pred) = aa.alloc(&inst_1); assert_eq!(pred, false); @@ -87,10 +55,10 @@ mod tests { #[test] fn alloc2() { - let mut aa: HAllocator = HAllocator::new(config1()); + let mut aa: HAllocator = HAllocator::new(config1()); - let inst_1 = TestObj { size: 1024 }; - let inst_2 = TestObj { size: 512 }; + let inst_1 = Object { size: 1024, bitset: &[0] }; + let inst_2 = Object { size: 512, bitset: &[0] }; unsafe { let (ptr, _) = aa.alloc(&inst_1); assert_ne!(ptr, 0); diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs index 497962e..ad16397 100644 --- a/runtime/src/gc/markqueue.rs +++ b/runtime/src/gc/markqueue.rs @@ -1,31 +1,31 @@ use std::cmp::min; pub use crate::alloca::*; -pub enum MarkQueueElement<'a, T: Arena3> { - arena(&'a mut T), +pub enum MarkQueueElement { + arena(ptr), // start of arena lol object(ptr), End } -pub struct MarkQueue<'a, T: Arena3> { - queue: std::sync::RwLock>>, +pub struct MarkQueue{ + queue: std::sync::RwLock>, } -impl<'a, T: Arena3> MarkQueue<'a, T> { - pub fn new() -> MarkQueue<'a, T> { +impl MarkQueue { + pub fn new() -> MarkQueue { Self { queue: std::sync::RwLock::new(vec![]), } } - pub fn pushn(&mut self, elements: &mut Vec>) { + pub fn pushn(&mut self, elements: &mut Vec) { self.queue .write() - .expect("pushn") - .extend(elements); + .expect("pushn1") + .append(elements); } - pub fn popn(&mut self, n: usize) -> Vec> { + pub fn popn(&mut self, n: usize) -> Vec { let mut lock = self.queue .write() .expect("popn"); @@ -37,9 +37,10 @@ impl<'a, T: Arena3> MarkQueue<'a, T> { result } - pub fn check(&self) -> Option<&MarkQueueElement<'a, T>> { - self.queue.read() - .expect("check") - .last() + pub fn last_is_end(&self) -> bool { + match self.queue.read().expect("last_is_end").last() { + Some(MarkQueueElement::End) => true, + _ => false + } } } \ No newline at end of file diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 46ef781..bb72313 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -6,135 +6,143 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use std::thread::JoinHandle; use crate::{alloca, threads, gc, utils}; -use alloca::{ptr, Arena3, Object, Cfg}; +use alloca::{ptr, Arena3, Cfg, ArenaAllocator3}; use threads::ThreadPhase; use gc::markqueue::{MarkQueue, MarkQueueElement}; use utils::reg; +use utils::object::Object; +use crate::alloca::IndexArena; -pub struct Gc<'a, T: Object, U: Arena3> { - pub alloca: alloca::HAllocator, +pub struct Gc { + pub alloca: Arc>, threads: Arc, - stw_is_done: Mutex, - stw_cv: std::sync::Condvar, + stw_is_done: &'static mut Mutex, + stw_cv: &'static mut std::sync::Condvar, - heap_is_done: Mutex, - heap_cv: std::sync::Condvar, + heap_is_done: &'static mut Mutex, + heap_cv: &'static mut std::sync::Condvar, - mark_is_done: Mutex, - mark_cv: std::sync::Condvar, + mark_is_done: &'static mut Mutex, + mark_cv: &'static mut std::sync::Condvar, - root_is_done: Mutex, - root_cv: std::sync::Condvar, + root_is_done: &'static mut Mutex, + root_cv: &'static mut std::sync::Condvar, - work_is_done: Mutex, - work_cv: std::sync::Condvar, + work_is_done: &'static mut Mutex, + work_cv: &'static mut std::sync::Condvar, workers: Vec>, - count_active_workers: AtomicUsize, + count_active_workers: &'static mut AtomicUsize, - root: Vec, - mark_queue: MarkQueue<'a, U>, + root: &'static mut Vec, + mark_queue: &'static mut MarkQueue, } -impl Gc<'_, T, U> { +impl Gc { pub fn new(threads: Arc, config: Cfg) -> Self { Self { - alloca: alloca::HAllocator::::new(config), + alloca: Arc::new(alloca::HAllocator::::new(config)), threads, - stw_is_done: Mutex::new(false), - stw_cv: Default::default(), + stw_is_done: Box::leak(Box::new(Mutex::new(false))), + stw_cv: Box::leak(Box::new(Default::default())), - heap_is_done: Mutex::new(false), - heap_cv: Default::default(), + heap_is_done: Box::leak(Box::new(Mutex::new(false))), + heap_cv: Box::leak(Box::new(Default::default())), - mark_is_done: Mutex::new(false), - mark_cv: Default::default(), + mark_is_done: Box::leak(Box::new(Mutex::new(false))), + mark_cv: Box::leak(Box::new(Default::default())), - root_is_done: Mutex::new(false), - root_cv: Default::default(), + root_is_done: Box::leak(Box::new(Mutex::new(false))), + root_cv: Box::leak(Box::new(Default::default())), - work_is_done: Mutex::new(false), - work_cv: Default::default(), + work_is_done: Box::leak(Box::new(Mutex::new(false))), + work_cv: Box::leak(Box::new(Default::default())), workers: Vec::new(), - count_active_workers: AtomicUsize::new(0), + count_active_workers: Box::leak(Box::new(AtomicUsize::new(0))), - root: Vec::new(), - mark_queue: MarkQueue::new(), + root: Box::leak(Box::new(Vec::new())), + mark_queue: Box::leak(Box::new(MarkQueue::new())), } } pub fn init_workers(&mut self, count: usize) { assert_ne!(self.workers.len(), 0); - self.count_active_workers = AtomicUsize::from(count); + self.count_active_workers = Box::leak(Box::new(AtomicUsize::from(count))); + let thread_root_is_done = &self.root_is_done; + let thread_stw_cv = &self.stw_cv; + let thread_root = &self.root; + let thread_alloca = &self.alloca; + let mut thread_mark_queue = &mut self.mark_queue; + let thread_count_active_workers = &mut self.count_active_workers; + let thread_stw_is_done = &self.stw_is_done; + let thread_work_is_done = &self.work_is_done; + let thread_work_cv = &self.work_cv; + + let mut workers = Vec::with_capacity(count); for i in 0..count { - self.workers.push(thread::spawn(move || { + workers.push(thread::spawn(move || { loop { { - let mut root_is_done_flag = self.root_is_done.lock().unwrap(); + let mut root_is_done_flag = thread_root_is_done.lock().unwrap(); while !*root_is_done_flag { - root_is_done_flag = self.stw_cv.wait(root_is_done_flag).unwrap() + root_is_done_flag = thread_stw_cv.wait(root_is_done_flag).unwrap() } } let mut local_queue = vec![]; - let count_for_scan = self.root.len() / count + 1; - for j in min(i*count_for_scan, self.root.len())..self.root.len() { - self.mark_gray_el_from_ptr(self.root[j], &mut local_queue); + let count_for_scan = thread_root.len() / count + 1; + for j in min(i*count_for_scan, thread_root.len())..thread_root.len() { + Self::mark_gray_el_from_ptr(thread_alloca.clone(), thread_root[j], &mut local_queue); - if !(local_queue.len() & 15) { // TODO: make somethink like cfg - self.mark_queue.pushn(&mut local_queue); + if !(local_queue.len() & 15 == 0) { // TODO: make somethink like cfg + (*thread_mark_queue).pushn(&mut local_queue); } } 'external: loop { while local_queue.len() > 0 { - self.mark(local_queue.pop().unwrap()); + Self::mark(thread_alloca.clone(), local_queue.pop().unwrap()); } - local_queue = self.mark_queue.popn(16); + local_queue = (*thread_mark_queue).popn(16); if local_queue.len() == 0 { - if self.count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { - self.mark_queue.pushn(&mut vec![MarkQueueElement::End]); + if thread_count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { + (*thread_mark_queue).pushn(&mut vec![MarkQueueElement::End]); { - let mut root_is_done_flag = self.stw_is_done.lock().unwrap(); - self.root = Vec::new(); + let mut root_is_done_flag = thread_stw_is_done.lock().unwrap(); + self.root = Box::leak(Box::new(Vec::new())); *root_is_done_flag = false; - let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + let mut work_is_done_flag = thread_work_is_done.lock().unwrap(); assert!(!*work_is_done_flag); *work_is_done_flag = true; - self.work_cv.notify_all(); + thread_work_cv.notify_all(); } break 'external; // for better reading } else { loop { - if let last = self.mark_queue.check() - && last.is_some() { - if last.unwrap() == MarkQueueElement::End { - self.count_active_workers.fetch_add(1, Ordering::SeqCst); - - { - let mut work_is_done_flag = self.work_is_done.lock().unwrap(); - while !*work_is_done_flag { - work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() - } + if (*thread_mark_queue).last_is_end() { + thread_count_active_workers.fetch_add(1, Ordering::SeqCst); + { + let mut work_is_done_flag = thread_work_is_done.lock().unwrap(); + while !*work_is_done_flag { + work_is_done_flag = thread_work_cv.wait(work_is_done_flag).unwrap() } - break 'external; - } - else { - local_queue = self.mark_queue.popn(16); - break; } + break 'external; + } else { + local_queue = (*thread_mark_queue).popn(16); + break; } } } @@ -179,10 +187,10 @@ impl Gc<'_, T, U> { } } - *(self.stw_is_done) = true; + *self.stw_is_done.get_mut().unwrap() = true; self.stw_cv.notify_all(); - *(self.heap_is_done) = false; + *self.heap_is_done.get_mut().unwrap()= false; let mut work_is_done_flag = self.work_is_done.lock().unwrap(); while !*work_is_done_flag { @@ -193,7 +201,7 @@ impl Gc<'_, T, U> { } pub fn notify_master(&mut self) { - *(self.heap_is_done) = true; + *self.heap_is_done.get_mut().unwrap() = true; self.heap_cv.notify_all(); } @@ -201,10 +209,11 @@ impl Gc<'_, T, U> { // TODO } - fn mark(&mut self, el: MarkQueueElement) { + fn mark(mut alloca: Arc>, el: MarkQueueElement) { let mut local_queue = vec![]; match el { - MarkQueueElement::arena(arena) => { + MarkQueueElement::arena(ptr_on_arena) => { + let arena = alloca.mut_arena_by_ptr(ptr_on_arena).unwrap(); arena.make_live(); let (black, size) = arena.black_map(); let (gray, size) = arena.gray_map(); @@ -217,17 +226,21 @@ impl Gc<'_, T, U> { } // bit-iter for i in 0..(size * 8) { - if diff_bits[i / 64] & (1 << (i % 64)) { + if (diff_bits[i / 64] & (1 << (i % 64))) != 0 { unsafe { *((black + (i / 64)) as *mut u64) |= (1 << (i % 64)); } let ptr_to_obj = arena.span_start() + i * 8; - let ptr_to_header = (ptr_to_obj - 8) as *const dyn Object; - let size_of_object = ptr_to_header.size(); + let ptr_to_header = (ptr_to_obj - 8) as *const Object; + let size_of_object = unsafe { + ptr_to_header.as_ref_unchecked().size + }; for j in 0..size_of_object / 8 { - if ptr_to_header.get_bitset_of_ref()[j / 8] & (1 << (j % 8)) { + if (unsafe { + ptr_to_header.as_ref_unchecked().bitset + }[j / 8] & (1 << (j % 8))) != 0 { let field_ptr = ptr_to_obj + j * 8; - self.mark_gray_el_from_ptr(field_ptr, &mut local_queue); + Self::mark_gray_el_from_ptr(alloca.clone(), field_ptr, &mut local_queue); } } } @@ -244,14 +257,16 @@ impl Gc<'_, T, U> { } } - fn mark_gray_el_from_ptr(&mut self, ptr: ptr, source: &mut Vec>) { - match self.alloca.mark_gray(ptr) { + fn mark_gray_el_from_ptr(mut alloca: Arc>, + ptr: ptr, + source: &mut Vec) { + match alloca.mark_gray(ptr) { None => { source.push(MarkQueueElement::object(ptr)) } Some(a) => { if !a.fetch_and_add_in_queue() { - source.push(MarkQueueElement::arena(a)) + source.push(MarkQueueElement::arena(a.span_start())) } } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 287223f..82328ab 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,4 +1,5 @@ #![feature(let_chains)] +#![feature(ptr_as_ref_unchecked)] mod alloca; mod nni; @@ -8,17 +9,29 @@ mod gc; use std::sync::Arc; use utils::*; +use crate::alloca::Cfg; +use crate::alloca::ArenaAllocator3; static mut THREADS: Option> = None; -static mut GC: Option> = None; +static mut GC: Option> = None; + pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { unsafe { let athreads = Arc::new(threads::Threads::new(stw)); THREADS = Some(athreads.clone()); - GC = Some(gc::Gc::new(athreads, 8 << 40)); + GC = Some(gc::Gc::new(athreads, Cfg::new( + 37, + 26, + 12, + 20, + 0, + 0, + |size| { + size / 64 + }))); THREADS.as_mut() .unwrap() @@ -30,10 +43,10 @@ pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { } } -pub extern "C" fn alloc(t: &dyn alloca::Object) -> alloca::ptr { +pub extern "C" fn alloc(t: &Object) -> alloca::ptr { unsafe { let gc = GC.as_mut().expect("gc is none (alloc)"); - let (ptr, heap_is_overflow) = gc.alloca.alloc(t);; + let (ptr, heap_is_overflow) = gc.alloca.alloc(t); if heap_is_overflow { gc.notify_master(); } diff --git a/runtime/src/utils/mod.rs b/runtime/src/utils/mod.rs index 0418d3d..cfeac1a 100644 --- a/runtime/src/utils/mod.rs +++ b/runtime/src/utils/mod.rs @@ -1,5 +1,5 @@ -mod treeheap; +pub mod object; pub type reg = usize; -pub use treeheap::*; \ No newline at end of file +pub use object::*; \ No newline at end of file diff --git a/runtime/src/utils/object.rs b/runtime/src/utils/object.rs new file mode 100644 index 0000000..b1ae6fe --- /dev/null +++ b/runtime/src/utils/object.rs @@ -0,0 +1,5 @@ + +pub struct Object { + pub size: usize, + pub bitset: &'static [u8], +} \ No newline at end of file diff --git a/runtime/src/utils/treeheap.rs b/runtime/src/utils/treeheap.rs deleted file mode 100644 index 6ac9454..0000000 --- a/runtime/src/utils/treeheap.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::collections::BTreeSet; - -pub(crate) trait KeyFromUsize { - fn from_usize(n: usize) -> Self; -} - -#[derive(Debug)] -pub(crate) struct TreeHeap { - pub items: std::sync::RwLock>, -} - -impl TreeHeap { - pub fn new() -> Self { - Self { - items: std::sync::RwLock::new(BTreeSet::new()), - } - } - - pub fn insert(&self, item: T) { - self.items.write().unwrap().insert(item); - } - - pub fn get_min_more_than(&self, n: usize) -> Option { - let etalon = T::from_usize(n - 1); - - let mut guarded = self.items.read().unwrap(); - - let key = guarded.range(etalon..).next()?.clone(); - - Some(guarded.take(&key).expect("Never fails in treeheap")) - } -} From 99dd8e5048f4944219e6625a5f3b4e13cd760bdb Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 26 Aug 2025 02:36:35 +0700 Subject: [PATCH 17/21] this fcking bitch compiled --- runtime/src/alloca/allocator.rs | 34 +- runtime/src/alloca/arena.rs | 72 ++-- runtime/src/alloca/cfg.rs | 71 ++-- runtime/src/alloca/hallocator.rs | 598 +++++++++++++++--------------- runtime/src/alloca/hedgearena.rs | 276 +++++++------- runtime/src/alloca/mod.rs | 125 ++++--- runtime/src/gc/markqueue.rs | 65 ++-- runtime/src/gc/mod.rs | 514 +++++++++++++------------ runtime/src/lib.rs | 104 +++--- runtime/src/nni/mod.rs | 2 +- runtime/src/threads/mod.rs | 56 +-- runtime/src/threads/nthread.rs | 32 +- runtime/src/threads/threadpool.rs | 125 ++++--- runtime/src/utils/mod.rs | 2 +- runtime/src/utils/object.rs | 7 +- 15 files changed, 1063 insertions(+), 1020 deletions(-) diff --git a/runtime/src/alloca/allocator.rs b/runtime/src/alloca/allocator.rs index 2cdddb8..9088260 100644 --- a/runtime/src/alloca/allocator.rs +++ b/runtime/src/alloca/allocator.rs @@ -1,21 +1,21 @@ -use crate::alloca::{ptr, Cfg}; use crate::alloca::arena::Arena3; +use crate::alloca::{Cfg, ptr}; use crate::utils::Object; pub trait ArenaAllocator3 { - fn new(config: Cfg) -> Self; - - fn alloc(&mut self, o: &Object) -> (ptr, bool); - - fn mark_white(&mut self); - - fn arena_by_ptr(&self, ptr: usize) -> Option<&U>; - - fn mut_arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U>; - - fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U>; - - fn mark_black(&mut self, ptr: ptr) -> Option<&mut U>; - - fn sweep(&mut self); -} \ No newline at end of file + fn new(config: &Cfg) -> Self; + + fn alloc(&mut self, o: &Object) -> (ptr, bool); + + fn mark_white(&mut self); + + fn arena_by_ptr(&self, ptr: usize) -> Option<&U>; + + fn mut_arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U>; + + fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U>; + + fn mark_black(&mut self, ptr: ptr) -> Option<&mut U>; + + fn sweep(&mut self); +} diff --git a/runtime/src/alloca/arena.rs b/runtime/src/alloca/arena.rs index 84ba34a..1e3b79a 100644 --- a/runtime/src/alloca/arena.rs +++ b/runtime/src/alloca/arena.rs @@ -1,39 +1,39 @@ use crate::alloca::ptr; pub trait Arena3 { - fn new(start: ptr, size: usize) -> Self; - - fn span_start(&self) -> ptr; - - fn cur(&self) -> ptr; - - fn add(&mut self, size: usize); - - fn size(&self) -> usize; - - fn how_much(&self) -> usize; - - fn gray_map(&self) ->(ptr, usize); - - fn black_map(&self) ->(ptr, usize); - - fn clear_mark(&mut self); - - fn live(&self) -> bool; - - fn alive(&mut self); - - fn kill(&mut self); - - fn make_live(&mut self); - - fn temp_kill(&mut self); - - fn mark_gray(&mut self, ptr: ptr); - - fn mark_black(&mut self, ptr: ptr); - - fn fetch_and_add_in_queue(&mut self) -> bool; - - fn fetch_and_take_from_queue(&mut self) -> bool; -} \ No newline at end of file + fn new(start: ptr, size: usize) -> Self; + + fn span_start(&self) -> ptr; + + fn cur(&self) -> ptr; + + fn add(&mut self, size: usize); + + fn size(&self) -> usize; + + fn how_much(&self) -> usize; + + fn gray_map(&self) -> (ptr, usize); + + fn black_map(&self) -> (ptr, usize); + + fn clear_mark(&mut self); + + fn live(&self) -> bool; + + fn alive(&mut self); + + fn kill(&mut self); + + fn make_live(&mut self); + + fn temp_kill(&mut self); + + fn mark_gray(&mut self, ptr: ptr); + + fn mark_black(&mut self, ptr: ptr); + + fn fetch_and_add_in_queue(&mut self) -> bool; + + fn fetch_and_take_from_queue(&mut self) -> bool; +} diff --git a/runtime/src/alloca/cfg.rs b/runtime/src/alloca/cfg.rs index 070ac97..b906638 100644 --- a/runtime/src/alloca/cfg.rs +++ b/runtime/src/alloca/cfg.rs @@ -1,38 +1,43 @@ - pub struct Cfg { - pub log_capacity_size: usize, - pub log_block_size: usize, - pub log_start_arena_size: usize, - pub step_arena_size: usize, - pub log_max_arena_size: usize, - pub count_of_tiers: usize, - pub max_size: usize, - pub max_object_size_by_size: fn(usize) -> usize, + pub log_capacity_size: usize, + pub log_block_size: usize, + pub log_start_arena_size: usize, + pub step_arena_size: usize, + pub log_max_arena_size: usize, + pub count_of_tiers: usize, + pub max_size: usize, + pub max_object_size_by_size: fn(usize) -> usize, + + pub count_gc_workers: usize, } impl Cfg { - pub fn new(log_capacity_size: usize, - log_block_size: usize, - log_start_arena_size: usize, - log_max_arena_size: usize, - step_arena_size: usize, - max_size: usize, - max_object_size_by_size: fn(usize) -> usize) -> Self { - - assert!(log_capacity_size > log_block_size); - assert!(log_block_size > log_max_arena_size); - assert!(log_max_arena_size > log_start_arena_size); - assert!(step_arena_size < log_max_arena_size - log_start_arena_size); - - Self { - log_capacity_size, - log_block_size, - log_start_arena_size, - step_arena_size, - log_max_arena_size, - count_of_tiers: ((log_max_arena_size - log_start_arena_size) / step_arena_size) + 1, - max_size, - max_object_size_by_size, + pub fn new( + log_capacity_size: usize, + log_block_size: usize, + log_start_arena_size: usize, + log_max_arena_size: usize, + step_arena_size: usize, + max_size: usize, + max_object_size_by_size: fn(usize) -> usize, + count_gc_workers: usize, + ) -> Self { + assert!(log_capacity_size > log_block_size); + assert!(log_block_size > log_max_arena_size); + assert!(log_max_arena_size > log_start_arena_size); + assert!(step_arena_size < log_max_arena_size - log_start_arena_size); + assert!(count_gc_workers > 0); + + Self { + log_capacity_size, + log_block_size, + log_start_arena_size, + step_arena_size, + log_max_arena_size, + count_of_tiers: ((log_max_arena_size - log_start_arena_size) / step_arena_size) + 1, + max_size, + max_object_size_by_size, + count_gc_workers, + } } - } -} \ No newline at end of file +} diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index b89acd1..57f242b 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -1,342 +1,334 @@ -use std::collections::LinkedList; -use std::sync::atomic::{AtomicUsize, Ordering}; -use crate::alloca::ptr; use crate::alloca::allocator::ArenaAllocator3; use crate::alloca::arena::Arena3; use crate::alloca::cfg::Cfg; +use crate::alloca::ptr; use crate::utils::Object; +use std::collections::LinkedList; +use std::sync::atomic::{AtomicUsize, Ordering}; pub struct HAllocator { - start: ptr, - used_memory: AtomicUsize, - - blocks: Vec>, - num_of_blocks_by_tier: Vec>, - - large_objects: LinkedList, - - - log_capacity_size: usize, - log_block_size: usize, - log_start_arena_size: usize, - step_arena_size: usize, - log_max_arena_size: usize, - count_of_tiers: usize, - max_size: usize, - max_object_size_by_tier: Box usize + Send + Sync>, + start: ptr, + used_memory: AtomicUsize, + + blocks: Vec>, + num_of_blocks_by_tier: Vec>, + + large_objects: LinkedList, + + log_capacity_size: usize, + log_block_size: usize, + log_start_arena_size: usize, + step_arena_size: usize, + log_max_arena_size: usize, + count_of_tiers: usize, + max_size: usize, + max_object_size_by_tier: Box usize + Send + Sync>, } impl HAllocator { - fn block_by_ptr(&self, ptr: ptr) -> Option<&HedgeBlock> { - if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { - None - } else { - Some(&self.blocks[ptr >> self.log_block_size]) + fn block_by_ptr(&self, ptr: ptr) -> Option<&HedgeBlock> { + if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { + None + } else { + Some(&self.blocks[ptr >> self.log_block_size]) + } } - } - - fn mut_block_by_ptr(&mut self, ptr: ptr) -> Option<&mut HedgeBlock> { - if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { - None - } else { - Some(&mut self.blocks[ptr >> self.log_block_size]) + + fn mut_block_by_ptr(&mut self, ptr: ptr) -> Option<&mut HedgeBlock> { + if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { + None + } else { + Some(&mut self.blocks[ptr >> self.log_block_size]) + } } - } - - fn add_new_needed_block(&mut self, size: usize) -> &mut U { - for tier in 0..self.count_of_tiers { - if (self.max_object_size_by_tier)(tier) >= size { - - let index = self.blocks.len(); - let mut new_block = HedgeBlock::new( - self.start + (index << self.log_block_size), - 1 << self.log_block_size, - self.log_start_arena_size + tier * self.step_arena_size, - index, // number_of_block - tier, // tier - (self.max_object_size_by_tier)(tier)); - - self.blocks.push(new_block); - - let mut new_block = self.blocks.last_mut().unwrap(); - let index_of_new_arena = new_block.archive.pop().unwrap(); - let ref_arena: &mut U = new_block.items - .get_mut(index_of_new_arena.num_of_arena) - .expect("index out of bounds in add_new_needed_block"); - ref_arena.alive(); - new_block.current = Some(index_of_new_arena); - - self.num_of_blocks_by_tier[tier].push(index); - return ref_arena - } + + fn add_new_needed_block(&mut self, size: usize) -> &mut U { + for tier in 0..self.count_of_tiers { + if (self.max_object_size_by_tier)(tier) >= size { + let index = self.blocks.len(); + let mut new_block = HedgeBlock::new( + self.start + (index << self.log_block_size), + 1 << self.log_block_size, + self.log_start_arena_size + tier * self.step_arena_size, + index, // number_of_block + tier, // tier + (self.max_object_size_by_tier)(tier), + ); + + self.blocks.push(new_block); + + let mut new_block = self.blocks.last_mut().unwrap(); + let index_of_new_arena = new_block.archive.pop().unwrap(); + let ref_arena: &mut U = new_block + .items + .get_mut(index_of_new_arena.num_of_arena) + .expect("index out of bounds in add_new_needed_block"); + ref_arena.alive(); + new_block.current = Some(index_of_new_arena); + + self.num_of_blocks_by_tier[tier].push(index); + return ref_arena; + } + } + unreachable!(); } - unreachable!(); - } - - fn arena_tier_by_size(&self, size: usize) -> usize { - for tier in 1..self.count_of_tiers { - if (self.max_object_size_by_tier)(tier) > size { - return tier - 1 - } + + fn arena_tier_by_size(&self, size: usize) -> usize { + for tier in 1..self.count_of_tiers { + if (self.max_object_size_by_tier)(tier) > size { + return tier - 1; + } + } + unreachable!(); } - unreachable!(); - } - - fn find(&mut self, size: usize) -> Option<&mut U> { - let tier = self.arena_tier_by_size(size); - for num_of_block in self.num_of_blocks_by_tier[tier].iter() { - let mut block = &mut self.blocks[*num_of_block]; - if block.current.is_some() { - Some(&mut block.items[block.current.unwrap().num_of_arena]); - } + + fn find(&mut self, size: usize) -> Option<&mut U> { + let tier = self.arena_tier_by_size(size); + for num_of_block in self.num_of_blocks_by_tier[tier].iter() { + let mut block = &mut self.blocks[*num_of_block]; + if block.current.is_some() { + Some(&mut block.items[block.current.unwrap().num_of_arena]); + } + } + None } - None - } - - fn for_each_arena(&mut self, mut f: F) - where - F: FnMut(&mut U), - { - let current_count = self.blocks.len(); - - for i in 0..current_count { - let mut block = &mut self.blocks[i]; - for index_arena in block.active.iter() { - let arena = &mut block.items[index_arena.num_of_arena]; - f(arena); - } + + fn for_each_arena(&mut self, mut f: F) + where + F: FnMut(&mut U), + { + let current_count = self.blocks.len(); + + for i in 0..current_count { + let mut block = &mut self.blocks[i]; + for index_arena in block.active.iter() { + let arena = &mut block.items[index_arena.num_of_arena]; + f(arena); + } + } } - } } - impl ArenaAllocator3 for HAllocator { - fn new(config: Cfg) -> Self { - - unsafe { - let start = libc::mmap( - std::ptr::null_mut(), - 1 << config.log_capacity_size, - libc::PROT_NONE, - libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, - -1, - 0 - ) as ptr; - - - if start == 0 { - panic!("reserve mmap failed"); - } - - Self { - start, - max_size: config.max_size, - used_memory: AtomicUsize::new(0), - blocks: Vec::new(), - num_of_blocks_by_tier: vec![Vec::new(); config.count_of_tiers], - large_objects: LinkedList::new(), - - log_capacity_size: config.log_capacity_size, - log_block_size: config.log_block_size, - log_start_arena_size: config.log_start_arena_size, - step_arena_size: config.step_arena_size, - log_max_arena_size: config.log_max_arena_size, - count_of_tiers: config.count_of_tiers, - max_object_size_by_tier: Box::new(move |tier| { - (config.max_object_size_by_size)( - 1 << (config.log_start_arena_size + config.step_arena_size * tier) - )}), - } + fn new(config: &Cfg) -> Self { + unsafe { + let start = libc::mmap( + std::ptr::null_mut(), + 1 << config.log_capacity_size, + libc::PROT_NONE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ) as ptr; + + if start == 0 { + panic!("reserve mmap failed"); + } + + let mosns = config.max_object_size_by_size; + let lsas = config.log_start_arena_size; + let sas = config.step_arena_size; + Self { + start, + max_size: config.max_size, + used_memory: AtomicUsize::new(0), + blocks: Vec::new(), + num_of_blocks_by_tier: vec![Vec::new(); config.count_of_tiers], + large_objects: LinkedList::new(), + + log_capacity_size: config.log_capacity_size, + log_block_size: config.log_block_size, + log_start_arena_size: config.log_start_arena_size, + step_arena_size: config.step_arena_size, + log_max_arena_size: config.log_max_arena_size, + count_of_tiers: config.count_of_tiers, + max_object_size_by_tier: Box::new(move |tier| mosns(1 << (lsas + sas * tier))), + } + } } - } - - - - fn alloc(&mut self, o: &Object) -> (ptr, bool) { - let real_size = o.size + 8; - - // let mut maybe_ref_arena = self.find(real_size); - // - // // let ref_arena = maybe_ref_arena.unwrap_or(self.add_new_needed_block(real_size)); - // let ref_arena = match maybe_ref_arena { - // Some(a) => a, - // None => self.add_new_needed_block(real_size), - // }; - - let ref_arena = { - let maybe_ref_arena = self.find(real_size); - match maybe_ref_arena { - Some(a) => a, - None => self.add_new_needed_block(real_size), - } - }; - - let ptr = ref_arena.cur(); - - ref_arena.add(real_size); - let cur = ref_arena.cur(); - let empty_space = ref_arena.how_much(); - - let block_of_arena= self - .mut_block_by_ptr(cur) - .expect("something went wrong"); - - if empty_space < block_of_arena.tier { - block_of_arena.active - .push(block_of_arena.current.unwrap()); - block_of_arena.current = block_of_arena.archive.pop(); + + fn alloc(&mut self, o: &Object) -> (ptr, bool) { + let real_size = o.size + 8; + + // let mut maybe_ref_arena = self.find(real_size); + // + // // let ref_arena = maybe_ref_arena.unwrap_or(self.add_new_needed_block(real_size)); + // let ref_arena = match maybe_ref_arena { + // Some(a) => a, + // None => self.add_new_needed_block(real_size), + // }; + + let ref_arena = { + let maybe_ref_arena = self.find(real_size); + match maybe_ref_arena { + Some(a) => a, + None => self.add_new_needed_block(real_size), + } + }; + + let ptr = ref_arena.cur(); + + ref_arena.add(real_size); + let cur = ref_arena.cur(); + let empty_space = ref_arena.how_much(); + + let block_of_arena = self.mut_block_by_ptr(cur).expect("something went wrong"); + + if empty_space < block_of_arena.tier { + block_of_arena.active.push(block_of_arena.current.unwrap()); + block_of_arena.current = block_of_arena.archive.pop(); + } + + unsafe { + *(ptr as *mut *const Object) = o as *const Object; + } + + let used = self.used_memory.load(Ordering::Relaxed); + if used > self.max_size { + (ptr, true) + } else { + (ptr, false) + } } - - unsafe { - *(ptr as *mut *const Object) = o as *const Object; + + fn mark_white(&mut self) { + self.for_each_arena(|arena| { + arena.temp_kill(); + }); + + for large in self.large_objects.iter_mut() { + *large >>= 2; + *large <<= 2; + } } - - let used = self.used_memory.load(Ordering::Relaxed); - if used > self.max_size { - (ptr, true) - } else { - (ptr, false) + + fn arena_by_ptr(&self, ptr: usize) -> Option<&U> { + Some(self.block_by_ptr(ptr)?.arena_by_ptr(ptr)) } - } - - fn mark_white(&mut self) { - self.for_each_arena(|arena| { - arena.temp_kill(); - }); - - for large in self.large_objects.iter_mut() { - *large >>= 2; - *large <<= 2; + + fn mut_arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { + Some(self.mut_block_by_ptr(ptr)?.mut_arena_by_ptr(ptr)) } - - } - - fn arena_by_ptr(&self, ptr: usize) -> Option<&U> { - Some(self.block_by_ptr(ptr)? - .arena_by_ptr(ptr)) - } - - fn mut_arena_by_ptr(&mut self, ptr: usize) -> Option<&mut U> { - Some(self.mut_block_by_ptr(ptr)? - .mut_arena_by_ptr(ptr)) - } - - fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U> { - match self.arena_by_ptr(ptr) { - Some(_) => { - let arena = self.mut_arena_by_ptr(ptr).unwrap(); - arena.mark_gray(ptr); - Some(arena) - } - None => { - *self.large_objects.iter_mut() - .find(|p| (**p >> 2) == (ptr >> 2)) - .expect("mark_gray") - |= 1; - None - } + + fn mark_gray(&mut self, ptr: ptr) -> Option<&mut U> { + match self.arena_by_ptr(ptr) { + Some(_) => { + let arena = self.mut_arena_by_ptr(ptr).unwrap(); + arena.mark_gray(ptr); + Some(arena) + } + None => { + *self + .large_objects + .iter_mut() + .find(|p| (**p >> 2) == (ptr >> 2)) + .expect("mark_gray") |= 1; + None + } + } } - } - - fn mark_black(&mut self, ptr: ptr) -> Option<&mut U> { - match self.arena_by_ptr(ptr) { - Some(_) => { - let arena = self.mut_arena_by_ptr(ptr).unwrap(); - arena.mark_gray(ptr); - Some(arena) - } - None => { - *self.large_objects.iter_mut() - .find(|p| (**p >> 2) == (ptr >> 2)) - .expect("mark_black") - |= 2; - None - } + + fn mark_black(&mut self, ptr: ptr) -> Option<&mut U> { + match self.arena_by_ptr(ptr) { + Some(_) => { + let arena = self.mut_arena_by_ptr(ptr).unwrap(); + arena.mark_gray(ptr); + Some(arena) + } + None => { + *self + .large_objects + .iter_mut() + .find(|p| (**p >> 2) == (ptr >> 2)) + .expect("mark_black") |= 2; + None + } + } + } + + fn sweep(&mut self) { + self.for_each_arena(|arena| { + if !arena.live() { + arena.kill(); + }; + }); } - } - - fn sweep(&mut self) { - self.for_each_arena(|arena| { - if !arena.live() { - arena.kill(); - }; - }); - } } #[derive(Debug, Clone, Copy)] pub struct IndexArena { - pub num_of_block: usize, - pub num_of_arena: usize, + pub num_of_block: usize, + pub num_of_arena: usize, } #[derive(Debug)] struct HedgeBlock { - start: ptr, - - size: usize, - - tier: usize, // the tier define log_arena_size and max_object_size - - log_arena_size: usize, - max_object_size: usize, - - // only for find object by ref. - // const - items: Box<[U]>, - - // dynamic - archive: Vec, - current: Option, - active: Vec, + start: ptr, + + size: usize, + + tier: usize, // the tier define log_arena_size and max_object_size + + log_arena_size: usize, + max_object_size: usize, + + // only for find object by ref. + // const + items: Box<[U]>, + + // dynamic + archive: Vec, + current: Option, + active: Vec, } impl HedgeBlock { - fn new(start: ptr, - size: usize, - log_arena_size: usize, - number_of_block: usize, - tier: usize, - max_object_size: usize) -> Self { - - let count = size >> log_arena_size; - - let mut arenas = Vec::with_capacity(count); - let mut archive = Vec::with_capacity(count); - for i in 0..count { - arenas.push(U::new(start + (i << log_arena_size), 1 << log_arena_size)); - archive.push(IndexArena { - num_of_block: number_of_block, - num_of_arena: i, - }) + fn new( + start: ptr, + size: usize, + log_arena_size: usize, + number_of_block: usize, + tier: usize, + max_object_size: usize, + ) -> Self { + let count = size >> log_arena_size; + + let mut arenas = Vec::with_capacity(count); + let mut archive = Vec::with_capacity(count); + for i in 0..count { + arenas.push(U::new(start + (i << log_arena_size), 1 << log_arena_size)); + archive.push(IndexArena { + num_of_block: number_of_block, + num_of_arena: i, + }) + } + + let box_arenas = arenas.into_boxed_slice(); + + Self { + start, + size, + tier, + log_arena_size, + max_object_size, + items: box_arenas, + archive, + current: None, + active: Vec::new(), + } } - - let box_arenas = arenas.into_boxed_slice(); - - Self { - start, - size, - tier, - log_arena_size, - max_object_size, - items: box_arenas, - archive, - current: None, - active: Vec::new(), + + fn mut_arena_by_ptr(&mut self, ptr: ptr) -> &mut U { + assert!(self.log_arena_size > 0); + assert!(self.start <= ptr); + assert!(ptr < self.start + self.size); + &mut self.items[(ptr - self.start) >> self.log_arena_size] + } + + fn arena_by_ptr(&self, ptr: ptr) -> &U { + assert!(self.log_arena_size > 0); + assert!(self.start <= ptr); + assert!(ptr < self.start + self.size); + &self.items[(ptr - self.start) >> self.log_arena_size] } - } - - fn mut_arena_by_ptr(&mut self, ptr: ptr) -> &mut U { - assert!(self.log_arena_size > 0); - assert!(self.start <= ptr); - assert!(ptr < self.start + self.size); - &mut self.items[(ptr - self.start) >> self.log_arena_size] - } - - fn arena_by_ptr(&self, ptr: ptr) -> &U { - assert!(self.log_arena_size > 0); - assert!(self.start <= ptr); - assert!(ptr < self.start + self.size); - &self.items[(ptr - self.start) >> self.log_arena_size] - } } diff --git a/runtime/src/alloca/hedgearena.rs b/runtime/src/alloca/hedgearena.rs index 410355c..3b3a9a9 100644 --- a/runtime/src/alloca/hedgearena.rs +++ b/runtime/src/alloca/hedgearena.rs @@ -1,154 +1,160 @@ +use crate::alloca::arena::Arena3; +use crate::alloca::ptr; use std::ffi::c_void; use std::sync::atomic::{AtomicBool, Ordering}; -use crate::alloca::ptr; -use crate::alloca::arena::Arena3; #[derive(Debug)] pub struct HedgeArena { - start: ptr, - cur: ptr, - size: usize, // = 32x - - span_start: ptr, - - // gray: Box<[u8]>, - // black: Box<[u8]>, - - live: AtomicBool, // хз пока нужен ли, мб оставлю только map, юуду смотреть на None - - /// dbg only - objects: Vec, - - in_queue: AtomicBool, + start: ptr, + cur: ptr, + size: usize, // = 32x + + span_start: ptr, + + // gray: Box<[u8]>, + // black: Box<[u8]>, + live: AtomicBool, // хз пока нужен ли, мб оставлю только map, юуду смотреть на None + + /// dbg only + objects: Vec, + + in_queue: AtomicBool, } impl Arena3 for HedgeArena { - fn new(start: ptr, size: usize) -> Self { - Self { - start, - cur: start, - size, - span_start: start + (size >> 5), - live: Default::default(), - objects: vec![], - in_queue: Default::default(), - } - } - - fn span_start(&self) -> ptr { - self.span_start - } - - fn cur(&self) -> ptr { - self.cur - } - - fn add(&mut self, size: usize) { - self.cur += size - } - - fn size(&self) -> usize { - self.size - } - - fn how_much(&self) -> usize { - self.start + self.size - self.cur - } - - fn gray_map(&self) -> (ptr, usize) { - (self.start, self.size >> 6) - } - - fn black_map(&self) -> (ptr, usize) { - (self.start + (self.size >> 6), self.size >> 6) - } - - fn clear_mark(&mut self) { - let size_mark = self.span_start - self.start; - assert!(size_mark > 0); - unsafe { - std::ptr::write_bytes(self.start as *mut u8, 0, size_mark as usize); - } - } - - fn live(&self) -> bool { - self.live.load(Ordering::Relaxed) - } - - fn alive(&mut self) { - self.make_live(); - - unsafe { - let res = libc::mmap(self.start as *mut c_void, self.size, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_FIXED, - -1, 0); - assert_ne!(res, libc::MAP_FAILED); - } - self.clear_mark(); - } - - fn kill(&mut self) { - unsafe { - let res = libc::munmap(self.start as *mut c_void, self.size); - assert_eq!(res, 0); - } - } - - fn make_live(&mut self) { - self.live.store(true, Ordering::Relaxed); - } - - fn temp_kill(&mut self) { - self.live.store(false, Ordering::Relaxed); - self.clear_mark(); - } - - fn mark_gray(&mut self, ptr: ptr) { - let offset = ptr - self.span_start; - let index = offset >> 3; - unsafe { - std::ptr::write((self.start + (index >> 3)) as *mut u8, (index % 8) as u8); - } - } - - fn mark_black(&mut self, ptr: ptr) { - let offset = ptr - self.span_start; - let index = offset >> 3; - unsafe { - std::ptr::write(((self.start + self.span_start >> 1) + (index >> 3)) as *mut u8, (index % 8) as u8); - } - } - - fn fetch_and_add_in_queue(&mut self) -> bool { - self.in_queue.fetch_or(true, Ordering::SeqCst) - } - - fn fetch_and_take_from_queue(&mut self) -> bool { - self.in_queue.fetch_and(false, Ordering::SeqCst) - } + fn new(start: ptr, size: usize) -> Self { + Self { + start, + cur: start, + size, + span_start: start + (size >> 5), + live: Default::default(), + objects: vec![], + in_queue: Default::default(), + } + } + + fn span_start(&self) -> ptr { + self.span_start + } + + fn cur(&self) -> ptr { + self.cur + } + + fn add(&mut self, size: usize) { + self.cur += size + } + + fn size(&self) -> usize { + self.size + } + + fn how_much(&self) -> usize { + self.start + self.size - self.cur + } + + fn gray_map(&self) -> (ptr, usize) { + (self.start, self.size >> 6) + } + + fn black_map(&self) -> (ptr, usize) { + (self.start + (self.size >> 6), self.size >> 6) + } + + fn clear_mark(&mut self) { + let size_mark = self.span_start - self.start; + assert!(size_mark > 0); + unsafe { + std::ptr::write_bytes(self.start as *mut u8, 0, size_mark as usize); + } + } + + fn live(&self) -> bool { + self.live.load(Ordering::Relaxed) + } + + fn alive(&mut self) { + self.make_live(); + + unsafe { + let res = libc::mmap( + self.start as *mut c_void, + self.size, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_FIXED, + -1, + 0, + ); + assert_ne!(res, libc::MAP_FAILED); + } + self.clear_mark(); + } + + fn kill(&mut self) { + unsafe { + let res = libc::munmap(self.start as *mut c_void, self.size); + assert_eq!(res, 0); + } + } + + fn make_live(&mut self) { + self.live.store(true, Ordering::Relaxed); + } + + fn temp_kill(&mut self) { + self.live.store(false, Ordering::Relaxed); + self.clear_mark(); + } + + fn mark_gray(&mut self, ptr: ptr) { + let offset = ptr - self.span_start; + let index = offset >> 3; + unsafe { + std::ptr::write((self.start + (index >> 3)) as *mut u8, (index % 8) as u8); + } + } + + fn mark_black(&mut self, ptr: ptr) { + let offset = ptr - self.span_start; + let index = offset >> 3; + unsafe { + std::ptr::write( + ((self.start + self.span_start >> 1) + (index >> 3)) as *mut u8, + (index % 8) as u8, + ); + } + } + + fn fetch_and_add_in_queue(&mut self) -> bool { + self.in_queue.fetch_or(true, Ordering::SeqCst) + } + + fn fetch_and_take_from_queue(&mut self) -> bool { + self.in_queue.fetch_and(false, Ordering::SeqCst) + } } impl Eq for HedgeArena {} impl PartialEq for HedgeArena { - fn eq(&self, other: &Self) -> bool { - false - } + fn eq(&self, other: &Self) -> bool { + false + } } impl PartialOrd for HedgeArena { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } impl Ord for HedgeArena { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - if self.how_much() == other.how_much() { - self.span_start().cmp(&other.span_start()) - } else { - self.how_much().cmp(&other.how_much()) - } - } -} \ No newline at end of file + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + if self.how_much() == other.how_much() { + self.span_start().cmp(&other.span_start()) + } else { + self.how_much().cmp(&other.how_much()) + } + } +} diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index c38eab5..0a9f34e 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -1,73 +1,80 @@ mod allocator; mod arena; +mod cfg; mod hallocator; mod hedgearena; -mod cfg; -pub use hedgearena::HedgeArena; -pub use hallocator::{HAllocator, IndexArena}; -pub use arena::Arena3; pub use allocator::ArenaAllocator3; +pub use arena::Arena3; pub use cfg::Cfg; +pub use hallocator::{HAllocator, IndexArena}; +pub use hedgearena::HedgeArena; pub(crate) type ptr = usize; #[cfg(test)] mod tests { - use crate::alloca::allocator::ArenaAllocator3; - use crate::alloca::cfg::Cfg; - use crate::alloca::hallocator::HAllocator; - use crate::alloca::hedgearena::HedgeArena; - use crate::utils::Object; - use super::*; - - fn config1() -> Cfg { - Cfg::new( - 37, - 26, - 12, - 20, - 0, - 0, - |size| { - size / 64 - }) - } - - #[test] - fn create_allocator() { - let aa: HAllocator = HAllocator::new(config1()); - } - - #[test] - fn first_alloc() { - let mut aa: HAllocator = HAllocator::new(config1()); - - let inst_1 = Object { size: 24, bitset: &[0] }; - unsafe { - let (ptr, pred) = aa.alloc(&inst_1); - assert_eq!(pred, false); - assert_ne!(ptr, 0); - std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); + use super::*; + use crate::alloca::allocator::ArenaAllocator3; + use crate::alloca::cfg::Cfg; + use crate::alloca::hallocator::HAllocator; + use crate::alloca::hedgearena::HedgeArena; + use crate::utils::Object; + + fn config1() -> &'static Cfg { + Box::leak(Box::new(Cfg::new( + 37, + 26, + 12, + 20, + 0, + 0, + |size| size / 64, + 3, + ))) } - - } - - #[test] - fn alloc2() { - let mut aa: HAllocator = HAllocator::new(config1()); - - let inst_1 = Object { size: 1024, bitset: &[0] }; - let inst_2 = Object { size: 512, bitset: &[0] }; - unsafe { - let (ptr, _) = aa.alloc(&inst_1); - assert_ne!(ptr, 0); - std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); - - let (ptr, _) = aa.alloc(&inst_2); - assert_ne!(ptr, 0); - std::ptr::write_bytes(ptr as *mut u8, 126, inst_2.size / 8); + + #[test] + fn create_allocator() { + let aa: HAllocator = HAllocator::new(config1()); + } + + #[test] + fn first_alloc() { + let mut aa: HAllocator = HAllocator::new(config1()); + + let inst_1 = Object { + size: 24, + bitset: &[0], + }; + unsafe { + let (ptr, pred) = aa.alloc(&inst_1); + assert_eq!(pred, false); + assert_ne!(ptr, 0); + std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); + } + } + + #[test] + fn alloc2() { + let mut aa: HAllocator = HAllocator::new(config1()); + + let inst_1 = Object { + size: 1024, + bitset: &[0], + }; + let inst_2 = Object { + size: 512, + bitset: &[0], + }; + unsafe { + let (ptr, _) = aa.alloc(&inst_1); + assert_ne!(ptr, 0); + std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); + + let (ptr, _) = aa.alloc(&inst_2); + assert_ne!(ptr, 0); + std::ptr::write_bytes(ptr as *mut u8, 126, inst_2.size / 8); + } } - } - -} \ No newline at end of file +} diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs index ad16397..a891b50 100644 --- a/runtime/src/gc/markqueue.rs +++ b/runtime/src/gc/markqueue.rs @@ -1,46 +1,41 @@ -use std::cmp::min; pub use crate::alloca::*; +use std::cmp::min; pub enum MarkQueueElement { - arena(ptr), // start of arena lol - object(ptr), - End + arena(ptr), // start of arena lol + object(ptr), + End, } -pub struct MarkQueue{ - queue: std::sync::RwLock>, +pub struct MarkQueue { + queue: std::sync::RwLock>, } impl MarkQueue { - pub fn new() -> MarkQueue { - Self { - queue: std::sync::RwLock::new(vec![]), + pub fn new() -> MarkQueue { + Self { + queue: std::sync::RwLock::new(vec![]), + } } - } - - pub fn pushn(&mut self, elements: &mut Vec) { - self.queue - .write() - .expect("pushn1") - .append(elements); - } - - pub fn popn(&mut self, n: usize) -> Vec { - let mut lock = self.queue - .write() - .expect("popn"); - let bound = min(lock.len(), n); - let mut result = vec![]; - for _ in 0..bound { - result.push(lock.pop().expect("popn copy")); + + pub fn pushn(&self, elements: &mut Vec) { + self.queue.write().expect("pushn1").append(elements); } - result - } - - pub fn last_is_end(&self) -> bool { - match self.queue.read().expect("last_is_end").last() { - Some(MarkQueueElement::End) => true, - _ => false + + pub fn popn(&self, n: usize) -> Vec { + let mut lock = self.queue.write().expect("popn"); + let bound = min(lock.len(), n); + let mut result = vec![]; + for _ in 0..bound { + result.push(lock.pop().expect("popn copy")); + } + result } - } -} \ No newline at end of file + + pub fn last_is_end(&self) -> bool { + match self.queue.read().expect("last_is_end").last() { + Some(MarkQueueElement::End) => true, + _ => false, + } + } +} diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index bb72313..7b8d85d 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -1,274 +1,298 @@ mod markqueue; +use crate::alloca::IndexArena; +use crate::{alloca, gc, threads, utils}; +use alloca::{Arena3, ArenaAllocator3, Cfg, ptr}; +use gc::markqueue::{MarkQueue, MarkQueueElement}; +use libc::abort; +use std::cell::{RefCell, RefMut}; use std::cmp::min; -use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, Mutex}; use std::thread; use std::thread::JoinHandle; -use crate::{alloca, threads, gc, utils}; -use alloca::{ptr, Arena3, Cfg, ArenaAllocator3}; use threads::ThreadPhase; -use gc::markqueue::{MarkQueue, MarkQueueElement}; -use utils::reg; use utils::object::Object; -use crate::alloca::IndexArena; +use utils::reg; + +// struct Arc(Arc>); +// +// impl Arc { +// pub fn new(value: T) -> Arc { +// Arc(Arc::new(RefCell::new(value))) +// } +// +// pub fn borrow_mut(&self) -> RefMut<'_, T> { +// self.0.borrow_mut +// } +// +// pub fn clone(&self) -> Arc { +// Arc(self.0.clone()) +// } +// } pub struct Gc { - pub alloca: Arc>, - - threads: Arc, - - stw_is_done: &'static mut Mutex, - stw_cv: &'static mut std::sync::Condvar, - - heap_is_done: &'static mut Mutex, - heap_cv: &'static mut std::sync::Condvar, - - mark_is_done: &'static mut Mutex, - mark_cv: &'static mut std::sync::Condvar, - - root_is_done: &'static mut Mutex, - root_cv: &'static mut std::sync::Condvar, - - work_is_done: &'static mut Mutex, - work_cv: &'static mut std::sync::Condvar, - workers: Vec>, - count_active_workers: &'static mut AtomicUsize, - - root: &'static mut Vec, - mark_queue: &'static mut MarkQueue, + pub alloca: Arc>>, + + threads: Arc>, + + stw_is_done: Arc>, + stw_cv: Arc, + + heap_is_done: Arc>, + heap_cv: Arc, + + mark_is_done: Arc>, + mark_cv: Arc, + + root_is_done: Arc>, + root_cv: Arc, + + work_is_done: Arc>, + work_cv: Arc, + workers: Vec>, + count_active_workers: Arc, + + root: Arc>, + mark_queue: Arc, } impl Gc { - - pub fn new(threads: Arc, config: Cfg) -> Self { - Self { - alloca: Arc::new(alloca::HAllocator::::new(config)), - threads, - stw_is_done: Box::leak(Box::new(Mutex::new(false))), - stw_cv: Box::leak(Box::new(Default::default())), - - heap_is_done: Box::leak(Box::new(Mutex::new(false))), - heap_cv: Box::leak(Box::new(Default::default())), - - mark_is_done: Box::leak(Box::new(Mutex::new(false))), - mark_cv: Box::leak(Box::new(Default::default())), - - root_is_done: Box::leak(Box::new(Mutex::new(false))), - root_cv: Box::leak(Box::new(Default::default())), - - work_is_done: Box::leak(Box::new(Mutex::new(false))), - work_cv: Box::leak(Box::new(Default::default())), - - workers: Vec::new(), - count_active_workers: Box::leak(Box::new(AtomicUsize::new(0))), - - root: Box::leak(Box::new(Vec::new())), - mark_queue: Box::leak(Box::new(MarkQueue::new())), + pub fn new(threads: Arc>, config: &Cfg) -> Self { + Self { + alloca: Arc::new(Mutex::new(alloca::HAllocator::::new(config))), + threads, + stw_is_done: Arc::new(Mutex::new(false)), + stw_cv: Arc::new(Default::default()), + + heap_is_done: Arc::new(Mutex::new(false)), + heap_cv: Arc::new(Default::default()), + + mark_is_done: Arc::new(Mutex::new(false)), + mark_cv: Arc::new(Default::default()), + + root_is_done: Arc::new(Mutex::new(false)), + root_cv: Arc::new(Default::default()), + + work_is_done: Arc::new(Mutex::new(false)), + work_cv: Arc::new(Default::default()), + + workers: Vec::new(), + count_active_workers: Arc::new(AtomicUsize::new(config.count_gc_workers)), + + root: Arc::new(Vec::new()), + mark_queue: Arc::new(MarkQueue::new()), + } } - } - - pub fn init_workers(&mut self, count: usize) { - assert_ne!(self.workers.len(), 0); - - self.count_active_workers = Box::leak(Box::new(AtomicUsize::from(count))); - - let thread_root_is_done = &self.root_is_done; - let thread_stw_cv = &self.stw_cv; - let thread_root = &self.root; - let thread_alloca = &self.alloca; - let mut thread_mark_queue = &mut self.mark_queue; - let thread_count_active_workers = &mut self.count_active_workers; - let thread_stw_is_done = &self.stw_is_done; - let thread_work_is_done = &self.work_is_done; - let thread_work_cv = &self.work_cv; - - let mut workers = Vec::with_capacity(count); - for i in 0..count { - workers.push(thread::spawn(move || { - loop { - { - let mut root_is_done_flag = thread_root_is_done.lock().unwrap(); - - while !*root_is_done_flag { - root_is_done_flag = thread_stw_cv.wait(root_is_done_flag).unwrap() - } - } - let mut local_queue = vec![]; - - let count_for_scan = thread_root.len() / count + 1; - for j in min(i*count_for_scan, thread_root.len())..thread_root.len() { - Self::mark_gray_el_from_ptr(thread_alloca.clone(), thread_root[j], &mut local_queue); - - if !(local_queue.len() & 15 == 0) { // TODO: make somethink like cfg - (*thread_mark_queue).pushn(&mut local_queue); - } - } - - 'external: loop { - - while local_queue.len() > 0 { - Self::mark(thread_alloca.clone(), local_queue.pop().unwrap()); - } - - local_queue = (*thread_mark_queue).popn(16); - if local_queue.len() == 0 { - if thread_count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { - (*thread_mark_queue).pushn(&mut vec![MarkQueueElement::End]); - - { - let mut root_is_done_flag = thread_stw_is_done.lock().unwrap(); - self.root = Box::leak(Box::new(Vec::new())); - *root_is_done_flag = false; - - let mut work_is_done_flag = thread_work_is_done.lock().unwrap(); - assert!(!*work_is_done_flag); - *work_is_done_flag = true; - - thread_work_cv.notify_all(); - } - - break 'external; // for better reading - } else { + + pub fn init_workers(&self, count: usize) { + assert_ne!(self.workers.len(), 0); + + let mut workers = Vec::with_capacity(count); + for i in 0..count { + let thread_root_is_done = self.root_is_done.clone(); + let thread_stw_cv = self.stw_cv.clone(); + let mut thread_root = self.root.clone(); + let thread_alloca = self.alloca.clone(); + let thread_mark_queue = self.mark_queue.clone().clone(); + let thread_count_active_workers = self.count_active_workers.clone(); + let thread_stw_is_done = self.stw_is_done.clone(); + let thread_work_is_done = self.work_is_done.clone(); + let thread_work_cv = self.work_cv.clone(); + workers.push(thread::spawn(move || { loop { - if (*thread_mark_queue).last_is_end() { - thread_count_active_workers.fetch_add(1, Ordering::SeqCst); { - let mut work_is_done_flag = thread_work_is_done.lock().unwrap(); - while !*work_is_done_flag { - work_is_done_flag = thread_work_cv.wait(work_is_done_flag).unwrap() - } + let mut root_is_done_flag = thread_root_is_done.lock().unwrap(); + + while !*root_is_done_flag { + root_is_done_flag = thread_stw_cv.wait(root_is_done_flag).unwrap() + } } - break 'external; - } else { - local_queue = (*thread_mark_queue).popn(16); - break; - } + let mut local_queue = vec![]; + + let count_for_scan = thread_root.len() / count + 1; + for j in min(i * count_for_scan, thread_root.len())..thread_root.len() { + Self::mark_gray_el_from_ptr( + thread_alloca.clone(), + thread_root[j], + &mut local_queue, + ); + + if !(local_queue.len() & 15 == 0) { + // TODO: make somethink like cfg + (*thread_mark_queue).pushn(&mut local_queue); + } + } + + 'external: loop { + while local_queue.len() > 0 { + Self::mark(thread_alloca.clone(), local_queue.pop().unwrap()); + } + + local_queue = (*thread_mark_queue).popn(16); + if local_queue.len() == 0 { + if thread_count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { + (*thread_mark_queue).pushn(&mut vec![MarkQueueElement::End]); + + { + let mut root_is_done_flag = thread_stw_is_done.lock().unwrap(); + thread_root = Arc::new(Vec::new()); + *root_is_done_flag = false; + + let mut work_is_done_flag = thread_work_is_done.lock().unwrap(); + assert!(!*work_is_done_flag); + *work_is_done_flag = true; + + thread_work_cv.notify_all(); + } + + break 'external; // for better reading + } else { + loop { + if (*thread_mark_queue).last_is_end() { + thread_count_active_workers.fetch_add(1, Ordering::SeqCst); + { + let mut work_is_done_flag = + thread_work_is_done.lock().unwrap(); + while !*work_is_done_flag { + work_is_done_flag = + thread_work_cv.wait(work_is_done_flag).unwrap() + } + } + break 'external; + } else { + local_queue = (*thread_mark_queue).popn(16); + break; + } + } + } + } + } + // TODO WORK } - } - } - } - // TODO WORK + })) } - })) } - } - - pub fn go_gc(&mut self, rbp: reg) { - self.threads.go_immut(rbp); - - - let mut stw_is_done_flag = self.stw_is_done.lock().unwrap(); - while !*stw_is_done_flag { - stw_is_done_flag = self.stw_cv.wait(stw_is_done_flag).unwrap() - } - - - // TODO - } - - pub fn master(&mut self) { - loop { - - let mut heap_is_done_flag = self.heap_is_done.lock().unwrap(); - while !*heap_is_done_flag { - heap_is_done_flag = self.heap_cv.wait(heap_is_done_flag).unwrap() - } - - for item in self.threads.pool.thread_map.iter() { - let nthread = item.value(); - match nthread.phase { - ThreadPhase::Mutable => { - unreachable!(); - } - ThreadPhase::Immutable(cntxt) => { - self.add_to_root(cntxt.rbp); - } + + pub fn go_gc(&mut self, rbp: reg) { + self.threads.lock().unwrap().go_immut(rbp); + + let mut stw_is_done_flag = self.stw_is_done.lock().unwrap(); + while !*stw_is_done_flag { + stw_is_done_flag = self.stw_cv.wait(stw_is_done_flag).unwrap() } - } - - *self.stw_is_done.get_mut().unwrap() = true; - self.stw_cv.notify_all(); - - *self.heap_is_done.get_mut().unwrap()= false; - - let mut work_is_done_flag = self.work_is_done.lock().unwrap(); - while !*work_is_done_flag { - work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() - - } + + // TODO } - } - - pub fn notify_master(&mut self) { - *self.heap_is_done.get_mut().unwrap() = true; - self.heap_cv.notify_all(); - } - - fn add_to_root(&mut self, rbp: reg) { - // TODO - } - - fn mark(mut alloca: Arc>, el: MarkQueueElement) { - let mut local_queue = vec![]; - match el { - MarkQueueElement::arena(ptr_on_arena) => { - let arena = alloca.mut_arena_by_ptr(ptr_on_arena).unwrap(); - arena.make_live(); - let (black, size) = arena.black_map(); - let (gray, size) = arena.gray_map(); - let mut diff_bits = vec![]; - // byte-iter - for i in (0..size).step_by(8) { - unsafe { - diff_bits.push(*((gray + i) as *const u64) ^ *((black + i) as *const u64)); - } - } - // bit-iter - for i in 0..(size * 8) { - if (diff_bits[i / 64] & (1 << (i % 64))) != 0 { - unsafe { - *((black + (i / 64)) as *mut u64) |= (1 << (i % 64)); + + pub fn master(&mut self) { + loop { + { + let mut heap_is_done_flag = self.heap_is_done.lock().unwrap(); + while !*heap_is_done_flag { + heap_is_done_flag = self.heap_cv.wait(heap_is_done_flag).unwrap() + } } - let ptr_to_obj = arena.span_start() + i * 8; - let ptr_to_header = (ptr_to_obj - 8) as *const Object; - let size_of_object = unsafe { - ptr_to_header.as_ref_unchecked().size - }; - for j in 0..size_of_object / 8 { - if (unsafe { - ptr_to_header.as_ref_unchecked().bitset - }[j / 8] & (1 << (j % 8))) != 0 { - let field_ptr = ptr_to_obj + j * 8; - Self::mark_gray_el_from_ptr(alloca.clone(), field_ptr, &mut local_queue); - } + + let threads = self.threads.clone(); + let guard_threads = threads.lock().unwrap(); + for item in guard_threads.pool.thread_map.iter() { + let nthread = item.value(); + match nthread.phase { + ThreadPhase::Mutable => { + unreachable!(); + } + ThreadPhase::Immutable(cntxt) => { + self.add_to_root(cntxt.rbp); + } + } + } + + *self.stw_is_done.lock().unwrap() = true; + self.stw_cv.notify_all(); + + *self.heap_is_done.lock().unwrap() = false; + + let mut work_is_done_flag = self.work_is_done.lock().unwrap(); + while !*work_is_done_flag { + work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() } - } } - } - MarkQueueElement::object(ptr) => { - todo!(); - // делать мне нехуй чтоли + } + + pub fn notify_master(&self) { + *self.heap_is_done.lock().unwrap() = true; + self.heap_cv.notify_all(); + } + + fn add_to_root(&mut self, rbp: reg) { // TODO - } - MarkQueueElement::End => { - panic!("something went wrong in mark"); - } } - } - - fn mark_gray_el_from_ptr(mut alloca: Arc>, - ptr: ptr, - source: &mut Vec) { - match alloca.mark_gray(ptr) { - None => { - source.push(MarkQueueElement::object(ptr)) - } - Some(a) => { - if !a.fetch_and_add_in_queue() { - source.push(MarkQueueElement::arena(a.span_start())) + + fn mark(mut alloca: Arc>>, el: MarkQueueElement) { + let mut local_queue = vec![]; + match el { + MarkQueueElement::arena(ptr_on_arena) => { + let mut alloca_guard = alloca.lock().unwrap(); + let arena = alloca_guard.mut_arena_by_ptr(ptr_on_arena).unwrap(); + arena.make_live(); + let (black, size) = arena.black_map(); + let (gray, size) = arena.gray_map(); + let mut diff_bits = vec![]; + // byte-iter + for i in (0..size).step_by(8) { + unsafe { + diff_bits.push(*((gray + i) as *const u64) ^ *((black + i) as *const u64)); + } + } + // bit-iter + for i in 0..(size * 8) { + if (diff_bits[i / 64] & (1 << (i % 64))) != 0 { + unsafe { + *((black + (i / 64)) as *mut u64) |= (1 << (i % 64)); + } + let ptr_to_obj = arena.span_start() + i * 8; + let ptr_to_header = (ptr_to_obj - 8) as *const Object; + let size_of_object = unsafe { ptr_to_header.as_ref_unchecked().size }; + for j in 0..size_of_object / 8 { + if (unsafe { ptr_to_header.as_ref_unchecked().bitset }[j / 8] + & (1 << (j % 8))) + != 0 + { + let field_ptr = ptr_to_obj + j * 8; + Self::mark_gray_el_from_ptr( + alloca.clone(), + field_ptr, + &mut local_queue, + ); + } + } + } + } + } + MarkQueueElement::object(ptr) => { + todo!(); + // делать мне нехуй чтоли + // TODO + } + MarkQueueElement::End => { + panic!("something went wrong in mark"); + } } - } } - } -} \ No newline at end of file + + fn mark_gray_el_from_ptr( + mut alloca: Arc>>, + ptr: ptr, + source: &mut Vec, + ) { + match alloca.lock().unwrap().mark_gray(ptr) { + None => source.push(MarkQueueElement::object(ptr)), + Some(a) => { + if !a.fetch_and_add_in_queue() { + source.push(MarkQueueElement::arena(a.span_start())) + } + } + } + } +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 82328ab..cf1e69e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -2,92 +2,90 @@ #![feature(ptr_as_ref_unchecked)] mod alloca; +mod gc; mod nni; mod threads; mod utils; -mod gc; -use std::sync::Arc; -use utils::*; -use crate::alloca::Cfg; use crate::alloca::ArenaAllocator3; +use crate::alloca::Cfg; +use std::sync::{Arc, Mutex, OnceLock}; +use utils::*; -static mut THREADS: Option> = None; - -static mut GC: Option> = None; +static THREADS: OnceLock>> = OnceLock::new(); +static GC: OnceLock>> = OnceLock::new(); pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { - unsafe { - let athreads = Arc::new(threads::Threads::new(stw)); - THREADS = Some(athreads.clone()); - - GC = Some(gc::Gc::new(athreads, Cfg::new( - 37, - 26, - 12, - 20, - 0, - 0, - |size| { - size / 64 - }))); - - THREADS.as_mut() + let athreads = Arc::new(Mutex::new(threads::Threads::new(stw))); + THREADS.get_or_init(|| athreads.clone()); + GC.get_or_init(|| { + Mutex::new(gc::Gc::new( + athreads, + &Cfg::new(37, 26, 12, 20, 0, 0, |size| size / 64, 3), + )) + }); + THREADS + .get() .unwrap() - .append(main, 0, 0, 0, 0, 0); - - GC.as_mut() + .lock() .unwrap() - .master() - } + .append(main, 0, 0, 0, 0, 0); + + GC.get().unwrap().lock().unwrap().master() } pub extern "C" fn alloc(t: &Object) -> alloca::ptr { - unsafe { - let gc = GC.as_mut().expect("gc is none (alloc)"); - let (ptr, heap_is_overflow) = gc.alloca.alloc(t); + let gc = GC.get().expect("gc is none (alloc)"); + let (ptr, heap_is_overflow) = gc.lock().unwrap().alloca.lock().unwrap().alloc(t); if heap_is_overflow { - gc.notify_master(); + gc.lock().unwrap().notify_master(); } ptr - } } - -pub extern "C" fn go(func: fn(reg, reg, reg, reg, reg), - r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { - func(r1, r2, r3, r4, r5); +pub extern "C" fn go( + func: fn(reg, reg, reg, reg, reg), + r1: reg, + r2: reg, + r3: reg, + r4: reg, + r5: reg, +) { + func(r1, r2, r3, r4, r5); } pub extern "C" fn go_gc(rbp: reg) { - unsafe { - GC.as_mut() - .expect("gc is None") - .go_gc(rbp); - } + unsafe { + GC.get().expect("gc is None").lock().unwrap().go_gc(rbp); + } } pub extern "C" fn go_native(rbp: reg) { - unsafe { - THREADS.as_mut() - .expect("thrds is None") - .go_immut(rbp); - } + unsafe { + THREADS + .get() + .expect("thrds is None") + .lock() + .unwrap() + .go_immut(rbp); + } } pub extern "C" fn go_back() { - unsafe { - THREADS.as_mut() - .expect("thrds is None") - .go_mut(); - } + unsafe { + THREADS + .get() + .expect("thrds is None") + .lock() + .unwrap() + .go_mut(); + } } #[cfg(test)] mod tests { use super::*; - #[test] fn it_works() { diff --git a/runtime/src/nni/mod.rs b/runtime/src/nni/mod.rs index 136d063..8b13789 100644 --- a/runtime/src/nni/mod.rs +++ b/runtime/src/nni/mod.rs @@ -1 +1 @@ - \ No newline at end of file + diff --git a/runtime/src/threads/mod.rs b/runtime/src/threads/mod.rs index 9fd2781..85e1a79 100644 --- a/runtime/src/threads/mod.rs +++ b/runtime/src/threads/mod.rs @@ -1,36 +1,44 @@ -use std::sync::atomic::{AtomicBool, Ordering}; -use std::thread::ThreadId; use crate::threads::nthread::NThread; use crate::threads::threadpool::ThreadPool; use crate::utils::*; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread::ThreadId; mod nthread; mod threadpool; pub use nthread::ThreadPhase; pub struct Threads { - pub pool: ThreadPool, - stw: &'static bool + pub pool: ThreadPool, + stw: &'static bool, } impl Threads { - pub fn new(stw: &'static bool) -> Self { - Self { - pool: ThreadPool::new(), - stw + pub fn new(stw: &'static bool) -> Self { + Self { + pool: ThreadPool::new(), + stw, + } + } + + pub fn append( + &mut self, + func: fn(reg, reg, reg, reg, reg), + r1: reg, + r2: reg, + r3: reg, + r4: reg, + r5: reg, + ) { + self.pool.append(func, r1, r2, r3, r4, r5); } - } - - pub fn append(&mut self, func: fn(reg, reg, reg, reg, reg), r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { - self.pool.append(func, r1, r2, r3, r4, r5); - } - - pub fn go_immut(&mut self, rbp: reg) { - self.pool.go_immut(rbp); - } - - pub fn go_mut(&mut self) { - while *self.stw {} - - self.pool.go_mut(); - } -} \ No newline at end of file + + pub fn go_immut(&self, rbp: reg) { + self.pool.go_immut(rbp); + } + + pub fn go_mut(&mut self) { + while *self.stw {} + + self.pool.go_mut(); + } +} diff --git a/runtime/src/threads/nthread.rs b/runtime/src/threads/nthread.rs index a484ec8..b48c446 100644 --- a/runtime/src/threads/nthread.rs +++ b/runtime/src/threads/nthread.rs @@ -1,32 +1,32 @@ -use std::sync::{Arc, RwLock}; use crate::utils::reg; +use std::sync::{Arc, RwLock}; pub struct NThread { - pub routine: std::thread::JoinHandle<()>, - pub state: Arc>, // i guess arc or rw or rw and arc id redundant - pub phase: ThreadPhase + pub routine: std::thread::JoinHandle<()>, + pub state: Arc>, // i guess arc or rw or rw and arc id redundant + pub phase: ThreadPhase, } #[derive(Debug, Clone, Copy)] pub enum ThreadPhase { - Mutable, - Immutable(ThreadCntxt) + Mutable, + Immutable(ThreadCntxt), } impl ThreadPhase { - pub fn new(rbp: reg) -> Self { - ThreadPhase::Immutable(ThreadCntxt {rbp}) - } + pub fn new(rbp: reg) -> Self { + ThreadPhase::Immutable(ThreadCntxt { rbp }) + } } #[derive(Debug, Clone, Copy)] -struct ThreadCntxt { - pub rbp: reg, +pub struct ThreadCntxt { + pub rbp: reg, } pub(crate) enum ThreadState { - Runnable, - Waiting, - Blocked, - Terminated -} \ No newline at end of file + Runnable, + Waiting, + Blocked, + Terminated, +} diff --git a/runtime/src/threads/threadpool.rs b/runtime/src/threads/threadpool.rs index 5f3fc3e..5bbf22d 100644 --- a/runtime/src/threads/threadpool.rs +++ b/runtime/src/threads/threadpool.rs @@ -1,68 +1,77 @@ -use std::sync::Arc; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use std::thread::ThreadId; use crate::threads::nthread::{NThread, ThreadPhase, ThreadState}; use crate::utils::reg; use dashmap::DashMap; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use std::thread::ThreadId; pub struct ThreadPool { - pub thread_map: Arc>, - pub count_of_mutable: AtomicUsize, + pub thread_map: Arc>, + pub count_of_mutable: AtomicUsize, } impl ThreadPool { - pub fn new() -> ThreadPool { - Self { - thread_map: Arc::new(DashMap::new()), - count_of_mutable: AtomicUsize::new(0) + pub fn new() -> ThreadPool { + Self { + thread_map: Arc::new(DashMap::new()), + count_of_mutable: AtomicUsize::new(0), + } } - } - - pub fn append(&mut self, func: fn(reg, reg, reg, reg, reg), r1: reg, r2: reg, r3: reg, r4: reg, r5: reg) { - let i = std::thread::current().id(); - let id = Arc::new(std::sync::Mutex::new(i)); - let id2 = Arc::clone(&id); - - let main_in_process = Arc::new(AtomicBool::new(true)); - let main_in_process2 = Arc::clone(&main_in_process); - - let routine = std::thread::spawn(move || { - *id2.lock().unwrap() = std::thread::current().id(); - - while main_in_process2.load(Ordering::SeqCst) {} - func(r1, r2, r3, r4, r5); - }); - - while i == *id.lock().unwrap() {} - self.count_of_mutable.fetch_add(1, Ordering::Relaxed); - self.thread_map.insert(*id.lock().unwrap(), NThread { - routine, - state: Arc::new(std::sync::RwLock::new(ThreadState::Runnable)), - phase: ThreadPhase::Mutable, - }); - - main_in_process.store(false, Ordering::SeqCst); - } - - pub fn go_immut(&mut self, rbp: reg) { - assert_ne!(self.count_of_mutable.load(Ordering::Relaxed), 0); - - self.thread_map - .get_mut(&std::thread::current().id()) - .expect("fantom thread") - .phase = ThreadPhase::new(rbp); - - self.count_of_mutable.fetch_sub(1, Ordering::Relaxed); - } - - pub fn go_mut(&mut self) { - - self.thread_map - .get_mut(&std::thread::current().id()) - .expect("fantom thread") - .phase = ThreadPhase::Mutable; - - self.count_of_mutable.fetch_add(1, Ordering::Relaxed); - } -} + pub fn append( + &mut self, + func: fn(reg, reg, reg, reg, reg), + r1: reg, + r2: reg, + r3: reg, + r4: reg, + r5: reg, + ) { + let i = std::thread::current().id(); + let id = Arc::new(std::sync::Mutex::new(i)); + let id2 = Arc::clone(&id); + + let main_in_process = Arc::new(AtomicBool::new(true)); + let main_in_process2 = Arc::clone(&main_in_process); + + let routine = std::thread::spawn(move || { + *id2.lock().unwrap() = std::thread::current().id(); + + while main_in_process2.load(Ordering::SeqCst) {} + func(r1, r2, r3, r4, r5); + }); + + while i == *id.lock().unwrap() {} + self.count_of_mutable.fetch_add(1, Ordering::Relaxed); + self.thread_map.insert( + *id.lock().unwrap(), + NThread { + routine, + state: Arc::new(std::sync::RwLock::new(ThreadState::Runnable)), + phase: ThreadPhase::Mutable, + }, + ); + + main_in_process.store(false, Ordering::SeqCst); + } + + pub fn go_immut(&self, rbp: reg) { + assert_ne!(self.count_of_mutable.load(Ordering::Relaxed), 0); + + self.thread_map + .get_mut(&std::thread::current().id()) + .expect("fantom thread") + .phase = ThreadPhase::new(rbp); + + self.count_of_mutable.fetch_sub(1, Ordering::Relaxed); + } + + pub fn go_mut(&self) { + self.thread_map + .get_mut(&std::thread::current().id()) + .expect("fantom thread") + .phase = ThreadPhase::Mutable; + + self.count_of_mutable.fetch_add(1, Ordering::Relaxed); + } +} diff --git a/runtime/src/utils/mod.rs b/runtime/src/utils/mod.rs index cfeac1a..1f8486b 100644 --- a/runtime/src/utils/mod.rs +++ b/runtime/src/utils/mod.rs @@ -2,4 +2,4 @@ pub mod object; pub type reg = usize; -pub use object::*; \ No newline at end of file +pub use object::*; diff --git a/runtime/src/utils/object.rs b/runtime/src/utils/object.rs index b1ae6fe..22a3053 100644 --- a/runtime/src/utils/object.rs +++ b/runtime/src/utils/object.rs @@ -1,5 +1,4 @@ - pub struct Object { - pub size: usize, - pub bitset: &'static [u8], -} \ No newline at end of file + pub size: usize, + pub bitset: &'static [u8], +} From ca5ed1560f4734844aeaa64895bf4dcafd024f28 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 26 Aug 2025 02:53:42 +0700 Subject: [PATCH 18/21] fix tests --- runtime/src/alloca/hallocator.rs | 2 +- runtime/src/alloca/mod.rs | 4 ++-- runtime/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index 57f242b..7a85c8d 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -38,7 +38,7 @@ impl HAllocator { if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { None } else { - Some(&mut self.blocks[ptr >> self.log_block_size]) + Some(&mut self.blocks[(ptr - self.start) >> self.log_block_size]) } } diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 0a9f34e..634e038 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -27,8 +27,8 @@ mod tests { 26, 12, 20, - 0, - 0, + 2, + 1 << 20, |size| size / 64, 3, ))) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index cf1e69e..4508170 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -22,7 +22,7 @@ pub extern "C" fn init(main: fn(reg, reg, reg, reg, reg), stw: &'static bool) { GC.get_or_init(|| { Mutex::new(gc::Gc::new( athreads, - &Cfg::new(37, 26, 12, 20, 0, 0, |size| size / 64, 3), + &Cfg::new(37, 26, 12, 20, 2, 1 << 20, |size| size / 64, 3), )) }); THREADS From 6db5291e439d1fc2da8946004f24ce2ed10b1437 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Tue, 26 Aug 2025 05:30:21 +0700 Subject: [PATCH 19/21] fix bugs, complete test and stress-test (alloca3) --- runtime/src/alloca/hallocator.rs | 43 +++++++++++++++++++++----------- runtime/src/alloca/mod.rs | 41 ++++++++++++++++++------------ 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index 7a85c8d..1a7f1d3 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -46,7 +46,7 @@ impl HAllocator { for tier in 0..self.count_of_tiers { if (self.max_object_size_by_tier)(tier) >= size { let index = self.blocks.len(); - let mut new_block = HedgeBlock::new( + let new_block = HedgeBlock::new( self.start + (index << self.log_block_size), 1 << self.log_block_size, self.log_start_arena_size + tier * self.step_arena_size, @@ -81,18 +81,28 @@ impl HAllocator { } unreachable!(); } - + fn find(&mut self, size: usize) -> Option<&mut U> { let tier = self.arena_tier_by_size(size); - for num_of_block in self.num_of_blocks_by_tier[tier].iter() { - let mut block = &mut self.blocks[*num_of_block]; - if block.current.is_some() { - Some(&mut block.items[block.current.unwrap().num_of_arena]); + let mut found = None; + + for &num_of_block in &self.num_of_blocks_by_tier[tier] { + let block = &self.blocks[num_of_block]; + if let Some(current) = block.current { + found = Some((num_of_block, current.num_of_arena)); + break; } } + + if let Some((block_idx, arena_idx)) = found { + let block = &mut self.blocks[block_idx]; + return Some(&mut block.items[arena_idx]); + } + None } - + + fn for_each_arena(&mut self, mut f: F) where F: FnMut(&mut U), @@ -169,14 +179,16 @@ impl ArenaAllocator3 for HAllocator { let ptr = ref_arena.cur(); ref_arena.add(real_size); - let cur = ref_arena.cur(); let empty_space = ref_arena.how_much(); - let block_of_arena = self.mut_block_by_ptr(cur).expect("something went wrong"); + let block_of_arena = self.mut_block_by_ptr(ptr).expect("something went wrong"); - if empty_space < block_of_arena.tier { + if empty_space < block_of_arena.max_object_size { block_of_arena.active.push(block_of_arena.current.unwrap()); block_of_arena.current = block_of_arena.archive.pop(); + if block_of_arena.current.is_some() { + block_of_arena.items[block_of_arena.current.unwrap().num_of_arena].alive(); + } } unsafe { @@ -185,9 +197,9 @@ impl ArenaAllocator3 for HAllocator { let used = self.used_memory.load(Ordering::Relaxed); if used > self.max_size { - (ptr, true) + (ptr + 8, true) } else { - (ptr, false) + (ptr + 8, false) } } @@ -296,10 +308,13 @@ impl HedgeBlock { let mut arenas = Vec::with_capacity(count); let mut archive = Vec::with_capacity(count); for i in 0..count { - arenas.push(U::new(start + (i << log_arena_size), 1 << log_arena_size)); + arenas.push(U::new( + start + ((count - i - 1) << log_arena_size), + 1 << log_arena_size, + )); archive.push(IndexArena { num_of_block: number_of_block, - num_of_arena: i, + num_of_arena: count - i - 1, // literally for good debug }) } diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 634e038..312f5f8 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -33,6 +33,15 @@ mod tests { 3, ))) } + + fn test_alloc(object: &Object, aa: &mut HAllocator) { + unsafe { + let (ptr, pred) = aa.alloc(object); + assert_eq!(pred, false); + assert_ne!(ptr, 0); + std::ptr::write_bytes(ptr as *mut u8, 126, object.size / 8); + } + } #[test] fn create_allocator() { @@ -41,40 +50,40 @@ mod tests { #[test] fn first_alloc() { - let mut aa: HAllocator = HAllocator::new(config1()); + let mut aa= HAllocator::new(config1()); let inst_1 = Object { size: 24, bitset: &[0], }; - unsafe { - let (ptr, pred) = aa.alloc(&inst_1); - assert_eq!(pred, false); - assert_ne!(ptr, 0); - std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); - } + test_alloc(&inst_1, &mut aa); } #[test] fn alloc2() { - let mut aa: HAllocator = HAllocator::new(config1()); + let mut aa = HAllocator::new(config1()); let inst_1 = Object { size: 1024, bitset: &[0], }; + test_alloc(&inst_1, &mut aa); let inst_2 = Object { size: 512, bitset: &[0], }; - unsafe { - let (ptr, _) = aa.alloc(&inst_1); - assert_ne!(ptr, 0); - std::ptr::write_bytes(ptr as *mut u8, 126, inst_1.size / 8); - - let (ptr, _) = aa.alloc(&inst_2); - assert_ne!(ptr, 0); - std::ptr::write_bytes(ptr as *mut u8, 126, inst_2.size / 8); + test_alloc(&inst_2, &mut aa); + } + + #[test] + fn alloc3() { + let mut aa = HAllocator::new(config1()); + let inst = Object { + size: 48, + bitset: &[0], + }; + for i in 0..100_000_000 { + test_alloc(&inst, &mut aa); } } } From 32acf956a77eff61226909ad2ffbe9cc40310cc9 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Thu, 28 Aug 2025 02:04:05 +0700 Subject: [PATCH 20/21] fix mutexs, bug in alloca and etc --- runtime/src/alloca/hallocator.rs | 82 ++++++++++++------------ runtime/src/alloca/mod.rs | 31 +++++++-- runtime/src/gc/markqueue.rs | 29 +++++---- runtime/src/gc/mod.rs | 102 +++++++++++++++--------------- runtime/src/lib.rs | 32 ++++------ runtime/src/threads/mod.rs | 4 +- runtime/src/threads/threadpool.rs | 4 +- 7 files changed, 149 insertions(+), 135 deletions(-) diff --git a/runtime/src/alloca/hallocator.rs b/runtime/src/alloca/hallocator.rs index 1a7f1d3..caab101 100644 --- a/runtime/src/alloca/hallocator.rs +++ b/runtime/src/alloca/hallocator.rs @@ -3,6 +3,7 @@ use crate::alloca::arena::Arena3; use crate::alloca::cfg::Cfg; use crate::alloca::ptr; use crate::utils::Object; +use libc::malloc; use std::collections::LinkedList; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -30,7 +31,7 @@ impl HAllocator { if ptr < self.start || ptr >= self.start + (1 << self.log_capacity_size) { None } else { - Some(&self.blocks[ptr >> self.log_block_size]) + Some(&self.blocks[(ptr - self.start) >> self.log_block_size]) } } @@ -73,19 +74,22 @@ impl HAllocator { unreachable!(); } - fn arena_tier_by_size(&self, size: usize) -> usize { - for tier in 1..self.count_of_tiers { - if (self.max_object_size_by_tier)(tier) > size { - return tier - 1; + fn arena_tier_by_size(&self, size: usize) -> Option { + for tier in 0..self.count_of_tiers { + if (self.max_object_size_by_tier)(tier) >= size { + return Some(tier); } } - unreachable!(); + None } - - fn find(&mut self, size: usize) -> Option<&mut U> { - let tier = self.arena_tier_by_size(size); + + fn find(&mut self, size: usize) -> (Option<&mut U>, bool) { + let tier = match self.arena_tier_by_size(size) { + Some(tier) => tier, + None => return (None, true), + }; let mut found = None; - + for &num_of_block in &self.num_of_blocks_by_tier[tier] { let block = &self.blocks[num_of_block]; if let Some(current) = block.current { @@ -93,16 +97,15 @@ impl HAllocator { break; } } - + if let Some((block_idx, arena_idx)) = found { let block = &mut self.blocks[block_idx]; - return Some(&mut block.items[arena_idx]); + return (Some(&mut block.items[arena_idx]), true); } - - None + + (None, true) } - - + fn for_each_arena(&mut self, mut f: F) where F: FnMut(&mut U), @@ -160,34 +163,29 @@ impl ArenaAllocator3 for HAllocator { fn alloc(&mut self, o: &Object) -> (ptr, bool) { let real_size = o.size + 8; - // let mut maybe_ref_arena = self.find(real_size); - // - // // let ref_arena = maybe_ref_arena.unwrap_or(self.add_new_needed_block(real_size)); - // let ref_arena = match maybe_ref_arena { - // Some(a) => a, - // None => self.add_new_needed_block(real_size), - // }; - - let ref_arena = { - let maybe_ref_arena = self.find(real_size); - match maybe_ref_arena { + let mut ptr = 0; // result + + let (maybe_ref_arena, big_object_flag) = self.find(real_size); + if big_object_flag { + ptr = unsafe { malloc(real_size) } as usize; + } else { + let ref_arena = match maybe_ref_arena { Some(a) => a, None => self.add_new_needed_block(real_size), - } - }; - - let ptr = ref_arena.cur(); + }; + ptr = ref_arena.cur(); - ref_arena.add(real_size); - let empty_space = ref_arena.how_much(); + ref_arena.add(real_size); + let empty_space = ref_arena.how_much(); - let block_of_arena = self.mut_block_by_ptr(ptr).expect("something went wrong"); + let block_of_arena = self.mut_block_by_ptr(ptr).expect("something went wrong"); - if empty_space < block_of_arena.max_object_size { - block_of_arena.active.push(block_of_arena.current.unwrap()); - block_of_arena.current = block_of_arena.archive.pop(); - if block_of_arena.current.is_some() { - block_of_arena.items[block_of_arena.current.unwrap().num_of_arena].alive(); + if empty_space < block_of_arena.max_object_size { + block_of_arena.active.push(block_of_arena.current.unwrap()); + block_of_arena.current = block_of_arena.archive.pop(); + if block_of_arena.current.is_some() { + block_of_arena.items[block_of_arena.current.unwrap().num_of_arena].alive(); + } } } @@ -195,7 +193,9 @@ impl ArenaAllocator3 for HAllocator { *(ptr as *mut *const Object) = o as *const Object; } - let used = self.used_memory.load(Ordering::Relaxed); + // this is shit, but pohuy + let used = self.used_memory.fetch_add(real_size, Ordering::Relaxed); + if used > self.max_size { (ptr + 8, true) } else { @@ -284,7 +284,7 @@ struct HedgeBlock { log_arena_size: usize, max_object_size: usize, - // only for find object by ref. + // only for find Object by ref. // const items: Box<[U]>, diff --git a/runtime/src/alloca/mod.rs b/runtime/src/alloca/mod.rs index 312f5f8..e5ba866 100644 --- a/runtime/src/alloca/mod.rs +++ b/runtime/src/alloca/mod.rs @@ -28,12 +28,12 @@ mod tests { 12, 20, 2, - 1 << 20, + 8/*GB*/<< 30, |size| size / 64, 3, ))) } - + fn test_alloc(object: &Object, aa: &mut HAllocator) { unsafe { let (ptr, pred) = aa.alloc(object); @@ -50,7 +50,7 @@ mod tests { #[test] fn first_alloc() { - let mut aa= HAllocator::new(config1()); + let mut aa = HAllocator::new(config1()); let inst_1 = Object { size: 24, @@ -74,16 +74,35 @@ mod tests { }; test_alloc(&inst_2, &mut aa); } - + #[test] fn alloc3() { let mut aa = HAllocator::new(config1()); let inst = Object { - size: 48, + size: 32, bitset: &[0], }; - for i in 0..100_000_000 { + for i in 0..1_000_000 { test_alloc(&inst, &mut aa); } } + + #[test] + fn alloc4() { + let cfg = config1(); + let mut aa = HAllocator::new(cfg); + + for i in 0..cfg.count_of_tiers { + for j in 0..(0x100000 >> (i * cfg.step_arena_size)) { + let max_size_for_this_tier = (cfg.max_object_size_by_size)( + 1 << (cfg.log_start_arena_size + i * cfg.step_arena_size), + ); + let inst = Object { + size: max_size_for_this_tier - 8 - (j % 4) * max_size_for_this_tier / 8, + bitset: &[0], + }; + test_alloc(&inst, &mut aa); + } + } + } } diff --git a/runtime/src/gc/markqueue.rs b/runtime/src/gc/markqueue.rs index a891b50..b898e69 100644 --- a/runtime/src/gc/markqueue.rs +++ b/runtime/src/gc/markqueue.rs @@ -1,41 +1,44 @@ pub use crate::alloca::*; use std::cmp::min; +use std::collections::VecDeque; +#[derive(Copy, Clone)] pub enum MarkQueueElement { - arena(ptr), // start of arena lol - object(ptr), + Arena(ptr), // start of Arena lol + Object(ptr), End, } pub struct MarkQueue { - queue: std::sync::RwLock>, + queue: std::sync::RwLock>, } impl MarkQueue { pub fn new() -> MarkQueue { Self { - queue: std::sync::RwLock::new(vec![]), + queue: std::sync::RwLock::new(VecDeque::new()), } } - pub fn pushn(&self, elements: &mut Vec) { + pub fn pushn(&self, elements: &mut VecDeque) { self.queue.write().expect("pushn1").append(elements); } - pub fn popn(&self, n: usize) -> Vec { + pub fn popn(&self, n: usize) -> VecDeque { let mut lock = self.queue.write().expect("popn"); let bound = min(lock.len(), n); - let mut result = vec![]; + let mut result = VecDeque::new(); for _ in 0..bound { - result.push(lock.pop().expect("popn copy")); + result.push_back(lock.pop_front().expect("popn copy")); } result } - pub fn last_is_end(&self) -> bool { - match self.queue.read().expect("last_is_end").last() { - Some(MarkQueueElement::End) => true, - _ => false, - } + pub fn last(&self) -> Option { + self.queue.read() + .expect("last_is_end") + .iter() + .last() + .copied() } } diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index 7b8d85d..ef8c77b 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -1,12 +1,10 @@ mod markqueue; -use crate::alloca::IndexArena; use crate::{alloca, gc, threads, utils}; use alloca::{Arena3, ArenaAllocator3, Cfg, ptr}; use gc::markqueue::{MarkQueue, MarkQueueElement}; -use libc::abort; -use std::cell::{RefCell, RefMut}; use std::cmp::min; +use std::collections::VecDeque; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; @@ -48,8 +46,6 @@ pub struct Gc { root_is_done: Arc>, root_cv: Arc, - work_is_done: Arc>, - work_cv: Arc, workers: Vec>, count_active_workers: Arc, @@ -74,9 +70,6 @@ impl Gc { root_is_done: Arc::new(Mutex::new(false)), root_cv: Arc::new(Default::default()), - work_is_done: Arc::new(Mutex::new(false)), - work_cv: Arc::new(Default::default()), - workers: Vec::new(), count_active_workers: Arc::new(AtomicUsize::new(config.count_gc_workers)), @@ -91,24 +84,23 @@ impl Gc { let mut workers = Vec::with_capacity(count); for i in 0..count { let thread_root_is_done = self.root_is_done.clone(); - let thread_stw_cv = self.stw_cv.clone(); + let thread_root_cv = self.root_cv.clone(); let mut thread_root = self.root.clone(); let thread_alloca = self.alloca.clone(); let thread_mark_queue = self.mark_queue.clone().clone(); let thread_count_active_workers = self.count_active_workers.clone(); - let thread_stw_is_done = self.stw_is_done.clone(); - let thread_work_is_done = self.work_is_done.clone(); - let thread_work_cv = self.work_cv.clone(); + let thread_mark_is_done = self.mark_is_done.clone(); + let thread_mark_cv = self.mark_cv.clone(); workers.push(thread::spawn(move || { loop { { let mut root_is_done_flag = thread_root_is_done.lock().unwrap(); while !*root_is_done_flag { - root_is_done_flag = thread_stw_cv.wait(root_is_done_flag).unwrap() + root_is_done_flag = thread_root_cv.wait(root_is_done_flag).unwrap() } } - let mut local_queue = vec![]; + let mut local_queue = VecDeque::new(); let count_for_scan = thread_root.len() / count + 1; for j in min(i * count_for_scan, thread_root.len())..thread_root.len() { @@ -118,64 +110,70 @@ impl Gc { &mut local_queue, ); - if !(local_queue.len() & 15 == 0) { - // TODO: make somethink like cfg + if local_queue.len() > /* TODO: add to cfg*/ 15 { (*thread_mark_queue).pushn(&mut local_queue); } } 'external: loop { while local_queue.len() > 0 { - Self::mark(thread_alloca.clone(), local_queue.pop().unwrap()); + Self::mark(thread_alloca.clone(), local_queue.pop_front().unwrap()); } local_queue = (*thread_mark_queue).popn(16); if local_queue.len() == 0 { if thread_count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { - (*thread_mark_queue).pushn(&mut vec![MarkQueueElement::End]); - + (*thread_mark_queue) + .pushn(&mut VecDeque::from([MarkQueueElement::End])); { - let mut root_is_done_flag = thread_stw_is_done.lock().unwrap(); + let mut root_is_done_flag = thread_root_is_done.lock().unwrap(); thread_root = Arc::new(Vec::new()); *root_is_done_flag = false; - let mut work_is_done_flag = thread_work_is_done.lock().unwrap(); - assert!(!*work_is_done_flag); - *work_is_done_flag = true; + let mut mark_is_done_flag = thread_mark_is_done.lock().unwrap(); + assert!(!*mark_is_done_flag); + *mark_is_done_flag = true; - thread_work_cv.notify_all(); + thread_mark_cv.notify_all(); } - break 'external; // for better reading + break 'external; } else { loop { - if (*thread_mark_queue).last_is_end() { - thread_count_active_workers.fetch_add(1, Ordering::SeqCst); - { - let mut work_is_done_flag = - thread_work_is_done.lock().unwrap(); - while !*work_is_done_flag { - work_is_done_flag = - thread_work_cv.wait(work_is_done_flag).unwrap() + match (*thread_mark_queue).last() { + Some(MarkQueueElement::End) => { + thread_count_active_workers + .fetch_add(1, Ordering::SeqCst); + { + let mut mark_is_done_flag = + thread_mark_is_done.lock().unwrap(); + while !*mark_is_done_flag { + mark_is_done_flag = thread_mark_cv + .wait(mark_is_done_flag) + .unwrap() + } } + break 'external; + } + None => {} + _ => { + local_queue = (*thread_mark_queue).popn(16); + break; } - break 'external; - } else { - local_queue = (*thread_mark_queue).popn(16); - break; } } } } } - // TODO WORK } })) } } pub fn go_gc(&mut self, rbp: reg) { - self.threads.lock().unwrap().go_immut(rbp); + if self.threads.lock().unwrap().go_immut(rbp) == 0 { + self.notify_master(); + } let mut stw_is_done_flag = self.stw_is_done.lock().unwrap(); while !*stw_is_done_flag { @@ -193,6 +191,7 @@ impl Gc { heap_is_done_flag = self.heap_cv.wait(heap_is_done_flag).unwrap() } } + *self.heap_is_done.lock().unwrap() = false; let threads = self.threads.clone(); let guard_threads = threads.lock().unwrap(); @@ -208,15 +207,14 @@ impl Gc { } } - *self.stw_is_done.lock().unwrap() = true; - self.stw_cv.notify_all(); - - *self.heap_is_done.lock().unwrap() = false; + *self.root_is_done.lock().unwrap() = true; + self.root_cv.notify_all(); - let mut work_is_done_flag = self.work_is_done.lock().unwrap(); - while !*work_is_done_flag { - work_is_done_flag = self.work_cv.wait(work_is_done_flag).unwrap() + let mut mark_is_done_flag = self.mark_is_done.lock().unwrap(); + while !*mark_is_done_flag { + mark_is_done_flag = self.mark_cv.wait(mark_is_done_flag).unwrap() } + // TODO SWEEP } } @@ -230,9 +228,9 @@ impl Gc { } fn mark(mut alloca: Arc>>, el: MarkQueueElement) { - let mut local_queue = vec![]; + let mut local_queue = VecDeque::new(); match el { - MarkQueueElement::arena(ptr_on_arena) => { + MarkQueueElement::Arena(ptr_on_arena) => { let mut alloca_guard = alloca.lock().unwrap(); let arena = alloca_guard.mut_arena_by_ptr(ptr_on_arena).unwrap(); arena.make_live(); @@ -270,7 +268,7 @@ impl Gc { } } } - MarkQueueElement::object(ptr) => { + MarkQueueElement::Object(ptr) => { todo!(); // делать мне нехуй чтоли // TODO @@ -284,13 +282,13 @@ impl Gc { fn mark_gray_el_from_ptr( mut alloca: Arc>>, ptr: ptr, - source: &mut Vec, + source: &mut VecDeque, ) { match alloca.lock().unwrap().mark_gray(ptr) { - None => source.push(MarkQueueElement::object(ptr)), + None => source.push_back(MarkQueueElement::Object(ptr)), Some(a) => { if !a.fetch_and_add_in_queue() { - source.push(MarkQueueElement::arena(a.span_start())) + source.push_back(MarkQueueElement::Arena(a.span_start())) } } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 4508170..541a2f7 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -56,31 +56,25 @@ pub extern "C" fn go( } pub extern "C" fn go_gc(rbp: reg) { - unsafe { - GC.get().expect("gc is None").lock().unwrap().go_gc(rbp); - } + GC.get().expect("gc is None").lock().unwrap().go_gc(rbp); } pub extern "C" fn go_native(rbp: reg) { - unsafe { - THREADS - .get() - .expect("thrds is None") - .lock() - .unwrap() - .go_immut(rbp); - } + THREADS + .get() + .expect("thrds is None") + .lock() + .unwrap() + .go_immut(rbp); } pub extern "C" fn go_back() { - unsafe { - THREADS - .get() - .expect("thrds is None") - .lock() - .unwrap() - .go_mut(); - } + THREADS + .get() + .expect("thrds is None") + .lock() + .unwrap() + .go_mut(); } #[cfg(test)] diff --git a/runtime/src/threads/mod.rs b/runtime/src/threads/mod.rs index 85e1a79..1fbd0ef 100644 --- a/runtime/src/threads/mod.rs +++ b/runtime/src/threads/mod.rs @@ -32,8 +32,8 @@ impl Threads { self.pool.append(func, r1, r2, r3, r4, r5); } - pub fn go_immut(&self, rbp: reg) { - self.pool.go_immut(rbp); + pub fn go_immut(&self, rbp: reg) -> usize { + self.pool.go_immut(rbp) } pub fn go_mut(&mut self) { diff --git a/runtime/src/threads/threadpool.rs b/runtime/src/threads/threadpool.rs index 5bbf22d..d2d9f2e 100644 --- a/runtime/src/threads/threadpool.rs +++ b/runtime/src/threads/threadpool.rs @@ -55,7 +55,7 @@ impl ThreadPool { main_in_process.store(false, Ordering::SeqCst); } - pub fn go_immut(&self, rbp: reg) { + pub fn go_immut(&self, rbp: reg) -> usize { assert_ne!(self.count_of_mutable.load(Ordering::Relaxed), 0); self.thread_map @@ -63,7 +63,7 @@ impl ThreadPool { .expect("fantom thread") .phase = ThreadPhase::new(rbp); - self.count_of_mutable.fetch_sub(1, Ordering::Relaxed); + self.count_of_mutable.fetch_sub(1, Ordering::Relaxed) - 1 } pub fn go_mut(&self) { From 6df85966f0d13429eb78b0a015b46b5553e49475 Mon Sep 17 00:00:00 2001 From: Km1zZzoU Date: Thu, 28 Aug 2025 06:34:08 +0700 Subject: [PATCH 21/21] review --- runtime/src/gc/mod.rs | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/runtime/src/gc/mod.rs b/runtime/src/gc/mod.rs index ef8c77b..63a53e5 100644 --- a/runtime/src/gc/mod.rs +++ b/runtime/src/gc/mod.rs @@ -13,22 +13,6 @@ use threads::ThreadPhase; use utils::object::Object; use utils::reg; -// struct Arc(Arc>); -// -// impl Arc { -// pub fn new(value: T) -> Arc { -// Arc(Arc::new(RefCell::new(value))) -// } -// -// pub fn borrow_mut(&self) -> RefMut<'_, T> { -// self.0.borrow_mut -// } -// -// pub fn clone(&self) -> Arc { -// Arc(self.0.clone()) -// } -// } - pub struct Gc { pub alloca: Arc>>, @@ -103,7 +87,9 @@ impl Gc { let mut local_queue = VecDeque::new(); let count_for_scan = thread_root.len() / count + 1; - for j in min(i * count_for_scan, thread_root.len())..thread_root.len() { + let start_j = i * count_for_scan; + let end_j = min(start_j + count_for_scan, thread_root.len()); + for j in start_j..end_j { Self::mark_gray_el_from_ptr( thread_alloca.clone(), thread_root[j], @@ -116,12 +102,12 @@ impl Gc { } 'external: loop { - while local_queue.len() > 0 { + while !local_queue.is_empty() { Self::mark(thread_alloca.clone(), local_queue.pop_front().unwrap()); } local_queue = (*thread_mark_queue).popn(16); - if local_queue.len() == 0 { + if local_queue.is_empty() { if thread_count_active_workers.fetch_sub(1, Ordering::SeqCst) == 1 { (*thread_mark_queue) .pushn(&mut VecDeque::from([MarkQueueElement::End]));