From 43acaacd089fe1426aafc0060e9f6f9d520db2d3 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 2 Oct 2026 19:24:56 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=80=80=E5=BD=B9=E6=A0=B9?= =?UTF-8?q?=E9=87=8D=E5=86=99=E9=95=9C=E5=83=8F=E4=B8=8E=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E5=85=8B=E9=9A=86=E9=87=8D=E5=86=99=E6=97=8F=EF=BC=8C=E4=BF=9D?= =?UTF-8?q?=E7=95=99=E5=8E=9F=E5=9C=B0=20sweep=20=E5=BC=B1=E9=94=AE?= =?UTF-8?q?=E5=AE=9A=E5=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_types/src/object.rs | 142 +----------------------- crates/oxide_types/src/object/props.rs | 18 --- crates/oxide_types/src/object/tests.rs | 30 ----- crates/oxide_vm/src/promise/jobs.rs | 30 ----- crates/oxide_vm/src/promise/mod.rs | 2 +- crates/oxide_vm/src/session_gc.rs | 42 +------ crates/oxide_vm/src/session_gc/tests.rs | 47 -------- crates/oxide_vm/src/vm/gc_hooks.rs | 120 +------------------- crates/oxide_vm/src/vm/mod.rs | 2 +- crates/oxide_vm/src/vm_state.rs | 2 +- 10 files changed, 11 insertions(+), 424 deletions(-) diff --git a/crates/oxide_types/src/object.rs b/crates/oxide_types/src/object.rs index b29590b7..c8241b22 100644 --- a/crates/oxide_types/src/object.rs +++ b/crates/oxide_types/src/object.rs @@ -224,8 +224,6 @@ impl JsObject { pub const SESSION_EPOCH_BIT: u8 = 0x01; /// `is_session_epoch` 字段中的 GC 标记位。 pub const GC_MARK_BIT: u8 = 0x02; - /// `is_session_epoch` 字段中的 epoch 归属标记位。 - pub const EPOCH_BIT: u8 = 0x04; /// `is_session_epoch` 字段中的堆载体标记位:对象本体经 `Box::into_raw` /// 分配(统一分配入口),释放点据此 `Box::from_raw` 释放本体;arena /// 载体(移动式 sweep 克隆、晋升族克隆)无此位,本体随 arena 归还。 @@ -489,22 +487,6 @@ impl JsObject { } } - /// 是否为 epoch 分配(非 session)的对象。 - #[inline] - pub fn is_epoch(&self) -> bool { - self.is_session_epoch & Self::EPOCH_BIT != 0 - } - - /// 设置 / 清除 epoch 归属标记。 - #[inline] - pub fn set_is_epoch(&mut self, value: bool) { - if value { - self.is_session_epoch |= Self::EPOCH_BIT; - } else { - self.is_session_epoch &= !Self::EPOCH_BIT; - } - } - /// 是否堆载体(本体经 `Box::into_raw` 分配,释放点须 `Box::from_raw`)。 #[inline] pub fn is_heap_alloc(&self) -> bool { @@ -521,56 +503,6 @@ impl JsObject { } } - /// 深拷贝本对象到 session epoch:复制属性向量与元数据,标记为新 session 对象。 - /// - /// 用于把持久对象快照进当前调用上下文,修改不反向传播到源对象。 - /// `upvalues` 指针别名共享(非深拷):调用帧固化的 upvalue 表跨 GC 晋升 - /// 恒有效依赖此不变量。 - pub fn clone_for_session_epoch(&self) -> Self { - let hash_props = self - .hash_props_vec() - .map(|props| Box::into_raw(Box::new(props.clone())) as *mut u8) - .unwrap_or(std::ptr::null_mut()); - let prop_meta = self - .prop_meta_vec() - .map(|meta| Box::into_raw(Box::new(meta.clone())) as *mut u8) - .unwrap_or(std::ptr::null_mut()); - let array_elements = self - .array_elements_vec() - .map(|elems| Box::into_raw(Box::new(elems.clone())) as *mut u8) - .unwrap_or(std::ptr::null_mut()); - let array_elements_meta = self - .array_elements_meta_vec() - .map(|meta| Box::into_raw(Box::new(meta.clone())) as *mut u8) - .unwrap_or(std::ptr::null_mut()); - - Self { - header: self.header, - native_arg_count: self.native_arg_count, - type_tag: self.type_tag, - is_session_epoch: Self::SESSION_EPOCH_BIT, - _pad: self._pad, - array_elements, - array_elements_meta, - hash_props, - prop_meta, - native_data: self.native_data, - proto: self.proto, - generation: self.generation, - array_prop_count: self.array_prop_count, - array_len_override: self.array_len_override, - native_fn: self.native_fn, - sub_module_index: self.sub_module_index, - table_gen: self.table_gen, - captured_this: self.captured_this, - home_object: self.home_object, - boxed_value: self.boxed_value, - regexp_source: self.regexp_source, - regexp_flags: self.regexp_flags, - upvalues: self.upvalues, - } - } - /// 命名属性区底层指针(未分配时为空指针)。 pub fn hash_props_raw(&self) -> *mut u8 { self.hash_props @@ -596,7 +528,7 @@ impl JsObject { /// /// 供 session 收尾调用:对象本体可能仍被 Arc 引用(此后属性区不再被读取), /// 每区至多释放一次、重复调用为 no-op。upvalue 列表不在本函数释放范围内 - /// (原件与晋升克隆间别名,须收尾时去重统一释放)。 + /// (与调用帧压帧时固化的 upvalue 表共享同一 Box,单所有权,随帧收尾释放)。 pub fn release_raw_heap(&mut self) { // SAFETY: 四个区指针归本对象所有(见字段声明);回收后即刻置空。 unsafe { @@ -660,78 +592,6 @@ impl JsObject { self.upvalues = Box::into_raw(v) as *mut u8; } - /// 用 `rewrite` 改写对象内引用的所有对象值。 - /// - /// 用于 GC 移动 / 世代晋升:遍历数组元素区、命名属性区、访问器 getter/setter、 - /// `proto`、`captured_this`、`home_object` 与 upvalue cell 中的对象值, - /// 原地替换为新地址。非对象值保持不变。 - pub fn rewrite_object_values(&mut self, mut rewrite: F) - where - F: FnMut(JsValue) -> JsValue, - { - if let Some(elements) = self.array_elements_vec_mut() { - for value in elements { - if value.is_object() { - *value = rewrite(*value); - } - } - } - if let Some(meta) = self.array_elements_meta_vec_mut() { - for entry in meta.iter_mut().flatten() { - if entry.get.is_object() { - entry.get = rewrite(entry.get); - } - if entry.set.is_object() { - entry.set = rewrite(entry.set); - } - } - } - if let Some(props) = self.hash_props_vec_mut() { - for value in props { - if value.is_object() { - *value = rewrite(*value); - } - } - } - if let Some(meta) = self.prop_meta_vec_mut() { - for entry in meta.iter_mut().flatten() { - if entry.get.is_object() { - entry.get = rewrite(entry.get); - } - if entry.set.is_object() { - entry.set = rewrite(entry.set); - } - } - } - if self.proto.is_object() { - self.proto = rewrite(self.proto); - } - if self.captured_this.is_object() { - self.captured_this = rewrite(self.captured_this); - } - if self.home_object.is_object() { - self.home_object = rewrite(self.home_object); - } - if self.boxed_value.is_object() { - self.boxed_value = rewrite(self.boxed_value); - } - if self.regexp_source.is_object() { - self.regexp_source = rewrite(self.regexp_source); - } - if self.regexp_flags.is_object() { - self.regexp_flags = rewrite(self.regexp_flags); - } - if !self.upvalues.is_null() { - let cells = unsafe { &mut *(self.upvalues as *mut Vec<*mut Cell>) }; - for cell_ptr in cells { - let cell = unsafe { &mut **cell_ptr }; - if cell.value.is_object() { - cell.value = rewrite(cell.value); - } - } - } - } - /// 当前形状 ID(header 低位 24 位)。 pub fn shape_id(&self) -> ShapeId { self.header & 0x00FF_FFFF diff --git a/crates/oxide_types/src/object/props.rs b/crates/oxide_types/src/object/props.rs index 45ebccad..f2cefdc4 100644 --- a/crates/oxide_types/src/object/props.rs +++ b/crates/oxide_types/src/object/props.rs @@ -342,15 +342,6 @@ impl JsObject { } } - pub(crate) fn hash_props_vec_mut(&mut self) -> Option<&mut Vec> { - if self.hash_props.is_null() { - None - } else { - // SAFETY: 指针归本对象所有,见字段声明。 - unsafe { Some(&mut *(self.hash_props as *mut Vec)) } - } - } - /// 若数组元素区为空则初始化,并把长度对齐到 `array_prop_count`,返回其可变引用。 fn ensure_array_elements(&mut self) -> &mut Vec { if self.array_elements.is_null() { @@ -375,15 +366,6 @@ impl JsObject { } } - pub(crate) fn array_elements_vec_mut(&mut self) -> Option<&mut Vec> { - if self.array_elements.is_null() { - None - } else { - // SAFETY: 指针归本对象所有,见字段声明。 - unsafe { Some(&mut *(self.array_elements as *mut Vec)) } - } - } - /// 确保数组元素元数据向量已分配并返回可变引用(长度对齐当前元素数)。 pub fn ensure_array_elements_meta(&mut self) -> &mut Vec> { if self.array_elements_meta.is_null() { diff --git a/crates/oxide_types/src/object/tests.rs b/crates/oxide_types/src/object/tests.rs index 7b3264d6..53054d2f 100644 --- a/crates/oxide_types/src/object/tests.rs +++ b/crates/oxide_types/src/object/tests.rs @@ -61,36 +61,6 @@ fn session_epoch_marker_keeps_object_size_bound() { assert!(sz <= 256, "JsObject grew unexpectedly: {sz}B"); } -#[test] -fn clone_for_session_epoch_marks_clone_and_does_not_alias_hash_props() { - let mut source = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()); - source.set_prop_at(0, JsValue::int(1)); - - let mut clone = source.clone_for_session_epoch(); - assert!(clone.is_session_epoch()); - clone.set_prop_at(0, JsValue::int(2)); - - assert_eq!(source.get_prop_at(0), JsValue::int(1)); - assert_eq!(clone.get_prop_at(0), JsValue::int(2)); -} - -#[test] -fn clone_for_session_epoch_does_not_alias_prop_meta() { - let mut source = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()); - source.set_prop_at(0, JsValue::undefined()); - source.set_accessor_meta(0, JsValue::int(10), JsValue::int(11), PropAttributes::DEFAULT_DATA); - - let mut clone = source.clone_for_session_epoch(); - clone.set_accessor_meta(0, JsValue::int(20), JsValue::int(21), PropAttributes::DEFAULT_DATA); - - let source_meta = source.prop_meta_at(0).expect("source meta"); - let clone_meta = clone.prop_meta_at(0).expect("clone meta"); - assert_eq!(source_meta.get, JsValue::int(10)); - assert_eq!(source_meta.set, JsValue::int(11)); - assert_eq!(clone_meta.get, JsValue::int(20)); - assert_eq!(clone_meta.set, JsValue::int(21)); -} - #[test] fn shape_id_roundtrip() { let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()); diff --git a/crates/oxide_vm/src/promise/jobs.rs b/crates/oxide_vm/src/promise/jobs.rs index 574d57cb..b19cd955 100644 --- a/crates/oxide_vm/src/promise/jobs.rs +++ b/crates/oxide_vm/src/promise/jobs.rs @@ -107,33 +107,3 @@ pub(crate) fn for_each_job_value(job: &Microtask, mut f: impl FnMut(JsValue)) { } } } - -/// 供外部改写微任务队列中的 JsValue(session GC sweep 用)。 -#[allow(dead_code)] -pub(crate) fn rewrite_job_values(job: &mut Microtask, mut rewrite: impl FnMut(JsValue) -> JsValue) { - match job { - Microtask::Reaction { - handler, - argument, - resolve, - reject, - .. - } => { - *handler = rewrite(*handler); - *argument = rewrite(*argument); - *resolve = rewrite(*resolve); - *reject = rewrite(*reject); - } - Microtask::Thenable { - thenable, - then, - resolve, - reject, - } => { - *thenable = rewrite(*thenable); - *then = rewrite(*then); - *resolve = rewrite(*resolve); - *reject = rewrite(*reject); - } - } -} diff --git a/crates/oxide_vm/src/promise/mod.rs b/crates/oxide_vm/src/promise/mod.rs index ce8ef4d1..841aeff0 100644 --- a/crates/oxide_vm/src/promise/mod.rs +++ b/crates/oxide_vm/src/promise/mod.rs @@ -18,7 +18,7 @@ mod reactions; mod settlement; pub(crate) use gc_edges::{drop_promise_native, promise_native_edges, promise_native_size}; -pub(crate) use jobs::{for_each_job_value, rewrite_job_values}; +pub(crate) use jobs::for_each_job_value; pub use reactions::promise_settled_value; /// Promise 的 settled 状态。 diff --git a/crates/oxide_vm/src/session_gc.rs b/crates/oxide_vm/src/session_gc.rs index 7bc1b48f..b008e09c 100644 --- a/crates/oxide_vm/src/session_gc.rs +++ b/crates/oxide_vm/src/session_gc.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::mem::size_of; use std::time::Instant; @@ -373,8 +373,8 @@ impl SessionGc { /// 对象 DFS 跟踪 session 对象单表(统一入口 Box 化后无 epoch 表);perm /// 对象不置位(其位跨收集残留会令 DFS 短路漏扫),走独立已访集防环。 /// 字符串边走 rope 闭包传播(Cons 子节点与扁平化产物),BigInt 边直接入 - /// 存活集。roots 由 `Vm::for_each_root` 枚举,字段清单与 `rewrite_values` - /// 一一对应、须同步。只置位不搬移,调用前须先 `clear_all_marks` 清位。 + /// 存活集。roots 由 `Vm::for_each_root` 枚举。只置位不搬移,调用前须先 + /// `clear_all_marks` 清位。 pub(crate) fn mark(&mut self, vm: &Vm) { vm_debug!("[GC] mark phase: {} roots", vm.gc_state.session_object_ptrs.len()); let mut seeds = Vec::new(); @@ -1060,19 +1060,6 @@ impl Default for SessionGc { } } -#[allow(dead_code)] -fn rewrite_forwarded_value( - value: JsValue, forwarding: &HashMap<*mut JsObject, *mut JsObject, FxBuildHasher>, -) -> JsValue { - if !value.is_object() { - return value; - } - forwarding - .get(&value.as_js_object_ptr()) - .map(|&ptr| JsValue::from_js_object(ptr)) - .unwrap_or(value) -} - /// 原地 sweep 的弱键判定:session 键按 mark 位定生死(已标 = 强可达保留, /// 未标 = 死键丢弃),非 session 键(perm 对象等)不可死、恒保留;symbol /// 键按值恒等、恒保留。 @@ -1096,28 +1083,5 @@ pub(crate) fn resolve_weak_key_sweep(key: weak_map::WeakKey) -> Option Option { - Some(key) -} - -/// 按 forwarding 表把全部 VM 根引用重写到搬移后的新地址。与 `for_each_value` -/// 共用同一字段清单(经 `rewrite_values` 遍历)且须同步:遗漏字段会在搬移后 -/// 保留指向旧 arena 的悬垂指针。 -#[allow(dead_code)] -pub(crate) fn rewrite_vm_roots(vm: &mut Vm, forwarding: &HashMap<*mut JsObject, *mut JsObject, FxBuildHasher>) { - vm_debug!("[GC] rewrite_vm_roots: {} forwarded objects", forwarding.len()); - // 统一遍历:与 for_each_value 共用同一字段清单。 - vm.rewrite_values(|value| rewrite_forwarded_value(value, forwarding)); -} - #[cfg(test)] mod tests; diff --git a/crates/oxide_vm/src/session_gc/tests.rs b/crates/oxide_vm/src/session_gc/tests.rs index d662c9d7..744fc394 100644 --- a/crates/oxide_vm/src/session_gc/tests.rs +++ b/crates/oxide_vm/src/session_gc/tests.rs @@ -131,53 +131,6 @@ fn gc_roots_contains_registers_frames_and_root_roots() { assert_eq!(vm.exception_value, Some(JsValue::from_js_object(root_session))); } -#[test] -fn rewrite_matches_roots_coverage() { - // 指针重写必须覆盖根收集访问的同一组执行核心字段:session→marker 映射后, - // 每个持有 session 的字段都应被改写为 marker(与上文基于 for_each 的覆盖 - // 测试同口径,共同构成孪生清单验证)。 - let mut vm = Vm::new(); - let obj = plain_object(&mut vm); - let session = obj; - let marker = plain_object(&mut vm); - let marker_session = marker; - vm.regs[0] = JsValue::from_js_object(session); - vm.last_uncaught_value = Some(JsValue::from_js_object(session)); - vm.generator_suspended = Some(JsValue::from_js_object(session)); - vm.delegated_iterator = Some(JsValue::from_js_object(session)); - vm.async_context = Some(JsValue::from_js_object(session)); - vm.async_gen_context = Some(JsValue::from_js_object(session)); - vm.inline_callee = Some(JsValue::from_js_object(session)); - vm.pending_completion = Some(crate::vm::Completion::Return { - value: JsValue::from_js_object(session), - remaining_finally: 0, - for_of_count: 0, - for_in_count: 0, - }); - - let mut forwarding = std::collections::HashMap::new(); - forwarding.insert(session, marker_session); - vm.rewrite_values(|v| { - if v.is_object() { - if let Some(&m) = forwarding.get(&v.as_js_object_ptr()) { - return JsValue::from_js_object(m); - } - } - v - }); - assert_eq!(vm.regs[0].as_js_object_ptr(), marker_session); - assert_eq!(vm.last_uncaught_value.unwrap().as_js_object_ptr(), marker_session); - assert_eq!(vm.generator_suspended.unwrap().as_js_object_ptr(), marker_session); - assert_eq!(vm.delegated_iterator.unwrap().as_js_object_ptr(), marker_session); - assert_eq!(vm.async_context.unwrap().as_js_object_ptr(), marker_session); - assert_eq!(vm.async_gen_context.unwrap().as_js_object_ptr(), marker_session); - assert_eq!(vm.inline_callee.unwrap().as_js_object_ptr(), marker_session); - match vm.pending_completion.unwrap() { - crate::vm::Completion::Return { value, .. } => assert_eq!(value.as_js_object_ptr(), marker_session), - _ => panic!("expected Return completion"), - } -} - #[test] fn mark_phase_reaches_cycles_and_unreachable_are_unmarked() { let mut vm = Vm::new(); diff --git a/crates/oxide_vm/src/vm/gc_hooks.rs b/crates/oxide_vm/src/vm/gc_hooks.rs index d268571b..fbca1fdc 100644 --- a/crates/oxide_vm/src/vm/gc_hooks.rs +++ b/crates/oxide_vm/src/vm/gc_hooks.rs @@ -1,4 +1,4 @@ -//! GC 根遍历与执行期收集钩子:根统一枚举、搬移后指针重写、执行期两档 +//! GC 根遍历与执行期收集钩子:根统一枚举、执行期两档 //! 收集入口(安全点门控)与 session GC 账目统计访问器。 use oxide_types::object::{Cell, JsObject, JsString}; @@ -9,10 +9,9 @@ use super::Vm; use crate::session_gc::SessionGc; impl Vm { - /// GC 根收集的统一遍历(对象与字符串都产出)。与 `rewrite_values` 字段一一对应。 + /// GC 根收集的统一遍历(对象与字符串都产出)。 /// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/ - /// 挂起信号/迭代器/微任务/global。新增执行字段必须同时登记在此与 - /// `rewrite_values`。 + /// 挂起信号/迭代器/微任务/global。 pub(crate) fn for_each_value(&self, mut f: impl FnMut(JsValue)) { for value in &self.regs { f(*value); @@ -106,118 +105,7 @@ impl Vm { f(JsValue::from_js_object(self.session.global_object().as_ptr() as *mut JsObject)); } - /// GC 指针重写(session 搬移后调用)。与 `for_each_value` 字段一一对应。 - #[allow(dead_code)] - pub(crate) fn rewrite_values(&mut self, mut rewrite: impl FnMut(JsValue) -> JsValue) { - for value in &mut self.regs { - *value = rewrite(*value); - } - for frame in &mut self.frames { - frame.saved_this = rewrite(frame.saved_this); - frame.saved_new_target = rewrite(frame.saved_new_target); - frame.callee = rewrite(frame.callee); - frame.constructed_this = frame.constructed_this.map(&mut rewrite); - } - for v in &mut self.save_stack { - *v = rewrite(*v); - } - for v in &mut self.spill_stack { - *v = rewrite(*v); - } - for cell_vec in &mut self.cell_stack { - for &mut cell_ptr in cell_vec.iter_mut() { - if cell_ptr.is_null() { - continue; - } - // SAFETY: cell 经 alloc_cell 独立堆分配,本 session 内指针有效。 - let cell = unsafe { &mut *cell_ptr }; - cell.value = rewrite(cell.value); - } - } - self.exception_value = self.exception_value.map(&mut rewrite); - self.pending_exception = self.pending_exception.map(&mut rewrite); - self.last_uncaught_value = self.last_uncaught_value.map(&mut rewrite); - self.pending_length_exception = self.pending_length_exception.map(&mut rewrite); - for cached in self.template_objects.values_mut() { - *cached = rewrite(*cached); - } - self.pending_completion = self.pending_completion.map(|completion| match completion { - Completion::Return { - value, - remaining_finally, - for_of_count, - for_in_count, - } => Completion::Return { - value: rewrite(value), - remaining_finally, - for_of_count, - for_in_count, - }, - other => other, - }); - self.generator_suspended = self.generator_suspended.map(&mut rewrite); - self.delegated_iterator = self.delegated_iterator.map(&mut rewrite); - self.async_context = self.async_context.map(&mut rewrite); - self.async_gen_context = self.async_gen_context.map(&mut rewrite); - // 在途异步逃出的 promise/完成值/剩余迭代器随 sweep 重写(与 mark 段一一对应)。 - self.pending_async_escape = self.pending_async_escape.as_mut().map(|pend| { - let completion = match pend.completion { - Completion::Return { - value, - remaining_finally, - for_of_count, - for_in_count, - } => Completion::Return { - value: rewrite(value), - remaining_finally, - for_of_count, - for_in_count, - }, - other => other, - }; - super::PendingAsyncEscape { - close_promise: rewrite(pend.close_promise), - completion, - remaining: pend.remaining.iter().copied().map(&mut rewrite).collect(), - } - }); - self.inline_callee = self.inline_callee.map(&mut rewrite); - for entry in &mut self.iters.for_of_iters { - entry.iterator = rewrite(entry.iterator); - entry.last_result = rewrite(entry.last_result); - entry.fast_value = rewrite(entry.fast_value); - } - // 微任务队列中的值随 sweep 重写。 - for job in &mut self.job_queue { - crate::promise::rewrite_job_values(job, &mut rewrite); - } - // Atomics waiter 表中的 promise 随 sweep 重写(与 mark 段一一对应)。 - for promises in self.atomics_waiters.values_mut() { - for p in promises { - *p = rewrite(*p); - } - } - for iter in &mut self.iters.for_in_iters { - if iter.is_null() { - continue; - } - // SAFETY: for_in_iters 存放堆上迭代器体,VM 表独占持有。 - unsafe { - for (v, _si) in (*(*iter)).keys.iter_mut() { - *v = rewrite(*v); - } - } - } - let global_ptr = self.session.global_object().as_ptr() as *mut JsObject; - if !global_ptr.is_null() { - // SAFETY: KernelSession 在 VM 生命周期内拥有 global_object。 - unsafe { - (*global_ptr).rewrite_object_values(rewrite); - } - } - } - - /// GC 根统一枚举入口:遍历的字段清单与 `rewrite_values` 一一对应。 + /// GC 根统一枚举入口:遍历的字段清单与 `for_each_value` 相同。 pub(crate) fn for_each_root(&self, f: impl FnMut(JsValue)) { self.for_each_value(f); } diff --git a/crates/oxide_vm/src/vm/mod.rs b/crates/oxide_vm/src/vm/mod.rs index 281f72d6..a4abe6e3 100644 --- a/crates/oxide_vm/src/vm/mod.rs +++ b/crates/oxide_vm/src/vm/mod.rs @@ -359,7 +359,7 @@ pub struct Vm { /// 标签模板对象缓存(GetTemplateObject):键 = (表代际, 模块 flat_id, site 序号)。 /// 同一代际同 flat_id 同 site 恒返回同一对象;每次 `run()` 清空(缓存只留 /// 本次 run 的条目,规模有界)。键含代际维度后,跨 run 调用旧代模块的 - /// flat_id 重编号不再误命中。值为 GC 根(for_each_value/rewrite_values 遍历)。 + /// flat_id 重编号不再误命中。值为 GC 根(for_each_value 遍历)。 pub(crate) template_objects: HashMap<(u32, u32, u32), JsValue>, /// 当前活动字节码所属模块的 flat_id(顶层 0;帧切换时随 bytecode 换)。 /// GET_TEMPLATE_OBJECT 据其区分不同编译树(eval 每次编译独立 site)。 diff --git a/crates/oxide_vm/src/vm_state.rs b/crates/oxide_vm/src/vm_state.rs index f782986b..4ab5607d 100644 --- a/crates/oxide_vm/src/vm_state.rs +++ b/crates/oxide_vm/src/vm_state.rs @@ -20,7 +20,7 @@ use oxide_types::value::JsValue; /// session 堆与 GC 簿记。 /// -/// 仅做字段分类。mark/sweep/rewrite_vm_roots 驻留在 `Vm` 上:GC 需扫描所有 +/// 仅做字段分类。mark/sweep 驻留在 `Vm` 上:GC 需扫描所有 /// 子结构的根(regs、frames、for_in_iters、for_of_iters、exception_value 等), /// 无法限制在 GcState 内。 pub(crate) struct GcState {