mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
docs: 改写虚拟机调度与属性域注释
vm/mod.rs:补模块头,说明基于寄存器的执行状态、寄存器文件、调用栈 与 session 内存及子模块职责;为 MAX_PROTO_CHAIN_DEPTH、 format_error_message、is_object_prototype 补文档。 vm/call.rs:为 is_session_ptr、alloc_object 补文档;为 call_function_sync、push_bytecode_frame 补五段式文档,写清 native/字节码 统一同步调用与统一压帧的步骤、边界和副作用。 vm/gc_hooks.rs:为 for_each_root、maybe_collect_session_gc 补文档。 vm/props.rs:property_key_si 首现展开字符串 intern id;为 array_index_from_property_key、resolve_property、get_own_property_slot 补文档。
This commit is contained in:
@@ -27,6 +27,7 @@ impl Vm {
|
||||
arg_regs
|
||||
}
|
||||
|
||||
/// 判定裸指针是否属于本 session 的 epoch:空指针恒 false。
|
||||
pub(crate) fn is_session_ptr(&self, obj_ptr: *mut JsObject) -> bool {
|
||||
if obj_ptr.is_null() {
|
||||
return false;
|
||||
@@ -35,12 +36,26 @@ impl Vm {
|
||||
unsafe { (*obj_ptr).is_session_epoch() }
|
||||
}
|
||||
|
||||
/// 在当前 epoch arena 分配对象并登记 GC 追踪表,返回裸指针。
|
||||
pub(crate) fn alloc_object(&mut self, obj: JsObject) -> *mut JsObject {
|
||||
let ptr = self.epoch.alloc(obj);
|
||||
self.gc_state.track_epoch_object(ptr);
|
||||
ptr
|
||||
}
|
||||
|
||||
/// native / 字节码函数的统一同步调用入口,返回结果或错误文本。
|
||||
///
|
||||
/// native 侧超过寄存器窗口(253)的实参转存 spill 溢出区(GC 根),字节码侧
|
||||
/// 交同 epoch 的内联执行以避免跨 epoch 指针悬垂。不可调用 callee 抛
|
||||
/// TypeError,调用深度达 `max_call_depth` 抛 RangeError。
|
||||
///
|
||||
/// # 步骤
|
||||
/// 1. 保存调用方窗口与溢出区描述,打包实参后调用 native 函数项。
|
||||
/// 2. 回拷窗口、截断溢出区并还原描述;`TailCall` 结果递归续走本入口。
|
||||
///
|
||||
/// # 副作用
|
||||
/// - 临时改写调用方寄存器窗口与 `spill_stack`,返回前还原。
|
||||
/// - `native_call_depth` 在 native 调用期间 ±1;错误对象写入异常通道。
|
||||
pub(crate) fn call_function_sync(
|
||||
&mut self, callee: JsValue, receiver: JsValue, args: &[JsValue],
|
||||
) -> Result<JsValue, String> {
|
||||
@@ -147,6 +162,24 @@ impl Vm {
|
||||
self.top_level_strict
|
||||
}
|
||||
|
||||
/// 字节码函数调用的统一压帧入口。
|
||||
///
|
||||
/// 按被调函数的表代际解析平表,实参拷入 spill 实参区后回写形参,保存调用方
|
||||
/// 窗口并切换到被调模块;非可调用、子模块索引越界或表代际缺失返回错误,
|
||||
/// 调用深度达 `max_call_depth` 时抛 RangeError。
|
||||
///
|
||||
/// # 步骤
|
||||
/// 1. 校验 callee 可调用且带子模块索引,按表代际取表并检查下标。
|
||||
/// 2. 实参写入 spill 实参区(CREATE_ARGUMENTS 源),再从中回写形参。
|
||||
/// 3. 绑定 this/new_target,压帧并切换 bytecode / immutables / 表代际。
|
||||
/// 4. 按窗口恢复内置镜像槽,重置 pc 与活动寄存器上限。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 形参多于实参补 undefined;实参区与形参写入区重叠时先拷 spill 再回写。
|
||||
///
|
||||
/// # 副作用
|
||||
/// - 压入调用帧与各类保存栈,改写 pc / bytecode / 活动寄存器上限与镜像槽;
|
||||
/// `continuation` 决定返回后的续行方式。
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub(crate) fn push_bytecode_frame(
|
||||
&mut self, callee: JsValue, this_value: JsValue, args: FrameArgs, construct_result_reg: Option<u8>,
|
||||
|
||||
@@ -168,11 +168,15 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
/// GC 根统一枚举入口:遍历的字段清单与 `rewrite_values` 一一对应。
|
||||
pub(crate) fn for_each_root(&self, f: impl FnMut(JsValue)) {
|
||||
// 统一遍历:根收集与指针重写共用同一字段清单。
|
||||
self.for_each_value(f);
|
||||
}
|
||||
|
||||
/// 执行一次 session GC(是否真正回收由 `SessionGc` 的水位门控决定)。
|
||||
///
|
||||
/// `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);
|
||||
session_gc.maybe_collect(self);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//! 基于寄存器的 JS 虚拟机:执行状态、寄存器文件、调用栈与 session 内存,
|
||||
//! 以及同步调用、指令主循环、异常通道、GC 钩子、属性解析等子模块的装配。
|
||||
|
||||
#![allow(clippy::arc_with_non_send_sync)]
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
@@ -38,6 +41,7 @@ pub use frames::{CallFrame, Completion, ForInIter, FrameContinuation, TryHandler
|
||||
pub(crate) use inline::InlineSyncState;
|
||||
pub(crate) use tables::TableGen;
|
||||
|
||||
/// 原型链解析深度上限:防超长或成环的原型链把属性查找拖入无界循环。
|
||||
pub(crate) const MAX_PROTO_CHAIN_DEPTH: usize = 1024;
|
||||
|
||||
/// 判定字符串是否为规范数组下标(无前导零的纯数字串),并反解其值。
|
||||
@@ -129,6 +133,7 @@ fn js_error_kind_name(kind: JsErrorKind) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
/// 按 name/msg 拼接错误文本:两者皆非空时为 `name: msg`,任一为空则取另一个。
|
||||
pub(crate) fn format_error_message(name: &str, msg: &str) -> String {
|
||||
if name.is_empty() {
|
||||
msg.to_string()
|
||||
@@ -371,6 +376,7 @@ impl Vm {
|
||||
&self.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();
|
||||
std::ptr::eq(ptr, proto_ptr)
|
||||
|
||||
@@ -13,7 +13,7 @@ use super::{canonical_index_of, canonical_index_units, Vm, MAX_PROTO_CHAIN_DEPTH
|
||||
use crate::vm_trace;
|
||||
|
||||
impl Vm {
|
||||
/// 把 `JsValue` 转为属性键 si(`u32`)。
|
||||
/// 把 `JsValue` 转为属性键 si(字符串 intern id,`u32`)。
|
||||
///
|
||||
/// 非负小整数(含整值 double)直接编码到整数键区间,免 to_string + intern;
|
||||
/// 字符串中形如数组下标的规范数字串(`"5"`)映射到同一整数键,保证
|
||||
@@ -97,6 +97,7 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
/// 属性键反解数组下标:整数键直取,字符串键须无前导零且 `u32` 解析成功。
|
||||
pub(crate) fn array_index_from_property_key(&self, prop_name_si: u32) -> Option<u32> {
|
||||
if is_int_key(prop_name_si) {
|
||||
return Some(int_key_value(prop_name_si));
|
||||
@@ -144,6 +145,11 @@ impl Vm {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// 属性读值解析:按数组 length 虚拟属性、元素区、shape 槽、原型链的顺序
|
||||
/// 查找,命中即返回,全链 miss 返回 `None`。
|
||||
///
|
||||
/// 数组元素区的 hole(删除标记)视同不存在;原型链查找止于
|
||||
/// `MAX_PROTO_CHAIN_DEPTH` 深度上限。
|
||||
pub(crate) fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> {
|
||||
vm_trace!("resolve_property: shape_id={} prop_name_si={}", obj.shape_id(), prop_name_si);
|
||||
let length_si = self.length_si;
|
||||
@@ -184,6 +190,9 @@ impl Vm {
|
||||
None
|
||||
}
|
||||
|
||||
/// 查找自身属性槽下标:数组 length 虚拟属性返回 `None`,元素区返回下标,
|
||||
/// shape 槽按数组(元素区之后偏移)与普通对象(槽位即下标)各自定位;
|
||||
/// 未命中的槽返回 `None`。
|
||||
pub(crate) fn get_own_property_slot(&self, obj: &JsObject, prop_name_si: u32) -> Option<u32> {
|
||||
let length_si = self.length_si;
|
||||
if obj.is_array() && prop_name_si == length_si {
|
||||
|
||||
Reference in New Issue
Block a user