docs: 添加 Rustdoc 注释
This commit is contained in:
@@ -40,6 +40,8 @@ macro_rules! bind_methods_static {
|
||||
};
|
||||
}
|
||||
|
||||
/// Object 静态方法与原型方法的 native 函数指针集合,由 builtin 绑定层填充后交给
|
||||
/// [`BuiltinWorld::bind_object_methods`] 安装到对象/原型上。
|
||||
pub struct ObjectMethods {
|
||||
pub keys: *const (),
|
||||
pub create: *const (),
|
||||
@@ -64,6 +66,7 @@ pub struct ObjectMethods {
|
||||
pub property_is_enumerable: *const (),
|
||||
}
|
||||
|
||||
/// Array 静态方法与原型方法的 native 函数指针集合,由 [`BuiltinWorld::bind_array_methods`] 安装。
|
||||
pub struct ArrayMethods {
|
||||
pub is_array: *const (),
|
||||
pub push: *const (),
|
||||
@@ -97,6 +100,7 @@ pub struct ArrayMethods {
|
||||
pub values: *const (),
|
||||
}
|
||||
|
||||
/// Error 家族(含各子类型)构造器与原型方法的 native 函数指针集合,由 [`BuiltinWorld::bind_error_methods`] 安装。
|
||||
pub struct ErrorMethods {
|
||||
pub error: *const (),
|
||||
pub type_error: *const (),
|
||||
@@ -109,6 +113,7 @@ pub struct ErrorMethods {
|
||||
pub stack: *const (),
|
||||
}
|
||||
|
||||
/// String 静态方法与原型方法的 native 函数指针集合,由 [`BuiltinWorld::bind_string_methods`] 安装。
|
||||
pub struct StringMethods {
|
||||
pub from_char_code: *const (),
|
||||
pub index_of: *const (),
|
||||
@@ -142,12 +147,14 @@ pub struct StringMethods {
|
||||
pub last_index_of: *const (),
|
||||
}
|
||||
|
||||
/// RegExp 原型方法的 native 函数指针集合。
|
||||
pub struct RegExpMethods {
|
||||
pub exec: *const (),
|
||||
pub test: *const (),
|
||||
pub to_string: *const (),
|
||||
}
|
||||
|
||||
/// Function 原型方法的 native 函数指针集合,由 [`BuiltinWorld::bind_function_methods`] 安装。
|
||||
pub struct FunctionMethods {
|
||||
pub call: *const (),
|
||||
pub apply: *const (),
|
||||
@@ -155,6 +162,10 @@ pub struct FunctionMethods {
|
||||
pub to_string: *const (),
|
||||
}
|
||||
|
||||
/// 全部内置对象(原型、构造器、全局单例 Math/JSON、well-known symbol 与 stub 对象)的持有者。
|
||||
///
|
||||
/// 每个 session 独立持有自己的 `BuiltinWorld`,保证 session 间内置对象隔离;
|
||||
/// 由 [`BuiltinWorld::new`] 全量构造,或 [`BuiltinWorld::rebuild_with_dirty`] 按脏标记部分重建。
|
||||
pub struct BuiltinWorld {
|
||||
pub object_proto: P<JsObject>,
|
||||
pub array_proto: P<JsObject>,
|
||||
@@ -485,6 +496,7 @@ impl BuiltinWorld {
|
||||
JsValue::from_js_object(self.function_proto.as_ptr() as *mut JsObject)
|
||||
}
|
||||
|
||||
/// 按 [`BuiltinId`] 取对应内置对象的指针引用。
|
||||
pub fn get_by_id(&self, id: BuiltinId) -> &P<JsObject> {
|
||||
match id {
|
||||
BuiltinId::ObjectProto => &self.object_proto,
|
||||
@@ -556,6 +568,8 @@ impl BuiltinWorld {
|
||||
}
|
||||
}
|
||||
|
||||
/// 全量构造一个全新的 builtin world:创建所有原型/构造器对、Error 子类型、
|
||||
/// TypedArray 家族与 well-known symbol 对象,并建立原型链链接。
|
||||
pub fn new(string_forge: &PermInterner, shape_forge: &ShapeForge) -> Self {
|
||||
let labels = builtin_labels(string_forge);
|
||||
|
||||
@@ -666,6 +680,7 @@ impl BuiltinWorld {
|
||||
world
|
||||
}
|
||||
|
||||
/// 按脏标记选择性重建 builtin world:仅重建被污染的对象家族,未污染的保留原指针。
|
||||
pub fn rebuild_with_dirty(
|
||||
current: &BuiltinWorld, string_forge: &PermInterner, shape_forge: &ShapeForge, dirty: &BuiltinDirtySet,
|
||||
) -> BuiltinWorld {
|
||||
@@ -900,6 +915,7 @@ impl BuiltinWorld {
|
||||
world
|
||||
}
|
||||
|
||||
/// 把 Object 家族方法安装到 Object 构造器与原型上(含 `hasOwnProperty` 等非枚举元数据修正)。
|
||||
pub fn bind_object_methods(&self, methods: &ObjectMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) {
|
||||
let ctor_ptr = P::as_ptr(&self.object_constructor) as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
@@ -947,6 +963,7 @@ impl BuiltinWorld {
|
||||
}
|
||||
}
|
||||
|
||||
/// 把 Array 家族方法安装到 Array 构造器与原型上。
|
||||
pub fn bind_array_methods(&self, methods: &ArrayMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) {
|
||||
let ctor_ptr = P::as_ptr(&self.array_constructor) as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
@@ -999,6 +1016,7 @@ impl BuiltinWorld {
|
||||
debug_assert!(shape_forge.lookup_position(proto.shape_id(), si).is_some());
|
||||
}
|
||||
|
||||
/// 把 Error 家族方法安装到 Error 及各子类型构造器与原型上。
|
||||
pub fn bind_error_methods(&self, methods: &ErrorMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) {
|
||||
let ctor_ptr = P::as_ptr(&self.error_constructor) as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
@@ -1061,6 +1079,7 @@ impl BuiltinWorld {
|
||||
proto.ensure_hash_props().push(name_val);
|
||||
}
|
||||
|
||||
/// 把 String 家族方法安装到 String 构造器与原型上。
|
||||
pub fn bind_string_methods(&self, methods: &StringMethods, string_forge: &PermInterner, shape_forge: &ShapeForge) {
|
||||
let ctor_ptr = P::as_ptr(&self.string_constructor) as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
@@ -1105,6 +1124,7 @@ impl BuiltinWorld {
|
||||
);
|
||||
}
|
||||
|
||||
/// 把 Function 原型方法安装到 Function.prototype 上。
|
||||
pub fn bind_function_methods(
|
||||
&self, methods: &FunctionMethods, string_forge: &PermInterner, shape_forge: &ShapeForge,
|
||||
) {
|
||||
@@ -1123,6 +1143,7 @@ impl BuiltinWorld {
|
||||
);
|
||||
}
|
||||
|
||||
/// 在指定原型上安装一个 native 方法,wrapper 函数以本 world 的 Function 原型为原型。
|
||||
pub fn bind_method(
|
||||
&self, proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, method_name: &str,
|
||||
native_fn_ptr: NativeFnPtr, arg_count: u8,
|
||||
@@ -1138,6 +1159,9 @@ impl BuiltinWorld {
|
||||
)
|
||||
}
|
||||
|
||||
/// 构造并安装一个 native 方法 wrapper 函数对象(设置 `length`/`name` 属性与参数元数据)。
|
||||
///
|
||||
/// 无状态版本,不依赖 `BuiltinWorld` 实例,供静态绑定宏在初始化阶段直接调用。
|
||||
pub fn bind_method_static(
|
||||
proto: &mut JsObject, shape_forge: &ShapeForge, string_forge: &PermInterner, method_name: &str,
|
||||
native_fn_ptr: NativeFnPtr, arg_count: u8, wrapper_proto: JsValue,
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
/// compiled bytecode cache:按编译后的 module 缓存字节码,避免重复编译。
|
||||
pub use oxide_code_cache::CodeForge;
|
||||
|
||||
@@ -16,6 +16,9 @@ use crate::string_forge::PermInterner;
|
||||
use oxide_log;
|
||||
use oxide_log::{Level, SUBSYSTEM_COUNT};
|
||||
|
||||
/// kernel 运行配置:VM 池规模、步数/调用深度上限、session GC 阈值、
|
||||
/// 日志级别与内置对象预热开关。由三个预设构造器([`KernelConfig::minimal`] /
|
||||
/// [`KernelConfig::standard`] / [`KernelConfig::full`])或默认值创建。
|
||||
#[derive(Clone)]
|
||||
pub struct KernelConfig {
|
||||
pub min_pool_size: usize,
|
||||
@@ -32,6 +35,7 @@ pub struct KernelConfig {
|
||||
}
|
||||
|
||||
impl KernelConfig {
|
||||
/// 最小配置:小 VM 池、关闭 code/IC 预热,适合嵌入式或单次执行场景。
|
||||
pub fn minimal() -> Self {
|
||||
Self {
|
||||
min_pool_size: 4,
|
||||
@@ -48,6 +52,7 @@ impl KernelConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// 标准配置:默认 VM 池大小,开启内置对象 code 预热。
|
||||
pub fn standard() -> Self {
|
||||
Self {
|
||||
min_pool_size: 8,
|
||||
@@ -64,6 +69,7 @@ impl KernelConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// 全量配置:无上限 VM 池,开启 shapes/code/IC 全量预热,为性能场景服务。
|
||||
pub fn full() -> Self {
|
||||
Self {
|
||||
min_pool_size: 16,
|
||||
@@ -80,18 +86,22 @@ impl KernelConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// 读取 session GC 阈值(字节数)。
|
||||
pub fn session_gc_threshold(&self) -> usize {
|
||||
self.session_gc_threshold
|
||||
}
|
||||
|
||||
/// 设置 session GC 阈值(字节数),超过后触发一次 session 级 GC。
|
||||
pub fn set_session_gc_threshold(&mut self, bytes: usize) {
|
||||
self.session_gc_threshold = bytes;
|
||||
}
|
||||
|
||||
/// 读取 code cache 的 module 数量上限。
|
||||
pub fn max_cached_modules(&self) -> usize {
|
||||
self.max_cached_modules
|
||||
}
|
||||
|
||||
/// 设置 code cache 的 module 数量上限。
|
||||
pub fn set_max_cached_modules(&mut self, cap: usize) {
|
||||
self.max_cached_modules = cap;
|
||||
}
|
||||
@@ -114,6 +124,7 @@ pub struct KernelCore {
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -138,42 +149,55 @@ impl KernelCore {
|
||||
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;
|
||||
}
|
||||
|
||||
/// 在每次 runner(test262 等)边界清理瞬时 shape/prop 缓存,防止跨测试累积膨胀。
|
||||
///
|
||||
/// 字符串 intern 表是 append-only,无需清理;仅当 shape 或 prop 表超过阈值时才执行
|
||||
/// [`ShapeForge::clear_transient`] 与 [`PropForge::clear`]。
|
||||
pub fn sweep_runner_forges(&self) {
|
||||
// The key interner is append-only (no per-run sweep); only the transient
|
||||
// shape/prop tables need bounding at the test262 per-test boundary.
|
||||
@@ -203,6 +227,10 @@ pub struct KernelSession {
|
||||
/// correct builtin family.
|
||||
pub const NUM_BUILTINS: usize = 66;
|
||||
|
||||
/// 内置对象枚举 id,与 `BuiltinWorld` 中的存储槽一一对应。
|
||||
///
|
||||
/// 覆盖各构造器/原型、Error 家族、集合类型、TypedArray 家族与 well-known symbols;
|
||||
/// `repr(u8)` 使其可直接作为数组下标(`u8` 值即下标)。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum BuiltinId {
|
||||
@@ -275,6 +303,7 @@ pub enum BuiltinId {
|
||||
}
|
||||
|
||||
impl BuiltinId {
|
||||
/// 全部 66 个内置对象的 id 常量表,供快照/脏检查按序遍历。
|
||||
pub const ALL: [BuiltinId; NUM_BUILTINS] = [
|
||||
BuiltinId::ObjectProto,
|
||||
BuiltinId::ArrayProto,
|
||||
@@ -345,6 +374,9 @@ impl BuiltinId {
|
||||
];
|
||||
}
|
||||
|
||||
/// 内置对象世代(generation)快照:记录构造时各对象及其 stub 的世代号与数量。
|
||||
///
|
||||
/// 供 [`KernelSession::dirty_since_snapshot`] 对比,判断哪些 builtin 家族在运行期被污染。
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BuiltinSnapshot {
|
||||
pub generations: [u32; NUM_BUILTINS],
|
||||
@@ -358,6 +390,7 @@ impl BuiltinSnapshot {
|
||||
obj.generation()
|
||||
}
|
||||
|
||||
/// 对给定 builtin world 与 global object 采集一份世代快照。
|
||||
pub fn new(world: &BuiltinWorld, global_object: &P<JsObject>) -> Self {
|
||||
let mut generations = [0u32; NUM_BUILTINS];
|
||||
for (i, id) in BuiltinId::ALL.iter().enumerate() {
|
||||
@@ -373,6 +406,9 @@ impl BuiltinSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
/// 按 builtin 家族划分的脏标记位集合:运行期哪些内置对象被用户代码修改过。
|
||||
///
|
||||
/// `any_builtin_dirty` 只关注 builtin world 内部对象,`any` 额外包含 global object。
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct BuiltinDirtySet {
|
||||
pub object: bool,
|
||||
@@ -397,6 +433,7 @@ pub struct BuiltinDirtySet {
|
||||
}
|
||||
|
||||
impl BuiltinDirtySet {
|
||||
/// 是否存在任何 builtin world 内部对象被污染(不含 global object)。
|
||||
pub fn any_builtin_dirty(&self) -> bool {
|
||||
self.object
|
||||
|| self.array
|
||||
@@ -418,6 +455,7 @@ impl BuiltinDirtySet {
|
||||
|| self.stubs
|
||||
}
|
||||
|
||||
/// 是否存在任何污染(builtin world 或 global object)。
|
||||
pub fn any(&self) -> bool {
|
||||
self.any_builtin_dirty() || self.global
|
||||
}
|
||||
@@ -460,18 +498,22 @@ impl KernelSession {
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读访问当前 session 的 builtin world。
|
||||
pub fn builtin_world(&self) -> &Arc<BuiltinWorld> {
|
||||
&self.builtin_world
|
||||
}
|
||||
|
||||
/// 只读访问当前 session 的 global object。
|
||||
pub fn global_object(&self) -> &P<JsObject> {
|
||||
&self.global_object
|
||||
}
|
||||
|
||||
/// 重新采集内置对象世代快照,作为下一次脏检查的基准。
|
||||
pub fn record_snapshot(&mut self) {
|
||||
self.builtin_snapshot = BuiltinSnapshot::new(&self.builtin_world, &self.global_object);
|
||||
}
|
||||
|
||||
/// 对比当前世代与最近快照,返回各 builtin 家族是否被污染。
|
||||
pub fn dirty_since_snapshot(&self) -> BuiltinDirtySet {
|
||||
let world = self.builtin_world.as_ref();
|
||||
let snapshot = &self.builtin_snapshot;
|
||||
@@ -555,10 +597,14 @@ impl KernelSession {
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否自上次快照以来存在任何污染。
|
||||
pub fn is_dirty_since_snapshot(&self) -> bool {
|
||||
self.dirty_since_snapshot().any()
|
||||
}
|
||||
|
||||
/// 选择性重置:只重建被污染的对象(global 或相应 builtin 家族),并返回脏集合。
|
||||
///
|
||||
/// 相比全量重建,可保留未污染的内置对象指针与世代,减少隔离成本。
|
||||
pub fn selective_reset(&mut self, core: &Arc<KernelCore>) -> BuiltinDirtySet {
|
||||
let dirty = self.dirty_since_snapshot();
|
||||
if dirty.global {
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
#![doc = "OxideJS - Shared kernel (CodeForge, ShapeForge, PropForge, StringForge, BuiltinWorld)"]
|
||||
//!
|
||||
//! 运行时共享内核层:所有 VM 实例共享的只读缓存(code cache、hidden class /
|
||||
//! shape store、属性模板、字符串 intern 表)以及内置对象(builtin world)的
|
||||
//! 构造与重建逻辑。位于依赖链 `oxide_types ← oxide_kernel ← ...` 中,被
|
||||
//! `oxide_vm` 与 `oxide_runtime_api` 共同依赖。
|
||||
|
||||
/// 内置运行时对象(Object/Array/... 及各自原型)的构造与重建。
|
||||
pub mod builtin;
|
||||
/// compiled bytecode cache 的再导出(来自 `oxide_code_cache`)。
|
||||
pub mod code_forge;
|
||||
/// kernel 核心:配置、共享缓存入口([`KernelCore`])与 per-session 状态。
|
||||
pub mod kernel;
|
||||
/// kernel 层日志宏。
|
||||
pub mod kernel_log;
|
||||
/// 属性模板缓存:按 shape 缓存属性槽位布局,加速属性查找。
|
||||
pub mod prop_forge;
|
||||
/// hidden class(shape)共享存储:把对象结构映射为整数 id。
|
||||
pub mod shape_forge;
|
||||
/// 永久字符串 intern 表:属性名/方法名稳定 id 化。
|
||||
pub mod string_forge;
|
||||
|
||||
/// kernel 对外的三个核心类型:配置、共享核心、会话。
|
||||
pub use kernel::{KernelConfig, KernelCore, KernelSession};
|
||||
|
||||
@@ -4,6 +4,9 @@ use dashmap::DashMap;
|
||||
|
||||
use crate::shape_forge::ShapeId;
|
||||
|
||||
/// 属性布局模板:记录某个 shape 下属性 `prop_name` 应落在对象存储中的 `position`。
|
||||
///
|
||||
/// `generation` 用于并发更新时的版本裁决(新代覆盖旧代)。
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PropTemplate {
|
||||
pub shape_id: ShapeId,
|
||||
@@ -12,23 +15,30 @@ pub struct PropTemplate {
|
||||
pub generation: u32,
|
||||
}
|
||||
|
||||
/// 属性模板缓存:`shape_id → 属性布局` 的共享映射。
|
||||
///
|
||||
/// 供 IC(inline cache)与属性写入路径查询,避免每次写属性都回溯 shape 父链算槽位。
|
||||
pub struct PropForge {
|
||||
templates: DashMap<ShapeId, Arc<PropTemplate>>,
|
||||
}
|
||||
|
||||
impl PropForge {
|
||||
/// 创建空缓存。
|
||||
pub fn new() -> Self {
|
||||
Self { templates: DashMap::new() }
|
||||
}
|
||||
|
||||
/// 取指定 shape 的属性模板;未缓存时返回 `None`。
|
||||
pub fn get_template(&self, shape_id: ShapeId) -> Option<Arc<PropTemplate>> {
|
||||
self.templates.get(&shape_id).map(|r| Arc::clone(&*r))
|
||||
}
|
||||
|
||||
/// 无条件写入(覆盖)该 shape 的模板。
|
||||
pub fn upsert(&self, shape_id: ShapeId, template: PropTemplate) {
|
||||
self.templates.insert(shape_id, Arc::new(template));
|
||||
}
|
||||
|
||||
/// 仅当新模板 `generation` 更高时覆盖已有模板;空缺则直接写入。
|
||||
pub fn upsert_if_better(&self, shape_id: ShapeId, template: PropTemplate) {
|
||||
use dashmap::mapref::entry::Entry;
|
||||
|
||||
@@ -44,14 +54,17 @@ impl PropForge {
|
||||
}
|
||||
}
|
||||
|
||||
/// 清空全部模板缓存。
|
||||
pub fn clear(&self) {
|
||||
self.templates.clear();
|
||||
}
|
||||
|
||||
/// 缓存的模板数量。
|
||||
pub fn len(&self) -> usize {
|
||||
self.templates.len()
|
||||
}
|
||||
|
||||
/// 缓存是否为空。
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.templates.is_empty()
|
||||
}
|
||||
|
||||
@@ -6,12 +6,19 @@ use dashmap::DashMap;
|
||||
|
||||
use crate::{kernel_debug, kernel_trace};
|
||||
|
||||
/// 隐藏类(shape)的整数标识符。
|
||||
pub type ShapeId = u32;
|
||||
/// 属性名在字符串 intern 表([`crate::string_forge::PermInterner`])中的 id。
|
||||
pub type StringIndex = u32;
|
||||
|
||||
/// 空 shape 的保留 id:表示"无属性"的根节点,构造对象时以此为初始 shape。
|
||||
pub const EMPTY_SHAPE_ID: ShapeId = 1;
|
||||
const EMPTY_SENTINEL: StringIndex = u32::MAX;
|
||||
|
||||
/// 单个隐藏类节点:记录新增的属性名、父节点与根到自身的深度。
|
||||
///
|
||||
/// shape 构成一棵树,从根([`EMPTY_SHAPE_ID`])出发每添加一个属性产生一个子节点;
|
||||
/// `depth` 即该节点的属性总数。
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Shape {
|
||||
pub id: ShapeId,
|
||||
@@ -39,6 +46,7 @@ pub struct ShapeForge {
|
||||
}
|
||||
|
||||
impl ShapeForge {
|
||||
/// 创建空 forge,并预置 [`EMPTY_SHAPE_ID`] 根节点。
|
||||
pub fn new() -> Self {
|
||||
let forge = Self {
|
||||
shapes: RwLock::new(Vec::with_capacity(256)),
|
||||
@@ -62,10 +70,14 @@ impl ShapeForge {
|
||||
forge
|
||||
}
|
||||
|
||||
/// 把 `(parent_shape, prop_name)` 打包为单个 u64 key,用作 transition / position 缓存的键。
|
||||
pub fn pack_key(parent_id: ShapeId, prop_name: StringIndex) -> u64 {
|
||||
((parent_id as u64) << 32) | (prop_name as u64)
|
||||
}
|
||||
|
||||
/// 取(或创建)`parent_id` 加属性 `prop_name` 对应的 shape id,实现哈希一致性。
|
||||
///
|
||||
/// 相同 `(parent, prop_name)` 组合返回同一 id;超过 24 位上限后转入 overflow map 兜底。
|
||||
pub fn make_shape(&self, parent_id: ShapeId, prop_name: StringIndex) -> ShapeId {
|
||||
let key = Self::pack_key(parent_id, prop_name);
|
||||
|
||||
@@ -132,19 +144,25 @@ impl ShapeForge {
|
||||
id
|
||||
}
|
||||
|
||||
/// 按 id 取出 shape 节点的 `Arc` 副本;id 不存在时返回 `None`。
|
||||
pub fn get_shape(&self, id: ShapeId) -> Option<Arc<Shape>> {
|
||||
let shapes = self.shapes.read().unwrap();
|
||||
shapes.get((id - 1) as usize).and_then(|s| s.clone())
|
||||
}
|
||||
|
||||
/// 当前登记在册的 shape 节点数(含根节点)。
|
||||
pub fn len(&self) -> usize {
|
||||
self.shapes.read().unwrap().len()
|
||||
}
|
||||
|
||||
/// 是否尚无任何 shape(正常情况下始终为 false,因根节点恒存在)。
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// 清空所有非根 shape、transition 与 position 缓存,id 计数器复位。
|
||||
///
|
||||
/// 用于 session 重建:丢弃一次性对象产生的形状,只保留跨 session 共享的根节点。
|
||||
pub fn clear_transient(&self) {
|
||||
let mut shapes = self.shapes.write().unwrap();
|
||||
if shapes.len() > 1 {
|
||||
@@ -155,6 +173,7 @@ impl ShapeForge {
|
||||
self.next_id.store(2, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 查询属性在给定 shape 对应对象存储中的槽位下标;沿父链上溯查找并缓存结果。
|
||||
pub fn lookup_position(&self, shape_id: ShapeId, prop_name: StringIndex) -> Option<u32> {
|
||||
let cache_key = Self::pack_key(shape_id, prop_name);
|
||||
if let Some(pos) = self.positions.get(&cache_key) {
|
||||
@@ -186,6 +205,7 @@ impl ShapeForge {
|
||||
None
|
||||
}
|
||||
|
||||
/// 判断 shape 或其祖先链上是否存在指定属性。
|
||||
pub fn has_property(&self, shape_id: ShapeId, prop_name: StringIndex) -> bool {
|
||||
let shapes = self.shapes.read().unwrap();
|
||||
let mut cursor = Some(shape_id);
|
||||
@@ -203,6 +223,7 @@ impl ShapeForge {
|
||||
false
|
||||
}
|
||||
|
||||
/// 返回 shape 的属性数量(即根到该节点的深度);未知 id 返回 0。
|
||||
pub fn shape_prop_count(&self, shape_id: ShapeId) -> u32 {
|
||||
let shapes = self.shapes.read().unwrap();
|
||||
shapes
|
||||
|
||||
@@ -46,6 +46,7 @@ pub struct PermInterner {
|
||||
}
|
||||
|
||||
impl PermInterner {
|
||||
/// 创建空 intern 表。
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
hash_map: DashMap::new(),
|
||||
@@ -110,6 +111,7 @@ impl PermInterner {
|
||||
self.entries.read().unwrap().len() as u32
|
||||
}
|
||||
|
||||
/// 是否尚无任何 intern 过的 key。
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entry_count() == 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user