mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 11:11:11 +08:00
refactor: 提取 Realm 组合类型,session 与 GC 及原型槽归 realm
This commit is contained in:
@@ -47,9 +47,9 @@ impl Vm {
|
||||
obj.set_session_epoch(true);
|
||||
obj.set_heap_alloc(true);
|
||||
let ptr = Box::into_raw(Box::new(obj));
|
||||
self.gc_state.session_object_ptrs.push(ptr);
|
||||
self.realm.gc.session_object_ptrs.push(ptr);
|
||||
// 直 session 分配计入堆账目(与 promote 同式:对象头 + 对象堆数据)。
|
||||
self.gc_state.session_bytes_allocated += std::mem::size_of::<JsObject>()
|
||||
self.realm.gc.session_bytes_allocated += std::mem::size_of::<JsObject>()
|
||||
+ crate::session_gc::SessionGc::object_heap_data_bytes(unsafe { &*ptr }) as usize;
|
||||
ptr
|
||||
}
|
||||
@@ -296,7 +296,7 @@ impl Vm {
|
||||
self.regs[254] = if sub_is_arrow {
|
||||
obj.captured_this()
|
||||
} else if !sub_is_strict && this_value.is_nullish() {
|
||||
JsValue::from_js_object(self.session.global_object().as_ptr() as *mut JsObject)
|
||||
JsValue::from_js_object(self.realm.session.global_object().as_ptr() as *mut JsObject)
|
||||
} else if sub_is_strict {
|
||||
this_value
|
||||
} else {
|
||||
@@ -402,7 +402,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn native_function(vm: &mut Vm, f: crate::native::NativeFn) -> JsValue {
|
||||
let proto = vm.session.builtin_world().function_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.realm.session.builtin_world().function_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(oxide_kernel::shape_forge::EMPTY_SHAPE_ID, JsValue::from_js_object(proto));
|
||||
obj.set_function(true);
|
||||
// SAFETY: f 是 NativeFn 函数项,可作为 NativeFnPtr 存储。
|
||||
|
||||
@@ -128,29 +128,29 @@ impl Vm {
|
||||
// 宿主 `$262.gc()` 置位的强制收集与压力模式收集在此边界消费:
|
||||
// 完整收集唯一安全点(无在途 dispatch 局部值),与正常触发路径
|
||||
// 同一入口。压力模式开启后每个顶层边界做一次完整收集。
|
||||
if self.gc_state.pending_forced_collect || self.gc_state.gc_pressure_mode {
|
||||
self.gc_state.pending_forced_collect = false;
|
||||
if self.realm.gc.pending_forced_collect || self.realm.gc.gc_pressure_mode {
|
||||
self.realm.gc.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 {
|
||||
self.gc_state.session_bytes_peak = bytes;
|
||||
let bytes = self.realm.gc.session_bytes_allocated;
|
||||
if bytes > self.realm.gc.session_bytes_peak {
|
||||
self.realm.gc.session_bytes_peak = bytes;
|
||||
}
|
||||
// 单 run 分配包络高水位:O(1) 读(手工账目 + BigInt/cell 表长)。
|
||||
let alloc = self.run_alloc_bytes();
|
||||
if alloc > self.gc_state.run_alloc_peak {
|
||||
self.gc_state.run_alloc_peak = alloc;
|
||||
if alloc > self.realm.gc.run_alloc_peak {
|
||||
self.realm.gc.run_alloc_peak = alloc;
|
||||
}
|
||||
// 压力模式开启时跳过两档水位收集:完整收集已涵盖其全部工作,
|
||||
// 同边界双触发只会多一轮空转 mark。
|
||||
if bytes >= self.gc_state.string_gc_watermark && !self.gc_state.gc_pressure_mode {
|
||||
if bytes >= self.realm.gc.string_gc_watermark && !self.realm.gc.gc_pressure_mode {
|
||||
self.maybe_collect_session_strings();
|
||||
}
|
||||
// 执行期原地 sweep 收集:O(1) 包络超触发水位 → 收集(无门控:
|
||||
// 迭代器键引用经根收集标活,原地释放不搬移存活对象;
|
||||
// 边界契约见 maybe_collect_in_run)。
|
||||
if alloc >= self.gc_state.gc_watermark && !self.gc_state.gc_pressure_mode {
|
||||
if alloc >= self.realm.gc.gc_watermark && !self.realm.gc.gc_pressure_mode {
|
||||
self.maybe_collect_in_run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
}
|
||||
f(RootGroup::Global, JsValue::from_js_object(self.session.global_object().as_ptr() as *mut JsObject));
|
||||
f(RootGroup::Global, JsValue::from_js_object(self.realm.session.global_object().as_ptr() as *mut JsObject));
|
||||
}
|
||||
|
||||
/// GC 根统一枚举入口:遍历的字段清单与 `for_each_value` 相同。
|
||||
@@ -163,17 +163,17 @@ impl Vm {
|
||||
/// `session_gc` 经 `mem::take` 借出后再放回:收集需要 `&mut Vm`,而
|
||||
/// `SessionGc` 是 `Vm` 的内部字段,借出以避开借用冲突。
|
||||
pub(crate) fn maybe_collect_session_gc(&mut self) {
|
||||
let mut session_gc = std::mem::take(&mut self.gc_state.session_gc);
|
||||
let mut session_gc = std::mem::take(&mut self.realm.gc.session_gc);
|
||||
session_gc.maybe_collect(self);
|
||||
self.gc_state.session_gc = session_gc;
|
||||
self.realm.gc.session_gc = session_gc;
|
||||
}
|
||||
|
||||
/// 执行期字符串阈值回收:仅回收 session 字符串(跳过对象搬移)。热路径只在
|
||||
/// 超阈值后进入,`mem::take` 不承担每次分配的开销。
|
||||
pub(crate) fn maybe_collect_session_strings(&mut self) {
|
||||
let mut session_gc = std::mem::take(&mut self.gc_state.session_gc);
|
||||
let mut session_gc = std::mem::take(&mut self.realm.gc.session_gc);
|
||||
session_gc.maybe_collect_strings_only(self);
|
||||
self.gc_state.session_gc = session_gc;
|
||||
self.realm.gc.session_gc = session_gc;
|
||||
}
|
||||
|
||||
/// 执行期原地 sweep 收集的 dispatch 安全点入口:仅在循环顶
|
||||
@@ -187,35 +187,35 @@ impl Vm {
|
||||
/// - 无对象可回收时仍跑一轮(mark + 原地清扫),水位同点抬高,
|
||||
/// 触发间距由包络增量控制。
|
||||
pub(crate) fn maybe_collect_in_run(&mut self) {
|
||||
let mut session_gc = std::mem::take(&mut self.gc_state.session_gc);
|
||||
let mut session_gc = std::mem::take(&mut self.realm.gc.session_gc);
|
||||
session_gc.collect_in_run(self);
|
||||
self.gc_state.session_gc = session_gc;
|
||||
self.realm.gc.session_gc = session_gc;
|
||||
}
|
||||
|
||||
/// 只读访问 session GC 的统计(回收次数、存活/死亡对象数、释放字节等)。
|
||||
pub fn session_gc_stats(&self) -> &SessionGc {
|
||||
&self.gc_state.session_gc
|
||||
&self.realm.gc.session_gc
|
||||
}
|
||||
|
||||
/// 当前 session arena 中存活(已晋升)的对象数量。
|
||||
pub fn session_object_count(&self) -> usize {
|
||||
self.gc_state.session_object_ptrs.len()
|
||||
self.realm.gc.session_object_ptrs.len()
|
||||
}
|
||||
|
||||
/// session 当前分配的字节数(对象 + 存活字符串)。
|
||||
pub fn session_bytes_allocated(&self) -> usize {
|
||||
self.gc_state.session_bytes_allocated
|
||||
self.realm.gc.session_bytes_allocated
|
||||
}
|
||||
|
||||
/// 执行期 session 堆账目的峰值高水位(顶层指令边界采样,全量重置清零)。
|
||||
pub fn session_bytes_peak(&self) -> usize {
|
||||
self.gc_state.session_bytes_peak
|
||||
self.realm.gc.session_bytes_peak
|
||||
}
|
||||
|
||||
/// 本 run 累计分配字节的高水位:`run_alloc_bytes` 的顶层指令边界
|
||||
/// 采样上界,run 边界(reset/full_reset)重起算。留存内存观测锚。
|
||||
pub fn run_alloc_peak(&self) -> usize {
|
||||
self.gc_state.run_alloc_peak
|
||||
self.realm.gc.run_alloc_peak
|
||||
}
|
||||
|
||||
/// 本 run 累计分配字节:session 手工堆账目(session 对象及其属性向量 +
|
||||
@@ -228,9 +228,9 @@ impl Vm {
|
||||
/// 属性区(元素/属性向量扩容)增长对其不可见——上限判定须配合
|
||||
/// [`Self::run_alloc_bytes_full`] 的深采样层。
|
||||
pub(crate) fn run_alloc_bytes(&self) -> usize {
|
||||
self.gc_state.session_bytes_allocated
|
||||
+ self.gc_state.session_bigint_ptrs.borrow().len() * std::mem::size_of::<num_bigint::BigInt>()
|
||||
+ self.gc_state.session_cell_ptrs.borrow().len() * std::mem::size_of::<Cell>()
|
||||
self.realm.gc.session_bytes_allocated
|
||||
+ self.realm.gc.session_bigint_ptrs.borrow().len() * std::mem::size_of::<num_bigint::BigInt>()
|
||||
+ self.realm.gc.session_cell_ptrs.borrow().len() * std::mem::size_of::<Cell>()
|
||||
}
|
||||
|
||||
/// 本 run 累计分配字节(O(1) 读)。
|
||||
@@ -248,7 +248,7 @@ impl Vm {
|
||||
/// 与 [`Self::run_alloc_bytes`] 的轻层公式逐位相等。
|
||||
pub(crate) fn run_alloc_bytes_full(&self) -> u64 {
|
||||
let mut bytes = 0u64;
|
||||
for &ptr in self.gc_state.session_object_ptrs.iter() {
|
||||
for &ptr in self.realm.gc.session_object_ptrs.iter() {
|
||||
if ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
@@ -256,15 +256,15 @@ impl Vm {
|
||||
let obj = unsafe { &*ptr };
|
||||
bytes += std::mem::size_of::<JsObject>() as u64 + SessionGc::object_heap_data_bytes(obj);
|
||||
}
|
||||
for &ptr in &self.gc_state.session_string_ptrs {
|
||||
for &ptr in &self.realm.gc.session_string_ptrs {
|
||||
if ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
// SAFETY: ptr 在字符串表登记,收尾前有效。
|
||||
bytes += (std::mem::size_of::<JsString>() + unsafe { (*ptr).payload_bytes() }) as u64;
|
||||
}
|
||||
bytes += (self.gc_state.session_bigint_ptrs.borrow().len() * std::mem::size_of::<num_bigint::BigInt>()) as u64;
|
||||
bytes += (self.gc_state.session_cell_ptrs.borrow().len() * std::mem::size_of::<Cell>()) as u64;
|
||||
bytes += (self.realm.gc.session_bigint_ptrs.borrow().len() * std::mem::size_of::<num_bigint::BigInt>()) as u64;
|
||||
bytes += (self.realm.gc.session_cell_ptrs.borrow().len() * std::mem::size_of::<Cell>()) as u64;
|
||||
bytes
|
||||
}
|
||||
|
||||
@@ -278,9 +278,9 @@ impl Vm {
|
||||
/// - 须在执行外的安全点调用(无在途 builtin 局部裸指针、dispatch 未重入);
|
||||
/// 执行期触发仍走水位路径,本入口供事后观测(如基准测 workload 后留存堆)。
|
||||
pub fn collect_session_gc(&mut self) {
|
||||
let mut session_gc = std::mem::take(&mut self.gc_state.session_gc);
|
||||
let mut session_gc = std::mem::take(&mut self.realm.gc.session_gc);
|
||||
session_gc.collect(self);
|
||||
self.gc_state.session_gc = session_gc;
|
||||
self.realm.gc.session_gc = session_gc;
|
||||
}
|
||||
|
||||
/// 当前 epoch 中已分配并跟踪的对象数量。对象分配统一入口 Box 化后
|
||||
|
||||
@@ -17,11 +17,11 @@ use smallvec::SmallVec;
|
||||
/// 初始化一个 session 的内置对象(global 槽位、各构造器与原型、IC 预热)。
|
||||
pub use crate::bindings::init_kernel_builtins;
|
||||
use crate::native::NativeFn;
|
||||
use crate::realm::Realm;
|
||||
use crate::vm_debug;
|
||||
use crate::vm_state::{GcState, IterState, ProfilingState, SampleState, SymbolState};
|
||||
use crate::vm_state::{IterState, ProfilingState, SampleState, SymbolState};
|
||||
use oxide_kernel::kernel::{KernelCore, KernelSession};
|
||||
use oxide_types::error::JsErrorKind;
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::{Cell, JsObject, JsString, NativeFnPtr};
|
||||
use oxide_types::private_key::INT_KEY_COUNT;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -175,7 +175,9 @@ pub struct Vm {
|
||||
pub(crate) active_immutables: *const [JsValue],
|
||||
pub(crate) frames: SmallVec<[CallFrame; 16]>,
|
||||
pub(crate) kernel_core: Arc<KernelCore>,
|
||||
pub(crate) session: KernelSession,
|
||||
/// 每 VM 的 realm 组合:内核会话(builtin world 与 global 对象)、
|
||||
/// session GC 簿记与 10 个内建原型槽(见 `realm` 模块)。
|
||||
pub(crate) realm: Realm,
|
||||
/// `"length"` 属性键的 intern id 缓存:进程内稳定(PermInterner append-only、
|
||||
/// KernelCore 不重建),属性 get/set 热路径免每次 intern(hash64 + DashMap +
|
||||
/// RwLock 读锁)。
|
||||
@@ -190,26 +192,6 @@ pub struct Vm {
|
||||
/// f64→string 十六槽 last-value 缓存的值(session 串,经 `for_each_value`
|
||||
/// 登记为 GC 根;`full_reset` 在 session 串释放前清空)。
|
||||
pub(crate) number_to_string_cache_vals: [JsValue; 16],
|
||||
pub object_prototype: P<JsObject>,
|
||||
/// `%GeneratorPrototype%`:生成器实例的原型(next/return/throw 方法挂此)。
|
||||
pub generator_proto: P<JsObject>,
|
||||
/// `%GeneratorFunction.prototype%`:生成器函数对象的原型(`constructor` 指向
|
||||
/// `%GeneratorFunction%`,使 `g.constructor.name` 解析为 "GeneratorFunction")。
|
||||
pub generator_function_proto: P<JsObject>,
|
||||
/// `%Promise%` 构造器(resolve/reject 静态方法挂此,global 的 Promise 槽指向它)。
|
||||
pub promise_constructor: P<JsObject>,
|
||||
/// `%Promise.prototype%`:Promise 实例的原型(then/catch/finally 方法挂此)。
|
||||
pub promise_proto: P<JsObject>,
|
||||
/// `%AggregateError%` 构造器(Promise.any 拒绝时构造 AggregateError 用)。
|
||||
pub aggregate_error_constructor: P<JsObject>,
|
||||
/// `%AggregateError.prototype%`(proto = %Error.prototype%)。
|
||||
pub aggregate_error_proto: P<JsObject>,
|
||||
/// `%AsyncFunction.prototype%`:异步函数对象的原型(`constructor` 指向 `%AsyncFunction%`)。
|
||||
pub async_function_proto: P<JsObject>,
|
||||
/// `%AsyncGeneratorPrototype%`:异步生成器实例的原型(next/return/throw/@@asyncIterator)。
|
||||
pub async_generator_proto: P<JsObject>,
|
||||
/// `%AsyncGeneratorFunction.prototype%`:异步生成器函数对象的原型。
|
||||
pub async_generator_function_proto: P<JsObject>,
|
||||
/// 微任务队列(Promise reactions / thenable 委托),`run()` 末尾 FIFO drain。
|
||||
pub(crate) job_queue: VecDeque<crate::promise::Microtask>,
|
||||
/// Atomics.waitAsync waiter 表:键 = (缓冲对象指针, 元素字节偏移),值 =
|
||||
@@ -357,8 +339,6 @@ pub struct Vm {
|
||||
/// 异步生成器 body `dispatch()` 的 AWAIT 让出信号:置 true 表示挂起在 await,
|
||||
/// 恢复方(异步生成器内嵌 dispatch 循环)据此快照挂起状态。
|
||||
pub(crate) async_gen_suspended: bool,
|
||||
/// 分组保存 session arena / GC 簿记状态。
|
||||
pub(crate) gc_state: GcState,
|
||||
/// 分组保存 `Symbol` intern 状态。
|
||||
pub(crate) symbols: SymbolState,
|
||||
/// 分组保存活跃的 for-in / for-of 迭代器状态。
|
||||
@@ -440,12 +420,12 @@ impl Vm {
|
||||
|
||||
/// 只读访问当前 session(builtin world 与 global object)。
|
||||
pub fn session(&self) -> &KernelSession {
|
||||
&self.session
|
||||
&self.realm.session
|
||||
}
|
||||
|
||||
/// 判定裸指针是否指向当前 session 的 `%Object.prototype%`。
|
||||
pub(crate) fn is_object_prototype(&self, ptr: *const JsObject) -> bool {
|
||||
let proto_ptr = self.session.builtin_world().object_proto.as_ptr();
|
||||
let proto_ptr = self.realm.session.builtin_world().object_proto.as_ptr();
|
||||
std::ptr::eq(ptr, proto_ptr)
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ impl oxide_runtime_api::VmHost for Vm {
|
||||
self.kernel_core()
|
||||
}
|
||||
fn session(&self) -> &KernelSession {
|
||||
self.session()
|
||||
&self.realm.session
|
||||
}
|
||||
fn pc(&self) -> usize {
|
||||
self.pc
|
||||
@@ -189,9 +189,9 @@ impl oxide_runtime_api::VmHost for Vm {
|
||||
return false;
|
||||
}
|
||||
let p = proto.as_js_object_ptr() as *const JsObject;
|
||||
std::ptr::eq(p, self.generator_function_proto.as_ptr())
|
||||
|| std::ptr::eq(p, self.async_function_proto.as_ptr())
|
||||
|| std::ptr::eq(p, self.async_generator_function_proto.as_ptr())
|
||||
std::ptr::eq(p, self.realm.generator_function_proto.as_ptr())
|
||||
|| std::ptr::eq(p, self.realm.async_function_proto.as_ptr())
|
||||
|| std::ptr::eq(p, self.realm.async_generator_function_proto.as_ptr())
|
||||
}
|
||||
fn step_rng(&mut self) {
|
||||
self.step_rng()
|
||||
|
||||
Reference in New Issue
Block a user