docs: kernel session 组注释改写与断链消解

This commit is contained in:
2026-09-17 04:29:24 +00:00
parent 2d48a7e253
commit eb6c441d62
5 changed files with 35 additions and 28 deletions
+3 -3
View File
@@ -219,8 +219,8 @@ impl BuiltinId {
];
}
// 顺序钉:ALL 与判别值 0..NUM_BUILTINS 严格同序(无换序、无重复、无遗漏);
// 错位即快照/脏检查按下标误读,钉成编译失败。
// 编译期自检:ALL 必须与判别值 0..NUM_BUILTINS 严格同序(无换序、无重复、无遗漏);
// 错位即快照/脏检查按下标误读,const 求值使错位直接成为编译错误。
const _: () = {
let mut i = 0;
while i < BuiltinId::ALL.len() {
@@ -233,7 +233,7 @@ const _: () = {
/// 内置对象世代(generation)快照:记录构造时各对象及其 stub 的世代号与数量。
///
/// 供 [`KernelSession::dirty_since_snapshot`] 对比,判断哪些 builtin 家族在运行期被污染。
/// 供 [`crate::kernel::KernelSession::dirty_since_snapshot`] 对比,判断哪些 builtin 家族在运行期被污染。
#[derive(Clone, Debug)]
pub struct BuiltinSnapshot {
pub generations: [u32; NUM_BUILTINS],
+3 -3
View File
@@ -11,11 +11,11 @@ use oxide_log::{Level, SUBSYSTEM_COUNT};
pub struct KernelConfig {
pub min_pool_size: usize,
pub max_pool_size: Option<usize>,
/// perm interner advisory 重建阈值:唯一键数 `entry_count` **超过**该值时,
/// perm interner 建议重建阈值:唯一键数 `entry_count` **超过**该值时,
/// 宿主应在安全边界(无存活 VM)整体重建 kernel,并把
/// [`KernelCore::should_rebuild_perm`] 返回的建议上限写入新 kernel 配置;
/// [`crate::kernel::KernelCore::should_rebuild_perm`] 返回的建议上限写入新 kernel 配置;
/// None = 无阈值(三个预设默认值,行为与无旋钮一致)。
/// 见 [`KernelCore::should_rebuild_perm`]。
/// 见 [`crate::kernel::KernelCore::should_rebuild_perm`]。
pub perm_interner_max_entries: Option<u32>,
pub max_steps: Option<u64>,
/// 单次 run 的分配上限(epoch + session arena + session 堆账目字节):
+14 -11
View File
@@ -1,5 +1,5 @@
//! 跨所有 VM 实例永久共享的不可变核心:持有 perm/shape/code/prop 四张 forge
//! Arc、VM 边界守卫计数(active_vms)、批边界 sweep 与 perm interner advisory
//! Arc、VM 边界守卫计数(active_vms)、批边界 sweep 与 perm interner 建议
//! 重建信号。
use std::num::NonZeroUsize;
@@ -136,28 +136,31 @@ impl KernelCore {
}
}
/// 宿主是否应整体重建本 kernel,并返回重建后的建议上限(advisory 信号)。
/// 判断宿主是否应整体重建本 kernel,并返回重建后建议写入新配置的阈值。
///
/// perm interner 唯一键数 `entry_count` **超过**配置的
/// [`KernelConfig::perm_interner_max_entries`] 阈值时返回
/// `Some(建议上限)`——建议上限 = 阈值取 2 的幂后加倍,宿主应在整体重建
/// 后把它写入新 kernel 的 `perm_interner_max_entries`(增长不立即再次
/// 触顶);阈值未设或键数未超阈值时返回 `None`。纯 advisory 契约:引擎
/// 不自动重建——重建须由宿主在"无存活 VM"边界驱动:归还全部 `VmGuard`
/// (池排空)→ 旧 `Arc<KernelCore>` 归零整体释放(PermInterner/ShapeForge/
/// CodeForge/PropForge,含全部泄漏键文本与物化串)→ 新建 kernel + 新池/
/// VM。存活 VM 的代际表注册表(`immutables`)与 P 对象持有旧 kernel 的物化串裸
/// 指针与 shape id,VM 存活期间重建会使其悬垂。三个预设默认 None = 永不
/// 触发(有意裁定:CLI eval/run/REPL/bench/test262 宿主均未接重建边界,
/// None 保证零行为漂移)。
/// 触顶);阈值未设或键数未超阈值时返回 `None`。
///
/// # 边界与前提
/// - 仅在宿主边界(run 间 / 测试间 / 迭代间)调用,勿入 dispatch 热路径:
/// `entry_count` 为 O(1) 读锁,intern 路径零加码;
/// `entry_count` 为一次读锁的 O(1) 查询,intern 路径零加码;
/// - 仅具备安全重建边界的宿主(test262 runner 批边界、嵌入宿主迭代
/// 之间)应启用旋钮;REPL 类宿主(单持久 VM,重建 = 丢失顶层状态)
/// 不应启用。
///
/// # 注意事项
/// - 纯建议、只读查询:引擎不自动重建。重建须由宿主在"无存活 VM"边界
/// 驱动:归还全部 `VmGuard`(池排空)→ 旧 `Arc<KernelCore>` 归零整体
/// 释放(PermInterner / ShapeForge / CodeForge / PropForge,含全部键
/// 文本与物化串)→ 新建 kernel 与新池 / VM。存活 VM 持有的模块代际表
/// 注册表与 P 对象引用旧 kernel 的物化串裸指针与 shape id,VM 存活
/// 期间重建会使它们悬垂。
/// - 三个预设默认 `None`(永不触发):现有 CLI eval/run/REPL/bench/test262
/// 宿主均未接重建边界,`None` 保证零行为漂移。
///
/// # 副作用
/// 无:只读查询。
pub fn should_rebuild_perm(&self) -> Option<u32> {
+14 -10
View File
@@ -12,7 +12,9 @@ use crate::shape_forge::EMPTY_SHAPE_ID;
use super::{BuiltinDirtySet, BuiltinId, BuiltinSnapshot, KernelCore};
/// 每会话可变状态:内置原型对象与全局对象。
/// 在 full_reset() 时重建,实现 JS 执行之间的完全隔离。
/// 两条重建路径:full_reset() 整体重建,实现 JS 执行之间的完全隔离;
/// selective_reset() 按世代快照的家族位脏集合只重建被污染的家族,保留
/// 未污染的内置指针与世代。
pub struct KernelSession {
pub builtin_world: Arc<BuiltinWorld>,
pub global_object: P<JsObject>,
@@ -59,7 +61,7 @@ impl KernelSession {
}
/// 从 KernelCore 构建一个全新 session。所有 string/shape intern 调用在
/// 第二次及后续调用时命中缓存——净开销 < 0.5 ms。
/// 第二次及后续调用时命中缓存。
pub fn new(core: &KernelCore) -> Self {
let builtin_world = Arc::new(BuiltinWorld::new(&core.perm_interner, &core.shape_forge));
let global_object = Self::new_global_object(core);
@@ -205,12 +207,12 @@ impl KernelSession {
self.dirty_since_snapshot().any()
}
/// 收尾释放 session 拥有的手工堆数据:builtin world(方法 wrapper 登记表 +
/// 收尾释放 session 拥有的手工堆数据:builtin world(方法 wrapper 释放登记表 +
/// 全部 P 对象属性区)与 global 对象属性区。对象本体随 Arc 引用归零释放。
///
/// # 注意事项
/// 幂等(登记表按值取走、属性区释放后置空),session 生命周期内可安全重入;
/// 仅应在 session 真正终止时调用——选择性重置换出的旧 world/global 不走本路径。
/// 幂等(释放登记表按值取走、属性区释放后置空),session 生命周期内可安全重入;
/// 仅应在 session 真正终止时调用——选择性重置替换的旧 world/global 不走本路径。
pub fn teardown_builtins(&mut self) {
self.builtin_world.teardown_heap_data();
// SAFETY: global 归本 session 所有,收尾时恰好释放其属性区一次。
@@ -237,12 +239,14 @@ impl KernelSession {
core.shape_forge.as_ref(),
&dirty,
);
// 旧 world 的登记表并入新 world:存活 wrapper(未污染家族别名)仍须在
// session 收尾统一释放;已弃 wrapper 随之恰好释放一次,不二次持有。
// 旧 world 的释放登记表并入新 world:存活 wrapper(未污染家族别名)
// 仍须在 session 收尾统一释放;已弃 wrapper 随之恰好释放一次,
// 不二次持有。
new_world.inherit_leaked_objects(&old_world);
// 重建收尾:保留对象(登记表 wrapper + 共用保留 P 字段)proto 槽
// 重指新指针,随后被替换旧对象属性区恰好释放一次(含保活钉住
// 对的属性区,本体钉保留);重指须先于释放、先于换出完成。
// 选择性重建收尾:保留对象(释放登记表 wrapper + 共用保留 P 字段)
// 原型槽改写到新指针,随后被替换旧 P 对象属性区恰好释放一次
// (Function/Object 4 个对象本体永久保留、属性区同批释放);原型
// 槽改写须先于释放、先于旧 world 被替换完成。
new_world.retire_replaced(&old_world);
self.builtin_world = Arc::new(new_world);
}
+1 -1
View File
@@ -52,7 +52,7 @@ fn test_kernel_config_presets() {
#[test]
fn should_rebuild_perm_default_off() {
// 预设默认 None = 无阈值:任意键数下永不触发,钉死零漂移默认面。
// 预设默认 None = 无阈值:任意键数下永不触发,默认配置行为与无旋钮时一致。
let core = KernelCore::new(KernelConfig::minimal());
for i in 0..10 {
core.perm_interner().intern(&format!("key{i}"));