diff --git a/crates/core/tests/execution.rs b/crates/core/tests/execution.rs index 4c3567b..ffb1205 100644 --- a/crates/core/tests/execution.rs +++ b/crates/core/tests/execution.rs @@ -1,5 +1,6 @@ //! 通过手工指令验证 VM 求值、根生命周期及暂停行为,测试框架直接调用,无需源码解析器。 //! op/simple/make_code 统一构造已验证代码;错误编码用 EndorCode 直接检验构造阶段拒绝。 +//! 部分协议场景只核对局部结果/计数,保留的测试根由 VM 析构收尾;显式清理场景另断言失效或空堆。 use std::any::Any; use std::sync::Arc; @@ -26,8 +27,11 @@ fn text(value: &str) -> Value { /// 测试辅助,编码并验证指令/常量/布局后分配代码拥有根;失败直接使测试失败。 fn make_code( vm: &mut Vm, + // 逻辑指令借用输入;编码器处理扩展前缀,代码构造器检查索引、跳转和栈高。 instructions: &[Instruction], + // 常量表示移入代码,含对象时只有成功托管分配才建立内部强边;不消耗调用方对象根。 constants: Vec, + // 参数/局部/Cell/名称布局随代码移入,执行帧按它分配和寻址。 layout: CodeLayout, ) -> ObjectRef { vm.new_code(EndorCode::from_instructions(instructions, constants, layout).unwrap()) @@ -151,7 +155,7 @@ fn opt_in_assignment_keeps_alias_identity_ordinary_values_and_root_accounting() fn failed_opt_in_assignment_preserves_target_and_cleans_execution_roots() { // 独立 VM 隔离对象计数/全局绑定,清理断言只针对本场景。 let mut vm = Vm::new().unwrap(); - // 共享目标以 1 初始化,同时另由 alias 持有;赋值后身份应保持。 + // 共享目标以 1 初始化,globals.value 稍后持有它;拒绝新值后身份及原内容都应保持。 let old = vm.allocate(SharedReference(AtomicUsize::new(1))).unwrap(); // 以哨兵值 99 触发校验拒绝,不允许污染旧目标值。 let rejected = vm.allocate(SharedReference(AtomicUsize::new(99))).unwrap(); @@ -505,7 +509,7 @@ fn argument_count_and_foreign_argument_failures_do_not_retain_inputs() { let mut other = Vm::new().unwrap(); // 异堆参数在执行源码之前拒绝,不改变当前函数计数。 let foreign = other.new_object().unwrap(); - // 保存调用前计数,结果交付多一根,归还结果后必须恢复。 + // 保存函数调用前计数;异堆实参预检失败后不应留下临时函数执行根。 let before = vm.ref_count(function).unwrap(); assert_eq!( vm.call(function, &[Value::Object(foreign)]), @@ -573,7 +577,7 @@ fn native_return_of_a_temporary_argument_is_retained_before_inputs_are_popped() let mut vm = Vm::new().unwrap(); // 函数执行环境的拥有根,函数也经载荷强边持有该字典。 let globals = vm.new_dict().unwrap(); - // 创建源码/原生函数拥有根,代码/全局/默认值内部边由分配协议另计。 + // 分配旧式原生 echo 根,本载荷没有源码代码/全局字段;globals 随后为它建立值边。 let function = vm .allocate(EndorNativeFunctionObject::new("echo", echo)) .unwrap(); @@ -599,7 +603,7 @@ fn native_return_of_a_temporary_argument_is_retained_before_inputs_are_popped() ); // 执行结果拥有根可跨越代码与全局生命周期。 let result = vm.execute(code, globals).unwrap(); - // 移除代码常量边后,返回图必须自己保留所需对象;不是只靠旧帧保活。 + // 包装代码的常量表为空;释放代码后,临时字典必须仅凭独立调用结果根继续存活。 vm.release(code).unwrap(); // 归还环境测试根,临时执行函数已清理,结果不能依赖其持续存在。 vm.release(globals).unwrap(); @@ -620,7 +624,7 @@ fn native_failure_unwinds_temporary_roots_and_keeps_execution_locations() { let mut vm = Vm::new().unwrap(); // 函数执行环境的拥有根,函数也经载荷强边持有该字典。 let globals = vm.new_dict().unwrap(); - // 创建源码/原生函数拥有根,代码/全局/默认值内部边由分配协议另计。 + // 分配恒定报错的旧式原生回调根,环境另持函数边;后面的源码包装器负责 Call 与回溯位置。 let function = vm .allocate(EndorNativeFunctionObject::new("fail", fail)) .unwrap(); @@ -703,9 +707,9 @@ fn recursion_uses_explicit_frames_and_unwinds_at_the_frame_limit() { assert_eq!(vm.ref_count(function).unwrap(), roots); // 调用前/后按场景归还测试函数根;全局字典可能仍持有函数内部边。 vm.release(function).unwrap(); - // 移除代码常量边后,返回图必须自己保留所需对象;不是只靠旧帧保活。 + // 归还代码测试根;递归函数仍持代码边,需随函数/环境无外根环一起回收。 vm.release(code).unwrap(); - // 归还环境测试根,临时执行函数已清理,结果不能依赖其持续存在。 + // 归还环境测试根后只剩 globals→function→globals 及代码边,显式 GC 应回收三个对象。 vm.release(globals).unwrap(); assert_eq!(vm.collect_cycles(), 3); } @@ -874,7 +878,7 @@ fn captured_argument_cells_keep_their_contents_after_the_frame_returns() { .unwrap(); // 参数对象有测试根,帧初始化提升 Cell 时另建立内容强边。 let value = vm.new_string("captured").unwrap(); - // 函数把已有参数/默认值作为结果,身份不变但结果仍取得独立拥有根。 + // LoadClosure 返回新建的参数 Cell,并非原参数字符串;结果根保活 Cell,Cell 内部边再保活参数。 let returned = vm.call(function, &[Value::Object(value)]).unwrap(); // 归还原参数测试根,返回的 Cell 内容边仍须保活它。 vm.release(value).unwrap(); @@ -2010,7 +2014,7 @@ impl ObjectPayload for AwaitGate { fn kind_name(&self) -> &'static str { "await-gate" } - /// Heap 分配、回收时遍历内部对象边;立即值没有托管引用,无需报告。 + /// Heap 分配载荷时据此登记对象边快照,回收沿已登记的边处理;立即值无需报告。 fn trace(&self, visit: &mut dyn FnMut(ObjectRef)) { // 只有对象值携带堆引用;必须报告这一边,使测试释放原根后结果仍存活。 if let Value::Object(reference) = self.value {