fix: $262.gc() 补 mark 收口为顶层边界强制完整收集

This commit is contained in:
2026-09-24 05:30:47 +00:00
parent 7a0d3ce336
commit 77369ff9f1
5 changed files with 54 additions and 5 deletions
+11 -5
View File
@@ -69,14 +69,20 @@ pub fn create_realm(vm: &mut Vm, _args: &[u8]) -> NativeResult {
not_supported(vm, "createRealm")
}
/// `$262.gc()`:请求一次 session 全量回收(不计返回值)。
/// `$262.gc()`:请求一次 session 全量强制收集,返回 undefined。
///
/// 收集延迟到下一个顶层指令边界执行,不在 native 重入点就地跑:重入期间
/// dispatch 调用链上的调用方寄存器窗口副本与 callee 引用是 Rust 局部值
/// (非 GC 根),移动式 sweep 就地搬移会使它们悬垂,返回后恢复动作还会
/// 把陈旧指针写回 `regs[254]`。顶层指令边界是无在途局部值的安全点,
/// 收集经既有完整收集入口(与引擎正常触发路径同一函数)执行。
/// 对 JS 可观察语义等价于同步:收集在下一条指令求值前完成。
///
/// # 副作用
/// - 执行 mark-sweep 搬移存活对象并释放不可达对象,会重写 session 对象指针。
/// - 置强制收集旗标;下一个顶层指令边界执行 mark + 移动式 sweep +
/// 字符串/BigInt 清扫,重写 session 对象指针。
pub fn gc(vm: &mut Vm, _args: &[u8]) -> NativeResult {
let mut session_gc = std::mem::take(&mut vm.gc_state.session_gc);
session_gc.sweep(vm);
vm.gc_state.session_gc = session_gc;
vm.gc_state.pending_forced_collect = true;
NativeResult::Ok(JsValue::undefined())
}
+6
View File
@@ -121,6 +121,12 @@ impl Vm {
// 返回顶层后检查恢复,存活值此时已回拷为执行根。账目未超水位时仅
// 少量字段比较。
if self.native_call_depth == 0 {
// 宿主 `$262.gc()` 置位的强制收集在此边界消费:移动式 sweep
// 唯一安全点(无在途 dispatch 局部值),与正常触发路径同一入口。
if self.gc_state.pending_forced_collect {
self.gc_state.pending_forced_collect = false;
self.collect_session_gc();
}
// 峰值高水位:同一边界采样 session 堆账目上界
let bytes = self.gc_state.session_bytes_allocated;
if bytes > self.gc_state.session_bytes_peak {
+3
View File
@@ -58,6 +58,9 @@ pub(crate) struct GcState {
/// 门控未过(挂起态持有 for-in)后的重扫锚:包络再增长一个阈值才重扫
/// 三型状态盒(O(对象数) 扫描),避免持挂起 for-in 的 run 每指令边界重扫。
pub(crate) gc_gate_retry_alloc: usize,
/// 宿主强制收集旗标(`$262.gc()`):native 重入中置位,由下一个顶层
/// 指令边界(移动式 sweep 的唯一安全点)消费并执行完整收集。
pub(crate) pending_forced_collect: bool,
pub(crate) forwarding: HashMap<*mut JsObject, *mut JsObject, FxBuildHasher>,
}
+2
View File
@@ -134,6 +134,7 @@ impl Vm {
gc_threshold_cached: gc_threshold,
gc_watermark: gc_threshold,
gc_gate_retry_alloc: 0,
pending_forced_collect: false,
forwarding: std::collections::HashMap::with_hasher(rustc_hash::FxBuildHasher),
},
symbols: SymbolState {
@@ -267,6 +268,7 @@ impl Vm {
gc_threshold_cached: gc_threshold,
gc_watermark: gc_threshold,
gc_gate_retry_alloc: 0,
pending_forced_collect: false,
forwarding: std::collections::HashMap::with_hasher(rustc_hash::FxBuildHasher),
},
symbols: SymbolState {