docs: explain Tessera modules and execution flows in Chinese

This commit is contained in:
2026-11-11 23:36:03 +08:00
parent 4c3fc8b5dd
commit 1fedd21d3c
77 changed files with 1418 additions and 0 deletions
+41
View File
@@ -1,3 +1,7 @@
//! 源 measure/arrange 协议的分片布局驱动器。自底向上的测量与自顶向下的安排共享一个只读 VM 调用域。
//! Plan 只保存派生几何和求解过程;Measurement 缓存记录真实读取依赖。已有业务对象在只读阶段不能被修改。
//! 较大树可在节点/指令量子之间挂起。Work 拥有尚未发布的执行状态,必须 resume 或 cancel;完成后才把 Draft 交给桥接层提交。
//!
//! Bottom-up measurement and top-down arrangement share one read-only VM call.
//! The host scratch plan contains derived data only, never a second business heap.
use crate::{
@@ -22,9 +26,11 @@ use std::{
// same per-occurrence VM driver so even intrinsic work can yield between nodes.
const NATIVE_FAST_PATH_MAX_NODES: usize = 64;
/// 统一构造本模块的参数错误,让调用方停止处理无效输入。
fn invalid(message: &'static str) -> VmError {
VmError::InvalidArgument(message)
}
/// 读取当前 desktop 的类型字典,为布局协议结果提供名义类型检查。
fn desktop_type_registry(cx: &NativeContext<'_>, desktop: ObjectRef) -> Result<ObjectRef, VmError> {
match cx.store().get_attr(desktop, "types")? {
Value::Object(object) => Ok(object),
@@ -32,6 +38,7 @@ fn desktop_type_registry(cx: &NativeContext<'_>, desktop: ObjectRef) -> Result<O
}
}
#[derive(Debug, Clone)]
/// 一次源测量的缓存输入、输出和真实读取依赖;不同约束或依赖版本不能复用。
struct Measurement {
owner: ObjectRef,
method: ObjectRef,
@@ -42,12 +49,14 @@ struct Measurement {
}
/// Borrowed identities and versions only: this cache adds no managed roots.
#[derive(Debug, Default, Clone)]
/// 按 Mount 弱身份保存源测量结果,不为业务对象增加托管根。
pub struct Cache {
entries: HashMap<WeakObjectRef, Measurement>,
pub hits: usize,
pub misses: usize,
}
impl Cache {
/// 从测量缓存依赖中移除宿主私有 desktop 记账对象,防止内部同步造成自我失效。
pub(crate) fn exclude_host_desktops(&mut self, desktops: &HashSet<ObjectRef>) {
for entry in self.entries.values_mut() {
entry
@@ -55,10 +64,12 @@ impl Cache {
.retain(|read| !desktops.contains(&read.object()));
}
}
/// 移除受影响 owner 的源测量缓存;其他出现继续按其读取版本检查。
pub fn invalidate(&mut self, owners: &HashSet<ObjectRef>) {
self.entries
.retain(|_, entry| !owners.contains(&entry.owner));
}
/// 清空本对象维护的当前内容或缓存,后续状态由调用方重新建立。
pub fn clear(&mut self) {
self.entries.clear();
self.hits = 0;
@@ -66,6 +77,7 @@ impl Cache {
}
}
#[derive(Debug)]
/// 一个等待源测量返回的收集项,记录本次方法、约束和子项输入。
struct Pending {
token: usize,
owner: ObjectRef,
@@ -75,10 +87,13 @@ struct Pending {
key: WeakObjectRef,
}
#[derive(Debug)]
/// 未发布的布局求解工作区,包含出现树、期望尺寸、分配边界、收敛记录和缓存。
struct Plan {
// 使用出现索引保存树和几何,不为每个位置建立第二份业务对象。
nodes: Vec<Arc<UiNode>>,
children: Vec<Vec<usize>>,
sizes: Vec<Size>,
// preferred 是测量偏好,bounds 是父级实际分配;换行/flex 会使两者不同。
preferred: Vec<Option<Size>>,
bounds: Vec<Option<[f32; 4]>>,
runtime: LayoutRuntime,
@@ -92,16 +107,19 @@ struct Plan {
native_arrange: Vec<bool>,
custom_measure: Vec<bool>,
measured_limits: Vec<[Option<f32>; 2]>,
// 保存几何状态用于检测收敛和重复状态,防止相互依赖布局无限循环。
previous: Option<Vec<u32>>,
seen: BTreeSet<Vec<u32>>,
}
type Shared = Arc<Mutex<Plan>>;
#[derive(Debug, Clone, Copy)]
/// 源视觉调用当前处于测量还是安排阶段,决定调用方法与结果解码。
enum Phase {
Measure,
Arrange,
}
impl Phase {
/// 把当前布局阶段映射为 measure 或 arrange 方法名称。
fn method(self) -> &'static str {
match self {
Self::Measure => "measure",
@@ -110,6 +128,7 @@ impl Phase {
}
}
#[derive(Debug)]
/// 为某次出现准备一个 measure/arrange 调用,选择原生快速结果或真正的源覆盖。
struct Step {
plan: Shared,
index: usize,
@@ -118,10 +137,12 @@ struct Step {
desktop: ObjectRef,
}
impl NativeCallable for Step {
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
fn arity(&self) -> Option<endor_core::CallArity> {
Some(endor_core::CallArity::exact(0))
}
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
fn invoke(&self, cx: &mut NativeContext<'_>, _: &[Value]) -> Result<NativeResult, VmError> {
let mount = cx.store().payload::<Mount>(self.mount, "Mount")?.clone();
let definition = cx
@@ -293,6 +314,7 @@ impl NativeCallable for Step {
}
}
#[derive(Debug)]
/// 接收并检查源协议返回结果,将其合入 Plan,而不是直接写成发布帧。
struct Collect {
plan: Shared,
index: usize,
@@ -300,10 +322,12 @@ struct Collect {
desktop: ObjectRef,
}
impl NativeCallable for Collect {
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
fn arity(&self) -> Option<endor_core::CallArity> {
Some(endor_core::CallArity::exact(1))
}
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
fn invoke(&self, cx: &mut NativeContext<'_>, args: &[Value]) -> Result<NativeResult, VmError> {
let pending = if matches!(self.phase, Phase::Measure) {
self.plan
@@ -496,14 +520,17 @@ impl NativeCallable for Collect {
}
}
#[derive(Debug)]
/// 检查本轮布局是否已收敛,必要时安排下一次测量/分配迭代。
struct Settle {
plan: Shared,
mounts: Arc<[WeakObjectRef]>,
}
impl NativeCallable for Settle {
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
fn arity(&self) -> Option<endor_core::CallArity> {
Some(endor_core::CallArity::exact(0))
}
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
fn invoke(&self, cx: &mut NativeContext<'_>, _: &[Value]) -> Result<NativeResult, VmError> {
let repeat = {
let mut plan = self
@@ -626,15 +653,18 @@ impl NativeCallable for Settle {
}
#[derive(Debug)]
/// 准备当前求解步骤所需的约束和 Mount 临时上下文。
struct Prepare {
plan: Shared,
mounts: Vec<WeakObjectRef>,
desktop: ObjectRef,
}
impl NativeCallable for Prepare {
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
fn arity(&self) -> Option<endor_core::CallArity> {
Some(endor_core::CallArity::exact(0))
}
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
fn invoke(&self, cx: &mut NativeContext<'_>, _: &[Value]) -> Result<NativeResult, VmError> {
let advance = cx.allocate(ContextNativeFunction::new(
"next layout occurrence",
@@ -655,6 +685,7 @@ impl NativeCallable for Prepare {
}
#[derive(Debug)]
/// 在同一驱动帧中安排下一项布局工作,使大树能够分片让出。
struct Advance {
plan: Shared,
mounts: Arc<[WeakObjectRef]>,
@@ -662,9 +693,11 @@ struct Advance {
next: Mutex<usize>,
}
impl NativeCallable for Advance {
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
fn arity(&self) -> Option<endor_core::CallArity> {
Some(endor_core::CallArity::exact(0))
}
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
fn invoke(&self, cx: &mut NativeContext<'_>, _: &[Value]) -> Result<NativeResult, VmError> {
let count = self.mounts.len();
let position = {
@@ -741,6 +774,7 @@ impl NativeCallable for Advance {
/// An unpublished layout frame and derived caches. These are merged only after
/// the driver completes; they are not another copy of application state.
/// 已经完成本阶段、但尚未由桥接层发布的派生结果,包含帧/缓存或真实读取依赖。
pub struct Draft {
pub frame: Frame,
pub runtime: LayoutRuntime,
@@ -749,6 +783,7 @@ pub struct Draft {
}
#[must_use = "pending layout work must be resumed or cancelled with its owning VM"]
/// 本次推进处于挂起还是完成;挂起工作必须继续恢复或显式取消。
pub enum Progress {
Pending(Work),
Complete(Draft),
@@ -756,6 +791,7 @@ pub enum Progress {
/// Host-owned continuation. No borrowed frame/cache references cross a pause.
/// The prepare handle owns one root until completion or explicit cancellation.
/// 拥有未完成源调用及临时根的工作句柄;丢弃 Rust 值不能替代 VM 内的取消。
pub struct Work {
state: Draft,
plan: Shared,
@@ -765,12 +801,14 @@ pub struct Work {
}
impl Work {
/// 恢复当前 Work 拥有的 VM 续体,继续同一轮求解而不是重放 measure/arrange。
pub fn resume(mut self, vm: &mut Vm, slice: usize) -> Result<Progress> {
self.slices += 1;
let progress = vm.resume_read_only_call(slice);
self.accept(vm, progress)
}
/// 显式结束布局续体和只读域,释放本次尚未提交的临时根。
pub fn cancel(self, vm: &mut Vm) -> Result<()> {
let cancelled = vm.cancel_read_only_call();
let released = vm.release(self.prepare);
@@ -779,6 +817,7 @@ impl Work {
Ok(())
}
/// 接收一次续体进度,挂起时保留工作,完成时将派生结果交给收尾阶段。
fn accept(
self,
vm: &mut Vm,
@@ -805,6 +844,7 @@ impl Work {
}
}
/// 建立只读布局 Plan 与托管驱动函数;小型原生树可走直接路径,大树保留分片推进能力。
pub fn start(
vm: &mut Vm,
desktop: ObjectRef,
@@ -945,6 +985,7 @@ pub fn start(
work.accept(vm, progress)
}
/// 验证求解已收敛,收集最终几何、读取依赖和缓存,返回尚待桥接层提交的 Draft。
fn finish(
vm: &mut Vm,
mut work: Work,