0. 重构背景
cilly-vm-cpp 已从“功能可跑”进入“架构可持续”阶段。
本轮重构目标不是新增功能,而是降低耦合、提升扩展性,并保证行为不回归。
本次复盘按阶段组织,记录每一阶段的:
- 问题定义
- 关键改动
- 验证结果
- 阶段收益
1. 阶段一:SRP(职责拆分)
1.1 问题定义
改造前 VM 与栈模块职责混杂:
StackStats同时承担栈存储和统计逻辑。VM暴露PushCount/PopCount/Depth/MaxDepth等统计 API。- test hook 逻辑与 VM 执行路径耦合。
结果是:改统计会牵动执行核心,维护成本高。
1.2 关键改动
- 栈模块瘦身与更名
StackStats->VmStackstack_stats_test->vm_stack_test
- 观察者机制引入
IVmObserverVmStackObserver
- test hook 事件化
TestEmit/NotifyTestEmit- 测试迁移为
VmHookObserver + AddObserver
- Bazel 依赖修复
- 清理
//src/frontend:frontend残留依赖 - 统一
//src:cilly_core收口
- 清理
1.3 验证结果
bazelisk test //tests:"all" --test_output=errors
结果:38/38 通过。
1.4 阶段收益
- VM 主流程更轻,职责更清晰。
- 统计与测试钩子改为可插拔能力。
- 构建图更稳定,排障成本明显下降。
2. 阶段二:DIP(依赖倒置)
2.1 问题定义
阶段一后,VM 虽已职责更清晰,但仍直接依赖 GC 具体实现,典型表现:
- VM 直接感知具体 GC 类型。
- roots 扫描与收集调用存在具体类型暴露。
- 对象创建分配细节泄漏到 VM 执行路径。
2.2 关键改动
- 抽象端口拆分
IGcPort:收集、root 管理、堆预算、对象工厂IMarkSink:统一Mark(GcObject*)能力
- Collector 适配抽象
Collector : public IGcPort, public IMarkSinkCollect(...)对外抽象,内部桥接CollectParallel(...)
- VM 去具体类型化
- VM 持有
gc::IGcPort* CollectGarbage()走IGcPort::Collect(...)TraceRoots(...)改为gc::IMarkSink&- 对象创建入口统一走
IGcPort工厂能力
- VM 持有
2.3 验证结果
bazelisk test //tests:"all" --test_output=errors
结果:38/38 通过。
2.4 阶段收益
- VM 依赖抽象而非具体实现,DIP 落地。
- GC 细节从 VM 指令主流程中继续收敛。
- 为后续 OCP(对象创建扩展、前端扩展)打下接口基础。
3. 当前状态总览
截至当前,重构已完成两阶段闭环:
- SRP 完成:执行、统计、测试钩子解耦。
- DIP 完成:VM 与 GC 之间完成抽象层隔离。
- 行为稳定:全量测试持续通过(38/38)。
4. 后续计划(暂缓第三阶段)
按当前决策,第三阶段(OCP)暂不进入。
后续可按优先级择机推进:
- 对象创建工厂继续细化,进一步减少 VM 分支增长。
- 前端 Generator/AST 访问者化,降低新增语法时的改动面。
- 注释与文档持续清理,保持设计意图与实现一致。