refactor: for-in 迭代器体脱离 epoch arena 改堆上 Box 独占释放

This commit is contained in:
2026-09-29 16:10:15 +00:00
parent c067dcce21
commit c671a6cfb0
14 changed files with 117 additions and 55 deletions
+4 -2
View File
@@ -87,11 +87,13 @@ pub struct CallFrame {
/// 一次 `for-in` 迭代的游标:已收集的 key 列表与当前下标。
///
/// 体是堆上 `Box`:迭代器表与挂起状态盒各独占持有体,出表/状态盒释放时
/// 逐条释放。
/// 每个 key 与它的 intern id 配对保存,使整型下标 key 无需重新 intern 即可排到字符串 key 之前。
pub struct ForInIter<'bump> {
pub struct ForInIter {
/// 每个 key 与其字符串 intern id 配对,使 for-in 排序时整型下标 key 无需
/// 重新 intern 即可排到字符串 key 之前。
pub keys: bumpalo::collections::Vec<'bump, (JsValue, u32)>,
pub keys: Vec<(JsValue, u32)>,
pub index: usize,
}
+5 -5
View File
@@ -96,7 +96,7 @@ impl Vm {
if iter.is_null() {
continue;
}
// SAFETY: for_in_iters 存放由当前 VM epoch 拥有的存活迭代器指针。
// SAFETY: for_in_iters 存放堆上迭代器体,VM 表独占持有。
unsafe {
for (v, _si) in (*(*iter)).keys.iter() {
f(*v);
@@ -200,7 +200,7 @@ impl Vm {
if iter.is_null() {
continue;
}
// SAFETY: for_in_iters 存放由当前 VM epoch 拥有的存活迭代器指针。
// SAFETY: for_in_iters 存放堆上迭代器体,VM 表独占持有。
unsafe {
for (v, _si) in (*(*iter)).keys.iter_mut() {
*v = rewrite(*v);
@@ -242,13 +242,13 @@ impl Vm {
/// 门控子句二:三型状态盒(生成器/异步函数/异步生成器)的
/// `suspended.for_in_iters` 是否非空。
///
/// ForInIter body 分配于 epoch arena,收集换新 Bump 即时失效在表迭代器;
/// 门控是保守门:for-in 迭代器活跃/挂起期间拦下执行期收集;
/// 挂起帧把迭代器搬入状态盒(`vm.iters` 不可见),故须逐状态盒扫描。
///
/// # 边界与前提
/// - 扫描 epoch + session 两份对象表——挂起状态盒宿主对象可能尚未晋升;
/// - 挂起帧的 keys 经状态盒边收为 GC 根(被枚举对象不误释放),悬的是
/// 迭代器 body,故按指针扫 `for_in_iters`;
/// - 挂起帧的 keys 经状态盒边收为 GC 根(被枚举对象不误释放),迭代器
/// 体是堆上 Box,故按指针扫 `for_in_iters`;
/// - 保守口径:死对象的状态盒同样计入(持挂起 for-in 的 run 放弃执行期
/// 收集),正确性优先于收益;
/// - 新增挂起态持有者须在此登记。
+18 -1
View File
@@ -32,7 +32,7 @@ pub(crate) struct InlineSyncState {
pub(crate) pending_exception: Option<JsValue>,
pub(crate) pending_error_kind: Option<&'static str>,
pub(crate) pending_completion: Option<Completion>,
pub(crate) for_in_iters: Vec<*mut ForInIter<'static>>,
pub(crate) for_in_iters: Vec<*mut ForInIter>,
pub(crate) for_of_iters: Vec<ForOfEntry>,
pub(crate) saved_bytecode_stack: Vec<Arc<[opcode::Instr]>>,
pub(crate) saved_immutables_stack: Vec<*const [JsValue]>,
@@ -62,3 +62,20 @@ pub(crate) struct InlineSyncState {
pub(crate) active_flat_id: u32,
pub(crate) active_table_gen: u32,
}
impl Drop for InlineSyncState {
/// 释放快照持有的 for-in 迭代器体:体是堆上 `Box`,快照独占持有自身体,
/// drop 时逐条释放(null 跳过)。restore 是字段直移,移出后字段为空,
/// Drop 不再触碰,无双放。
fn drop(&mut self) {
for iter in self.for_in_iters.drain(..) {
if iter.is_null() {
continue;
}
// SAFETY: 指针是堆上迭代器体,快照独占持有,释放恰好一次。
unsafe {
drop(Box::from_raw(iter));
}
}
}
}