diff --git a/Cargo.lock b/Cargo.lock index 73c2c0f1..e38aa372 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.8.88" +version = "0.8.89" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.8.88" +version = "0.8.89" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.8.88" +version = "0.8.89" dependencies = [ "ansi_term", "bumpalo", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.8.88" +version = "0.8.89" dependencies = [ "lru", "oxide_bytecode", @@ -1235,7 +1235,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1269,7 +1269,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.8.88" +version = "0.8.89" dependencies = [ "num-bigint", "oxc_allocator", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1296,7 +1296,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.8.88" +version = "0.8.89" dependencies = [ "bumpalo", "dashmap", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.8.88" +version = "0.8.89" dependencies = [ "tracing", "tracing-appender", @@ -1340,7 +1340,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1371,7 +1371,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.8.88" +version = "0.8.89" dependencies = [ "num-bigint", "num-traits", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.8.88" +version = "0.8.89" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.8.88" +version = "0.8.89" dependencies = [ "bumpalo", "dashmap", @@ -1415,7 +1415,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.8.88" +version = "0.8.89" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 9c9db652..3f12c30c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ ] [workspace.package] -version = "0.8.88" +version = "0.8.89" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_runtime_api/src/host.rs b/crates/oxide_runtime_api/src/host.rs index e01b29a8..3b5874c5 100644 --- a/crates/oxide_runtime_api/src/host.rs +++ b/crates/oxide_runtime_api/src/host.rs @@ -408,4 +408,25 @@ pub trait VmHost { /// 唤醒 (缓冲, 偏移) 处登记的前 `count` 个 waiter(`<= 0` 不唤醒、`+Inf` /// 全唤醒),逐个以 "ok" 结算(反应入队随 run 收尾 drain);返回唤醒数。 fn atomics_wake_waiters(&mut self, buffer: *mut JsObject, offset: usize, count: f64) -> usize; + + // BroadcastChannel 注册表(per-realm 弱引用) + /// 把通道对象指针按通道名登记进 per-realm 注册表(弱引用,不保活)。 + /// + /// # 边界与前提 + /// - `port` 为构造器登记后的 session 对象指针;同一指针的重复登记由 + /// 调用方保证不发生。 + /// # 副作用 + /// - 写注册表(内部可变);同名通道追加到该名下。 + fn bc_register(&self, name: &str, port: *mut JsObject); + /// 从注册表移除通道对象指针(close 注销);指针不在表内时 no-op。 + /// + /// # 副作用 + /// - 写注册表(内部可变);幂等,重复注销不报错。 + fn bc_unregister(&self, name: &str, port: *mut JsObject); + /// 查同名通道对象指针列表(返回克隆;无匹配为空列表)。 + /// + /// # 边界与前提 + /// - 列表元素为弱引用裸指针,调用方不得跨用户调用持有(GC 可释放 + /// 通道对象,须在下一次使用前重新查表校验)。 + fn bc_lookup(&self, name: &str) -> Vec<*mut JsObject>; } diff --git a/crates/oxide_vm/src/vm/vmhost.rs b/crates/oxide_vm/src/vm/vmhost.rs index 531b6531..278633e9 100644 --- a/crates/oxide_vm/src/vm/vmhost.rs +++ b/crates/oxide_vm/src/vm/vmhost.rs @@ -357,4 +357,27 @@ impl oxide_runtime_api::VmHost for Vm { fn atomics_wake_waiters(&mut self, buffer: *mut JsObject, offset: usize, count: f64) -> usize { self.atomics_wake_waiters(buffer, offset, count) } + fn bc_register(&self, name: &str, port: *mut JsObject) { + self.realm + .gc + .borrow_mut() + .broadcast_channels + .entry(name.to_string()) + .or_default() + .push(port); + } + fn bc_unregister(&self, name: &str, port: *mut JsObject) { + if let Some(v) = self.realm.gc.borrow_mut().broadcast_channels.get_mut(name) { + v.retain(|p| *p != port); + } + } + fn bc_lookup(&self, name: &str) -> Vec<*mut JsObject> { + self.realm + .gc + .borrow() + .broadcast_channels + .get(name) + .cloned() + .unwrap_or_default() + } } diff --git a/crates/oxide_vm/src/vm_state.rs b/crates/oxide_vm/src/vm_state.rs index 28c1fd2a..ad99316b 100644 --- a/crates/oxide_vm/src/vm_state.rs +++ b/crates/oxide_vm/src/vm_state.rs @@ -63,8 +63,7 @@ pub(crate) struct GcState { pub(crate) gc_pressure_mode: bool, /// BroadcastChannel per-realm 弱引用注册表:通道名 → 通道对象裸指针列表 /// (弱引用,不保活)。构造器分配后登记、close 注销、GC sweep 按 mark 位 - /// 剪枝。当前仅声明,不填不读(登记与剪枝由后续任务接线)。 - #[allow(dead_code)] + /// 剪枝、full_reset 随 session 对象一并清表。 pub(crate) broadcast_channels: HashMap>, } diff --git a/crates/oxide_vm/src/vm_support.rs b/crates/oxide_vm/src/vm_support.rs index a1004e9b..37c7144c 100644 --- a/crates/oxide_vm/src/vm_support.rs +++ b/crates/oxide_vm/src/vm_support.rs @@ -466,6 +466,9 @@ impl Vm { // 否则下次命中返回悬垂指针。 self.number_to_string_cache_keys = [0u64; 16]; self.number_to_string_cache_vals = [JsValue::undefined(); 16]; + // BroadcastChannel 注册表持 session 对象裸指针:teardown 释放全部 + // session 对象前须清表,否则残留悬垂指针。 + self.realm.gc.borrow_mut().broadcast_channels.clear(); self.realm.teardown_session_heap_data(); self.realm.gc.borrow_mut().session_bytes_allocated = 0; self.realm.gc.borrow_mut().session_bytes_peak = 0;