mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: kernel 共享核心段拆出独立 core 模块
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
//! 跨所有 VM 实例永久共享的不可变核心:持有 perm/shape/code/prop 四张 forge
|
||||
//! Arc、VM 边界守卫计数(active_vms)、批边界 sweep 与 perm interner advisory
|
||||
//! 重建信号。
|
||||
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::code_forge::CodeForge;
|
||||
use crate::kernel_info;
|
||||
use crate::prop_forge::PropForge;
|
||||
use crate::shape_forge::ShapeForge;
|
||||
use crate::string_forge::PermInterner;
|
||||
use oxide_log;
|
||||
|
||||
use super::KernelConfig;
|
||||
|
||||
/// 不可变、跨所有 VM 实例永久共享的状态。
|
||||
/// 构造后从不原地重建——forge 表为 append-only;宿主可经
|
||||
/// [`KernelCore::should_rebuild_perm`] 阈值在安全边界(无存活 VM)整体
|
||||
/// 重建(换 `Arc`,非原地清表)。
|
||||
pub struct KernelCore {
|
||||
pub config: KernelConfig,
|
||||
pub perm_interner: Arc<PermInterner>,
|
||||
pub shape_forge: Arc<ShapeForge>,
|
||||
pub code_forge: Arc<CodeForge>,
|
||||
pub prop_forge: Arc<PropForge>,
|
||||
/// 边界不变量守卫计数:当前持有本 kernel `Arc` 的 Vm 数。
|
||||
/// `Vm` 构造器增、`Drop for Vm` 减(恰好一次),供 sweep / kernel 重建 /
|
||||
/// kernel drop 处断言"无存活 VM"边界。
|
||||
active_vms: AtomicUsize,
|
||||
}
|
||||
|
||||
impl KernelCore {
|
||||
/// 按配置创建共享核心:初始化日志系统与四个共享 forge(interner/shape/code/prop)。
|
||||
pub fn new(config: KernelConfig) -> Arc<Self> {
|
||||
oxide_log::init(&oxide_log::LogConfig {
|
||||
output: oxide_log::Output::Stderr,
|
||||
levels: config.log_levels,
|
||||
});
|
||||
let perm_interner = Arc::new(PermInterner::new());
|
||||
let shape_forge = Arc::new(ShapeForge::new());
|
||||
let code_forge = Arc::new(CodeForge::new(
|
||||
NonZeroUsize::new(config.max_cached_modules).expect("max_cached_modules must be greater than zero"),
|
||||
));
|
||||
let prop_forge = Arc::new(PropForge::new());
|
||||
let max_cached = config.max_cached_modules;
|
||||
let min_pool = config.min_pool_size;
|
||||
let core = Arc::new(Self {
|
||||
config,
|
||||
perm_interner,
|
||||
shape_forge,
|
||||
code_forge,
|
||||
prop_forge,
|
||||
active_vms: AtomicUsize::new(0),
|
||||
});
|
||||
kernel_info!("KernelCore initialized: max_cached_modules={}, min_pool={}", max_cached, min_pool);
|
||||
core
|
||||
}
|
||||
|
||||
/// 只读访问永久字符串 intern 表。
|
||||
pub fn perm_interner(&self) -> &Arc<PermInterner> {
|
||||
&self.perm_interner
|
||||
}
|
||||
|
||||
/// 只读访问共享 hidden class(shape)存储。
|
||||
pub fn shape_forge(&self) -> &Arc<ShapeForge> {
|
||||
&self.shape_forge
|
||||
}
|
||||
|
||||
/// 只读访问共享 bytecode cache。
|
||||
pub fn code_forge(&self) -> &Arc<CodeForge> {
|
||||
&self.code_forge
|
||||
}
|
||||
|
||||
/// 只读访问共享属性模板缓存。
|
||||
pub fn prop_forge(&self) -> &Arc<PropForge> {
|
||||
&self.prop_forge
|
||||
}
|
||||
|
||||
/// 只读访问构建时固定的配置。
|
||||
pub fn config(&self) -> &KernelConfig {
|
||||
&self.config
|
||||
}
|
||||
|
||||
/// 读取 session GC 阈值(字节数)。
|
||||
pub fn session_gc_threshold(&self) -> usize {
|
||||
self.config.session_gc_threshold
|
||||
}
|
||||
|
||||
/// 设置 session GC 阈值(字节数)。
|
||||
pub fn set_session_gc_threshold(&mut self, bytes: usize) {
|
||||
self.config.session_gc_threshold = bytes;
|
||||
}
|
||||
|
||||
/// 读取 code cache 的 module 数量上限。
|
||||
pub fn max_cached_modules(&self) -> usize {
|
||||
self.config.max_cached_modules
|
||||
}
|
||||
|
||||
/// 设置 code cache 的 module 数量上限。
|
||||
pub fn set_max_cached_modules(&mut self, cap: usize) {
|
||||
self.config.max_cached_modules = cap;
|
||||
}
|
||||
|
||||
/// 批边界清理瞬时 shape/prop 缓存,防止跨测试累积膨胀。
|
||||
///
|
||||
/// 瞬时 forge(非根 shape/transition/position + prop 模板)的 id 空间只在两类
|
||||
/// 边界复位:(1)kernel 整体重建——新核构造即空(结构性必清;宿主义务 =
|
||||
/// 重建前旧核无存活 VM,否则旧核连同其 forge 永久驻留);(2)批内兜底 sweep
|
||||
/// ——本函数,数据依赖:仅当 shape 或 prop 表超过 50k 阈值时才执行
|
||||
/// [`ShapeForge::clear_transient`] 与 [`PropForge::clear`](阈值是增长闸门,
|
||||
/// 宿主的检查节奏只是采样点)。字符串 intern 表 append-only、CodeForge LRU
|
||||
/// 自管理,均不碰。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 调用点须无存活 VM:对象头与 IC 词持 shape id,清空使 id 空间复位,跨复位
|
||||
/// 存活的 VM 会因 id 复用碰撞静默错槽;该前提由 debug_assert 守卫(开发期
|
||||
/// fail-fast),release 构建无断言,宿主可经 [`Self::active_vms`] 自检;
|
||||
/// - 引擎不自动重建:id 空间的另一类复位(kernel 整体重建)由宿主在
|
||||
/// "无存活 VM" 边界驱动(runner 由循环结构满足:VM 每测试新建即弃,
|
||||
/// 重建/sweep 点都在 VM 作用域外)。
|
||||
pub fn sweep_runner_forges(&self) {
|
||||
// id 空间复位在有存活 VM 时是静默错槽隐患,守卫先于阈值判断。
|
||||
debug_assert!(
|
||||
self.active_vms.load(Ordering::Relaxed) == 0,
|
||||
"sweep_runner_forges requires no live VMs (shape id space reset)"
|
||||
);
|
||||
// 键 interner 是 append-only(无逐次清理);仅当瞬时 shape/prop 表超阈值
|
||||
// 时清表(批内兜底)。
|
||||
if self.shape_forge.len() > 50_000 {
|
||||
self.shape_forge.clear_transient();
|
||||
self.prop_forge.clear();
|
||||
} else if self.prop_forge.len() > 50_000 {
|
||||
self.prop_forge.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// 宿主是否应整体重建本 kernel,并返回重建后的建议上限(advisory 信号)。
|
||||
///
|
||||
/// 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 保证零行为漂移)。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 仅在宿主边界(run 间 / 测试间 / 迭代间)调用,勿入 dispatch 热路径:
|
||||
/// `entry_count` 为 O(1) 读锁,intern 路径零加码;
|
||||
/// - 仅具备安全重建边界的宿主(test262 runner 批边界、嵌入宿主迭代
|
||||
/// 之间)应启用旋钮;REPL 类宿主(单持久 VM,重建 = 丢失顶层状态)
|
||||
/// 不应启用。
|
||||
///
|
||||
/// # 副作用
|
||||
/// 无:只读查询。
|
||||
pub fn should_rebuild_perm(&self) -> Option<u32> {
|
||||
let cap = self.config.perm_interner_max_entries?;
|
||||
(self.perm_interner.entry_count() > cap).then_some(cap.next_power_of_two().saturating_mul(2))
|
||||
}
|
||||
|
||||
/// 边界不变量守卫计数:登记一个 Vm 出生(`Vm` 两条构造路径完整构造后调用)。
|
||||
pub fn note_vm_started(&self) {
|
||||
self.active_vms.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 边界不变量守卫计数:注销一个 Vm 死亡(`Drop for Vm` 恰好调用一次)。
|
||||
pub fn note_vm_ended(&self) {
|
||||
self.active_vms.fetch_sub(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 读取当前持有本 kernel 的存活 Vm 数;release 宿主可在 id 空间复位边界自检。
|
||||
pub fn active_vms(&self) -> usize {
|
||||
self.active_vms.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KernelCore {
|
||||
fn drop(&mut self) {
|
||||
// kernel 能 drop 说明持 Arc 的 Vm 已全部归零;计数非零 = 纯计数漂移
|
||||
// (note_vm_started/note_vm_ended 配对挂接回归探测)。
|
||||
debug_assert_eq!(
|
||||
self.active_vms.load(Ordering::Relaxed),
|
||||
0,
|
||||
"KernelCore dropped with live VMs (note_vm_ended counter drift)"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
#![allow(clippy::arc_with_non_send_sync)]
|
||||
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_types::mem::P;
|
||||
@@ -9,196 +7,15 @@ use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtin::BuiltinWorld;
|
||||
use crate::code_forge::CodeForge;
|
||||
use crate::kernel_info;
|
||||
use crate::prop_forge::PropForge;
|
||||
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
|
||||
use crate::string_forge::PermInterner;
|
||||
use oxide_log;
|
||||
use crate::shape_forge::EMPTY_SHAPE_ID;
|
||||
|
||||
mod builtin_id;
|
||||
mod config;
|
||||
mod core;
|
||||
|
||||
pub use builtin_id::{BuiltinDirtySet, BuiltinId, BuiltinSnapshot, NUM_BUILTINS};
|
||||
pub use config::KernelConfig;
|
||||
|
||||
/// 不可变、跨所有 VM 实例永久共享的状态。
|
||||
/// 构造后从不原地重建——forge 表为 append-only;宿主可经
|
||||
/// [`KernelCore::should_rebuild_perm`] 阈值在安全边界(无存活 VM)整体
|
||||
/// 重建(换 `Arc`,非原地清表)。
|
||||
pub struct KernelCore {
|
||||
pub config: KernelConfig,
|
||||
pub perm_interner: Arc<PermInterner>,
|
||||
pub shape_forge: Arc<ShapeForge>,
|
||||
pub code_forge: Arc<CodeForge>,
|
||||
pub prop_forge: Arc<PropForge>,
|
||||
/// 边界不变量守卫计数:当前持有本 kernel `Arc` 的 Vm 数。
|
||||
/// `Vm` 构造器增、`Drop for Vm` 减(恰好一次),供 sweep / kernel 重建 /
|
||||
/// kernel drop 处断言"无存活 VM"边界。
|
||||
active_vms: AtomicUsize,
|
||||
}
|
||||
|
||||
impl KernelCore {
|
||||
/// 按配置创建共享核心:初始化日志系统与四个共享 forge(interner/shape/code/prop)。
|
||||
pub fn new(config: KernelConfig) -> Arc<Self> {
|
||||
oxide_log::init(&oxide_log::LogConfig {
|
||||
output: oxide_log::Output::Stderr,
|
||||
levels: config.log_levels,
|
||||
});
|
||||
let perm_interner = Arc::new(PermInterner::new());
|
||||
let shape_forge = Arc::new(ShapeForge::new());
|
||||
let code_forge = Arc::new(CodeForge::new(
|
||||
NonZeroUsize::new(config.max_cached_modules).expect("max_cached_modules must be greater than zero"),
|
||||
));
|
||||
let prop_forge = Arc::new(PropForge::new());
|
||||
let max_cached = config.max_cached_modules;
|
||||
let min_pool = config.min_pool_size;
|
||||
let core = Arc::new(Self {
|
||||
config,
|
||||
perm_interner,
|
||||
shape_forge,
|
||||
code_forge,
|
||||
prop_forge,
|
||||
active_vms: AtomicUsize::new(0),
|
||||
});
|
||||
kernel_info!("KernelCore initialized: max_cached_modules={}, min_pool={}", max_cached, min_pool);
|
||||
core
|
||||
}
|
||||
|
||||
/// 只读访问永久字符串 intern 表。
|
||||
pub fn perm_interner(&self) -> &Arc<PermInterner> {
|
||||
&self.perm_interner
|
||||
}
|
||||
|
||||
/// 只读访问共享 hidden class(shape)存储。
|
||||
pub fn shape_forge(&self) -> &Arc<ShapeForge> {
|
||||
&self.shape_forge
|
||||
}
|
||||
|
||||
/// 只读访问共享 bytecode cache。
|
||||
pub fn code_forge(&self) -> &Arc<CodeForge> {
|
||||
&self.code_forge
|
||||
}
|
||||
|
||||
/// 只读访问共享属性模板缓存。
|
||||
pub fn prop_forge(&self) -> &Arc<PropForge> {
|
||||
&self.prop_forge
|
||||
}
|
||||
|
||||
/// 只读访问构建时固定的配置。
|
||||
pub fn config(&self) -> &KernelConfig {
|
||||
&self.config
|
||||
}
|
||||
|
||||
/// 读取 session GC 阈值(字节数)。
|
||||
pub fn session_gc_threshold(&self) -> usize {
|
||||
self.config.session_gc_threshold
|
||||
}
|
||||
|
||||
/// 设置 session GC 阈值(字节数)。
|
||||
pub fn set_session_gc_threshold(&mut self, bytes: usize) {
|
||||
self.config.session_gc_threshold = bytes;
|
||||
}
|
||||
|
||||
/// 读取 code cache 的 module 数量上限。
|
||||
pub fn max_cached_modules(&self) -> usize {
|
||||
self.config.max_cached_modules
|
||||
}
|
||||
|
||||
/// 设置 code cache 的 module 数量上限。
|
||||
pub fn set_max_cached_modules(&mut self, cap: usize) {
|
||||
self.config.max_cached_modules = cap;
|
||||
}
|
||||
|
||||
/// 批边界清理瞬时 shape/prop 缓存,防止跨测试累积膨胀。
|
||||
///
|
||||
/// 瞬时 forge(非根 shape/transition/position + prop 模板)的 id 空间只在两类
|
||||
/// 边界复位:(1)kernel 整体重建——新核构造即空(结构性必清;宿主义务 =
|
||||
/// 重建前旧核无存活 VM,否则旧核连同其 forge 永久驻留);(2)批内兜底 sweep
|
||||
/// ——本函数,数据依赖:仅当 shape 或 prop 表超过 50k 阈值时才执行
|
||||
/// [`ShapeForge::clear_transient`] 与 [`PropForge::clear`](阈值是增长闸门,
|
||||
/// 宿主的检查节奏只是采样点)。字符串 intern 表 append-only、CodeForge LRU
|
||||
/// 自管理,均不碰。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 调用点须无存活 VM:对象头与 IC 词持 shape id,清空使 id 空间复位,跨复位
|
||||
/// 存活的 VM 会因 id 复用碰撞静默错槽;该前提由 debug_assert 守卫(开发期
|
||||
/// fail-fast),release 构建无断言,宿主可经 [`Self::active_vms`] 自检;
|
||||
/// - 引擎不自动重建:id 空间的另一类复位(kernel 整体重建)由宿主在
|
||||
/// "无存活 VM" 边界驱动(runner 由循环结构满足:VM 每测试新建即弃,
|
||||
/// 重建/sweep 点都在 VM 作用域外)。
|
||||
pub fn sweep_runner_forges(&self) {
|
||||
// id 空间复位在有存活 VM 时是静默错槽隐患,守卫先于阈值判断。
|
||||
debug_assert!(
|
||||
self.active_vms.load(Ordering::Relaxed) == 0,
|
||||
"sweep_runner_forges requires no live VMs (shape id space reset)"
|
||||
);
|
||||
// 键 interner 是 append-only(无逐次清理);仅当瞬时 shape/prop 表超阈值
|
||||
// 时清表(批内兜底)。
|
||||
if self.shape_forge.len() > 50_000 {
|
||||
self.shape_forge.clear_transient();
|
||||
self.prop_forge.clear();
|
||||
} else if self.prop_forge.len() > 50_000 {
|
||||
self.prop_forge.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// 宿主是否应整体重建本 kernel,并返回重建后的建议上限(advisory 信号)。
|
||||
///
|
||||
/// 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 保证零行为漂移)。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 仅在宿主边界(run 间 / 测试间 / 迭代间)调用,勿入 dispatch 热路径:
|
||||
/// `entry_count` 为 O(1) 读锁,intern 路径零加码;
|
||||
/// - 仅具备安全重建边界的宿主(test262 runner 批边界、嵌入宿主迭代
|
||||
/// 之间)应启用旋钮;REPL 类宿主(单持久 VM,重建 = 丢失顶层状态)
|
||||
/// 不应启用。
|
||||
///
|
||||
/// # 副作用
|
||||
/// 无:只读查询。
|
||||
pub fn should_rebuild_perm(&self) -> Option<u32> {
|
||||
let cap = self.config.perm_interner_max_entries?;
|
||||
(self.perm_interner.entry_count() > cap).then_some(cap.next_power_of_two().saturating_mul(2))
|
||||
}
|
||||
|
||||
/// 边界不变量守卫计数:登记一个 Vm 出生(`Vm` 两条构造路径完整构造后调用)。
|
||||
pub fn note_vm_started(&self) {
|
||||
self.active_vms.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 边界不变量守卫计数:注销一个 Vm 死亡(`Drop for Vm` 恰好调用一次)。
|
||||
pub fn note_vm_ended(&self) {
|
||||
self.active_vms.fetch_sub(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 读取当前持有本 kernel 的存活 Vm 数;release 宿主可在 id 空间复位边界自检。
|
||||
pub fn active_vms(&self) -> usize {
|
||||
self.active_vms.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KernelCore {
|
||||
fn drop(&mut self) {
|
||||
// kernel 能 drop 说明持 Arc 的 Vm 已全部归零;计数非零 = 纯计数漂移
|
||||
// (note_vm_started/note_vm_ended 配对挂接回归探测)。
|
||||
debug_assert_eq!(
|
||||
self.active_vms.load(Ordering::Relaxed),
|
||||
0,
|
||||
"KernelCore dropped with live VMs (note_vm_ended counter drift)"
|
||||
);
|
||||
}
|
||||
}
|
||||
pub use core::KernelCore;
|
||||
|
||||
/// 每会话可变状态:内置原型对象与全局对象。
|
||||
/// 在 full_reset() 时重建,实现 JS 执行之间的完全隔离。
|
||||
|
||||
Reference in New Issue
Block a user