From 55bec82f699c45a26d4485732f7b45298825571e Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 7 Oct 2026 01:50:02 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20Vm=20=E5=8A=A0=20unsafe=20impl=20Se?= =?UTF-8?q?nd=EF=BC=8C=E7=A7=BB=E9=99=A4=20vm=5Fpool=20=E7=9A=84=20Send=20?= =?UTF-8?q?=E6=8A=91=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 36 +++++++++++++++++----------------- Cargo.toml | 2 +- crates/oxide_vm/src/vm/mod.rs | 26 ++++++++++++++++++++++++ crates/oxide_vm/src/vm_pool.rs | 13 ++++++------ 4 files changed, 52 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 173c394f..ebff378f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.8.48" +version = "0.8.49" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.8.48" +version = "0.8.49" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.8.48" +version = "0.8.49" dependencies = [ "ansi_term", "bumpalo", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.8.48" +version = "0.8.49" dependencies = [ "lru", "oxide_bytecode", @@ -1234,7 +1234,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1253,7 +1253,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.8.48" +version = "0.8.49" dependencies = [ "num-bigint", "oxc_allocator", @@ -1282,7 +1282,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1291,7 +1291,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.8.48" +version = "0.8.49" dependencies = [ "bumpalo", "dashmap", @@ -1306,7 +1306,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1318,7 +1318,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.8.48" +version = "0.8.49" dependencies = [ "tracing", "tracing-appender", @@ -1327,7 +1327,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1342,7 +1342,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1358,7 +1358,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.8.48" +version = "0.8.49" dependencies = [ "num-bigint", "num-traits", @@ -1370,7 +1370,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.8.48" +version = "0.8.49" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.8.48" +version = "0.8.49" dependencies = [ "bumpalo", "hashbrown 0.14.5", @@ -1399,7 +1399,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.8.48" +version = "0.8.49" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index f823c1d2..35f354d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ members = [ ] [workspace.package] -version = "0.8.48" +version = "0.8.49" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_vm/src/vm/mod.rs b/crates/oxide_vm/src/vm/mod.rs index d4f0b65d..885ee0d2 100644 --- a/crates/oxide_vm/src/vm/mod.rs +++ b/crates/oxide_vm/src/vm/mod.rs @@ -392,6 +392,32 @@ impl Drop for Vm { } } +// SAFETY: Vm 可安全跨线程移动(Send),依据四条不变量: +// +// 1. session 堆随 Vm 整体迁移:Vm 内全部裸指针(session 对象表 +// session_object_ptrs、字符串表 session_string_ptrs、BigInt/cell 表、 +// upvalue cell 指针、active_immutables 视图、length_perm_ptr)指向的堆对象 +// 均由该 Vm 独占分配(Box::into_raw 统一入口),地址稳定、不随 Vm 移动而 +// 搬移。跨线程移动 Vm 时指针恒有效,不产生悬垂。 +// +// 2. &Vm 不跨线程共享:Vm 只经 &mut Vm 在单线程内访问(池化 VmGuard 独占 +// 借出),RefCell(GcState 的 BigInt/cell 表、Realm 的 session/gc/P 字段) +// 与 Cell(profiling 计数)的非 Sync 性不构成跨线程数据竞争。 +// +// 3. GC 根集不跨线程共享:每个 Vm 持有独立的 session 堆、独立的 mark/sweep +// 表与水位,无跨 Vm 的 GC 边。KernelCore 经 Arc 共享 +// (Send + Sync),是唯一的跨 Vm 共享面,其内部为 append-only forge 与 +// 原子计数,无 per-VM 可变状态。 +// +// 4. 裸指针不跨线程逃逸:Vm 内的裸指针只指向本 Vm 的 session 堆或共享 kernel +// 对象(perm 串 / shape / code forge),不指向其他 Vm 的堆。跨线程移动 +// Vm 时这些指针的指向不变(堆对象地址稳定),不引入别名。 +// +// realm 字段为 Arc:Realm 的 session 堆不跨线程共享,Arc 引用计数为 +// 原子操作,跨线程移动 Arc 安全;Realm 只经 Vm(单线程 &mut)访问, +// 其非 Sync 性对 Send 无碍。 +unsafe impl Send for Vm {} + impl Vm { const SYNC_NATIVE_ARG_BASE: usize = 0; const SYNC_NATIVE_ARG_LIMIT: usize = 253; diff --git a/crates/oxide_vm/src/vm_pool.rs b/crates/oxide_vm/src/vm_pool.rs index cb2f9cf6..dfb17ae0 100644 --- a/crates/oxide_vm/src/vm_pool.rs +++ b/crates/oxide_vm/src/vm_pool.rs @@ -1,5 +1,3 @@ -#![allow(clippy::arc_with_non_send_sync)] - use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Condvar, Mutex}; use std::time::Duration; @@ -15,8 +13,9 @@ struct VmPoolInner { /// 池状态计数器:空闲数、在借数、峰值借出数与已创建总数的跨线程可读快照。 /// -/// 池本体不是 Send/Sync(Vm 不跨线程),状态接口经独立原子暴露, -/// 与队列变更同步更新;空闲数恒不大于总数(总数只增不减)。 +/// 池本体是 Send/Sync(Vm 经 unsafe impl Send 跨线程移动,VmGuard 独占借出 +/// 不共享 &Vm),状态接口经独立原子暴露,与队列变更同步更新; +/// 空闲数恒不大于总数(总数只增不减)。 /// 安静态(无并发借出归还)下在借数恒等于总数减空闲数;峰值是每次 /// 借出后精确在借数的最大值,单调不降。 pub struct PoolCounters { @@ -109,7 +108,8 @@ impl VmPool { /// (共享聚合上不得覆盖写,各池各自累加)。 /// /// # 边界与前提 - /// - 计数器通常经 `PoolCounters::shared` 跨线程共享;池本体不跨线程移动。 + /// - 计数器通常经 `PoolCounters::shared` 跨线程共享;池本体可跨线程移动 + /// (Send/Sync),worker 经 spawn 独占借出 Vm。 /// /// # 副作用 /// - 同步创建 `min_size` 个 Vm。 @@ -428,7 +428,8 @@ mod tests { let kernel = Arc::clone(&kernel); let counters = Arc::clone(&counters); std::thread::spawn(move || { - // 池本体不跨线程(Vm 不 Send),每线程自建池、共享同一聚合计数器。 + // 每线程自建池、共享同一聚合计数器(Vm 经 unsafe impl Send 可 + // 跨线程,本测试仍按每线程自有池验证计数器聚合)。 let pool = VmPool::with_counters(kernel, 0, Some(8), counters); for _ in 0..50 { let guard = pool.spawn();