cilly-vm-cpp 重构复盘

23 阅读2分钟

0. 重构背景

cilly-vm-cpp 已从“功能可跑”进入“架构可持续”阶段。
本轮重构目标不是新增功能,而是降低耦合、提升扩展性,并保证行为不回归。

本次复盘按阶段组织,记录每一阶段的:

  1. 问题定义
  2. 关键改动
  3. 验证结果
  4. 阶段收益

1. 阶段一:SRP(职责拆分)

1.1 问题定义

改造前 VM 与栈模块职责混杂:

  1. StackStats 同时承担栈存储和统计逻辑。
  2. VM 暴露 PushCount/PopCount/Depth/MaxDepth 等统计 API。
  3. test hook 逻辑与 VM 执行路径耦合。

结果是:改统计会牵动执行核心,维护成本高。

1.2 关键改动

  1. 栈模块瘦身与更名
    • StackStats -> VmStack
    • stack_stats_test -> vm_stack_test
  2. 观察者机制引入
    • IVmObserver
    • VmStackObserver
  3. test hook 事件化
    • TestEmit/NotifyTestEmit
    • 测试迁移为 VmHookObserver + AddObserver
  4. Bazel 依赖修复
    • 清理 //src/frontend:frontend 残留依赖
    • 统一 //src:cilly_core 收口

1.3 验证结果

bazelisk test //tests:"all" --test_output=errors

结果:38/38 通过

1.4 阶段收益

  1. VM 主流程更轻,职责更清晰。
  2. 统计与测试钩子改为可插拔能力。
  3. 构建图更稳定,排障成本明显下降。

2. 阶段二:DIP(依赖倒置)

2.1 问题定义

阶段一后,VM 虽已职责更清晰,但仍直接依赖 GC 具体实现,典型表现:

  1. VM 直接感知具体 GC 类型。
  2. roots 扫描与收集调用存在具体类型暴露。
  3. 对象创建分配细节泄漏到 VM 执行路径。

2.2 关键改动

  1. 抽象端口拆分
    • IGcPort:收集、root 管理、堆预算、对象工厂
    • IMarkSink:统一 Mark(GcObject*) 能力
  2. Collector 适配抽象
    • Collector : public IGcPort, public IMarkSink
    • Collect(...) 对外抽象,内部桥接 CollectParallel(...)
  3. VM 去具体类型化
    • VM 持有 gc::IGcPort*
    • CollectGarbage()IGcPort::Collect(...)
    • TraceRoots(...) 改为 gc::IMarkSink&
    • 对象创建入口统一走 IGcPort 工厂能力

2.3 验证结果

bazelisk test //tests:"all" --test_output=errors

结果:38/38 通过

2.4 阶段收益

  1. VM 依赖抽象而非具体实现,DIP 落地。
  2. GC 细节从 VM 指令主流程中继续收敛。
  3. 为后续 OCP(对象创建扩展、前端扩展)打下接口基础。

3. 当前状态总览

截至当前,重构已完成两阶段闭环:

  1. SRP 完成:执行、统计、测试钩子解耦。
  2. DIP 完成:VM 与 GC 之间完成抽象层隔离。
  3. 行为稳定:全量测试持续通过(38/38)。

4. 后续计划(暂缓第三阶段)

按当前决策,第三阶段(OCP)暂不进入。
后续可按优先级择机推进:

  1. 对象创建工厂继续细化,进一步减少 VM 分支增长。
  2. 前端 Generator/AST 访问者化,降低新增语法时的改动面。
  3. 注释与文档持续清理,保持设计意图与实现一致。