From 42c27d083d924e51578789680208324ad7672667 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sat, 24 Oct 2026 01:39:49 +0800 Subject: [PATCH] docs: specify precise read observations and conservative compatibility --- crates/core/src/README.md | 2 + crates/core/tests/README.md | 2 + crates/core/tests/execution.rs | 111 +++++++++++++++++++++++++++++++++ crates/objects/src/README.md | 2 + docs/README.md | 2 + docs/runtime/bytecode.md | 2 + docs/runtime/native-calls.md | 3 + 7 files changed, 124 insertions(+) diff --git a/crates/core/src/README.md b/crates/core/src/README.md index 7067432..2cc2717 100644 --- a/crates/core/src/README.md +++ b/crates/core/src/README.md @@ -21,3 +21,5 @@ core 不访问对象私有字段或 Heap;执行器只通过受校验的对象存储操作维护帧根。返回 [core](../README.md)。 独立托管调用帧:frame.rs 定义 CoroutineProgress 和私有可追踪帧载荷;eval.rs 提供 new_coroutine/resume_coroutine/cancel_coroutine,暂停帧以托管边保活,恢复时转回执行根。与跨量子只读续算分开,所有权及边界见 docs/runtime/bytecode.md。 + +eval.rs的LoadGlobal及可恢复只读结果支持ReadDependency;frame.rs携带精确观察,lib.rs重导出只读观察类型,兼容旧reads对象列表。 diff --git a/crates/core/tests/README.md b/crates/core/tests/README.md index fe33e7b..e738173 100644 --- a/crates/core/tests/README.md +++ b/crates/core/tests/README.md @@ -19,3 +19,5 @@ execution.rs 同时覆盖宿主可选 assign_from 的全局/局部赋值、别 execution.rs 的 managed_coroutine 用例覆盖交替恢复不重放写入、累计预算错误释放、取消幂等和暂停帧引用环回收;本地只经宿主Clippy编译,不运行测试。 execution.rs补AwaitGate,覆盖真实Waiting、前缀写入不重放、等待操作数保活及拥有式对象结果;本地仅编译不执行。 + +execution.rs的named_reads/precise_nested_regions覆盖无关键、缺失遮蔽、内建变化、区域传播、保守遍历及观察不保活;仅编译未本地运行。 diff --git a/crates/core/tests/execution.rs b/crates/core/tests/execution.rs index c887fe7..da42424 100644 --- a/crates/core/tests/execution.rs +++ b/crates/core/tests/execution.rs @@ -1712,3 +1712,114 @@ fn await_keeps_operand_and_owned_object_result_without_replaying_prefix() { vm.release_value(result).unwrap(); assert_eq!(vm.object_count(), 0); } + +#[test] +fn named_reads_ignore_unrelated_globals_but_track_missing_shadow_and_payload_kind() { + let mut vm = Vm::new().unwrap(); + let globals = vm.new_dict().unwrap(); + let builtins = vm.new_dict().unwrap(); + vm.dict_set(builtins, text("name"), text("builtin")) + .unwrap(); + vm.dict_set(globals, text("__builtins__"), Value::Object(builtins)) + .unwrap(); + let code = make_code( + &mut vm, + &[op(Opcode::LoadGlobal, 0), simple(Opcode::ReturnValue)], + vec![], + CodeLayout { + names: vec!["name".into()], + ..CodeLayout::default() + }, + ); + let function = vm + .new_function("read-name", code, globals, vec![], vec![]) + .unwrap(); + let endor_core::ExecutionProgress::Complete { + value, + reads, + dependencies, + .. + } = vm + .start_read_only_call(function, &[], ExecutionLimits::default(), 64) + .unwrap() + else { + panic!("complete") + }; + assert_eq!(value, text("builtin")); + assert!(reads.contains(&globals) && reads.contains(&builtins)); + vm.release_value(value).unwrap(); + vm.dict_set(globals, text("_"), text("unrelated")).unwrap(); + assert!( + dependencies + .iter() + .all(|dependency| vm.object_store().read_dependency_valid(dependency)) + ); + vm.dict_set(globals, text("name"), text("shadow")).unwrap(); + assert!( + dependencies + .iter() + .any(|dependency| !vm.object_store().read_dependency_valid(dependency)) + ); + vm.dict_delete(globals, &text("name")).unwrap(); + assert!( + dependencies + .iter() + .all(|dependency| vm.object_store().read_dependency_valid(dependency)) + ); + vm.dict_set(builtins, text("name"), text("changed")) + .unwrap(); + assert!( + dependencies + .iter() + .any(|dependency| !vm.object_store().read_dependency_valid(dependency)) + ); + for object in [function, code, globals, builtins] { + vm.release(object).unwrap(); + } + assert_eq!(vm.object_count(), 0); + assert!( + dependencies + .iter() + .any(|dependency| !vm.object_store().read_dependency_valid(dependency)) + ); +} + +#[test] +fn precise_nested_regions_replay_borrowed_dependencies_without_hiding_full_dict_reads() { + let mut vm = Vm::new().unwrap(); + let globals = vm.new_dict().unwrap(); + vm.dict_set(globals, text("name"), text("value")).unwrap(); + let scope = vm.object_store_mut().begin_read_only(); + let token = vm.object_store().begin_read_tracking().unwrap(); + vm.object_store().dict_get_name(globals, "name").unwrap(); + let tracked = vm.object_store().end_read_tracking_precise(token).unwrap(); + assert!( + tracked + .accesses + .iter() + .any(|access| access.object == globals) + ); + for dependency in &tracked.dependencies { + assert!(vm.object_store().read_dependency_valid(dependency)); + } + let reads = vm.object_store_mut().end_read_only_precise(scope).unwrap(); + vm.dict_set(globals, text("other"), Value::Nil).unwrap(); + assert!( + reads + .dependencies + .iter() + .all(|dependency| vm.object_store().read_dependency_valid(dependency)) + ); + let scope = vm.object_store_mut().begin_read_only(); + vm.dict_items(globals).unwrap(); + let reads = vm.object_store_mut().end_read_only_precise(scope).unwrap(); + vm.dict_set(globals, text("third"), Value::Nil).unwrap(); + assert!( + reads + .dependencies + .iter() + .any(|dependency| !vm.object_store().read_dependency_valid(dependency)) + ); + vm.release(globals).unwrap(); + assert_eq!(vm.object_count(), 0); +} diff --git a/crates/objects/src/README.md b/crates/objects/src/README.md index a46942c..9b1969c 100644 --- a/crates/objects/src/README.md +++ b/crates/objects/src/README.md @@ -25,3 +25,5 @@ Heap、ObjectRef 字段、对象头计数和可变容器字段不向包外开放;公开代码读取接口不允许改写已登记的常量和托管边。检查入口见 [tests](../tests/README.md)。返回 [objects](../README.md)。 object.rs提供AwaitPoll与ObjectPayload::poll_await;instruction.rs/code.rs验证Await操作数/栈效果,effects.rs将其视为不能证明只读,error.rs承载等待失败/取消。契约见docs/runtime/bytecode.md。 + +heap.rs的ReadDependency/ReadSet/TrackedReads记录借用观察,store.rs暴露精确结束/验证,store_builtins.rs按名读取与字典种类验证保留保守API;types.rs/effects.rs使用按名注解/全局解析。 diff --git a/docs/README.md b/docs/README.md index f99239c..42535f7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,3 +24,5 @@ 目录入口:[architecture](architecture/README.md)、[runtime](runtime/README.md)、[operations](operations/README.md)、[contributing](contributing/README.md)。宿主部署、文件信息和数据库正文已移至 Hestia,命令行与实际输出报告已移至 Lyra;本仓库不保留重复正文。研究资料仍在忽略的 work/research,不提交。 Await入口:语法见runtime/frontend.md,名称与发码见runtime/compiler.md,等待/恢复与所有权见runtime/bytecode.md,宿主协议见runtime/objects.md。 + +按名全局依赖、缺失键遮蔽与兼容保守读取见runtime/native-calls.md的精确只读观察章节。 diff --git a/docs/runtime/bytecode.md b/docs/runtime/bytecode.md index 374a2ea..ff48e72 100644 --- a/docs/runtime/bytecode.md +++ b/docs/runtime/bytecode.md @@ -202,3 +202,5 @@ LoadAttr 对实例自有属性返回原值;缺失时沿类型父链找方法 `Await`(opcode 30,无参数)把栈顶 awaitable 换成结果,验证栈效果为1入1出。`ObjectPayload::poll_await()` 是非阻塞、无副作用的宿主协议,默认不支持;返回 Pending 或 Ready(借用 Value),也可返回 AwaitFailed(String)/AwaitCancelled。引擎验证 Ready 句柄并先retain结果,再释放原操作数;不可信宿主仍需遵守借用与非阻塞契约。Await 不被保守效果分析证明为只读,运行时也拒绝只读阶段。 在独立coroutine中,Pending保持已求值的栈顶、当前帧和返回契约,返回CoroutineProgress::Waiting { awaitable, instructions };awaitable是由暂停帧保活的借用身份。宿主等待条件满足后再次resume,仅重查同一个Await,不重放操作数表达式、前缀写入或IO请求。每次实际执行Await计入同一硬预算;宿主不应对未就绪对象反复resume来轮询。完成结果与错误沿普通执行/清理路径传播。非coroutine调用允许立即Ready的await,Pending则明确报错,不阻塞线程。调度、取消传播和循环等待检测属于宿主;本引擎不依赖Tessera Task。 + +LoadGlobal按文本名字分别观察函数globals及缺失时的captured builtins,不因无关全局写入而失效。可恢复只读Complete新增dependencies,reads保留兼容保守列表;精确验证/所有权见native-calls.md。 diff --git a/docs/runtime/native-calls.md b/docs/runtime/native-calls.md index e7e3b12..acc159d 100644 --- a/docs/runtime/native-calls.md +++ b/docs/runtime/native-calls.md @@ -113,3 +113,6 @@ Delegated 在替换兼容中视为未知整体效果,与源码未知效果一 ContextNativeFunction::implementation() 只借用当前具体宿主实现,不执行或复制载荷,也不改变捕获/签名的托管边。NativeCallable 继承Any(原有static要求保持);宿主可据自己的实现类型/操作识别原生快速路径,不能只凭函数句柄或当前可变类型方法表认定原生身份。替换载荷后查询跟随新实现,旧类型查询返回None;宿主缓存仍须订阅函数对象版本变化。此接口不暴露可变借用,不替代原生类型/数量/效果检查。 + + +精确只读观察:end_read_only_precise返回ReadSet,兼容objects列表并提供ReadDependency;end_read_tracking_precise返回区域的ReadAccess与相同观察。Object依赖验证对象版本;DictionaryKind只验证存活/字典载荷;Name验证文本键的存在与值身份/表示。缺失名字也被记录,因此后续全局遮蔽内建名会失效;相同值删除/重建后可恢复有效,这是值观察而非“发生过写入”的通知。dict_get_name用于全局/注解/__builtins__名字查询,普通dict_get、dict_items和其他内容读取仍保守依赖整个对象。read_dependency_valid在只读区域内检查时会重记相同观察,使缓存命中仍向外传播依赖。所有对象句柄(包括Name中的Value::Object)均借用,不增加GC根;立即字符串/数字保留比较快照,值不写回业务对象。现有end_read_only/end_read_tracking/details仍返回保守对象列表,不自动替调用方放宽缓存。类型验证字典通过DictionaryKind观察,不把只验证载荷种类误当读取所有条目。