工程实践 Max Bernstein 2026/08/13
本文介绍了一种在编译器中间表示(IR)中实现 canonicalize 传递的方法,用于通过类型保护重写合并冗余的 GuardType 指令。作者首先描述了一个块局部的版本,该版本在每个基本块内重映射操作数,使后续的常量折叠能消除多余的检查。随后,作者基于支配树实现了全局版本,通过在支配树中沿支配者向下级联重写来扩大优化范围,并讨论了慢速但易于验证的实现策略。文章进一步扩展该传递,当块是条件分支的目标时,在 rewrite_map 中预先填入条件变量的真假常量,使分支体得以了解其条件值,从而简化 30k_ifelse 等基准中的分支链。作者还提到该传递可能需要常量驻留来保证幂等性,并说明了其依赖 SSA 最小化传递的效果。文章以具体代码和 PR 为证据,展示了编译器优化开发中的工程取舍与实证验证。
推荐收录,因为文章详细记录了一个现实编译器中的优化实现过程,既有算法伪代码,又有对支配树、SSA 形式、常量驻留等底层概念的透彻解释。编译器开发者或编程语言研究者可以从中学习如何设计传递以利用支配关系传播类型信息,以及如何在正确性和性能之间做工程取舍。文中所探讨的块局部与全局重写级联技术,以及条件分支信息播种方法,均具有较强的可迁移性。
技术文章 Max Bernstein 2026/08/07
文章以图三着色为例,从 Goldreich 等原论文的 Protocol 4 出发,用 Python 代码展示零知识证明的交互式流程。作者实现颜色置换、Nonce 加盐哈希锁定、随机边挑战和校验,解析单轮协议逻辑。然后讨论多轮重复的概率保障,并简要介绍如何将协议推广到数独和其他 NP 完全问题。文中还提供客户端/服务器端的交互式演示,指出该方法在实际大数分解等场景中因图规模过大而存在实践限制。整体面向计算理论和密码学爱好者,强调可运行代码与学术论文的对应关系。
推荐收录,因为文章将经典零知识证明协议从论文转化为可运行代码,完整保留原协议中的置换、Nonce 和哈希锁定等关键设计,并提供概率分析和交互式演示。适合对密码学、计算复杂性或交互式证明感兴趣的学生和工程师,可作为理解 ZKP 原理和实现 NP 完全问题零知识证明的入门参考。文中对归约方法的讨论也提示了该技术的实际边界与迁移思路。
技术文章 Max Bernstein 2026/07/28
文章详细介绍了 Ruby 的 ZJIT 编译器中内联器(inliner)如何通过方法内联优化块(block)调用,从而提升性能。作者首先回顾了 Ruby 解释器中块的工作机制,随后解释 JIT 编译器如何通过类型特化来优化方法调用,并指出核心库方法(如 Array#each)因多态块调用导致优化困难。ZJIT 采用将 callee 的代码内联到 caller 中的方式,利用调用上下文将动态的 invokeblock 转换为直接的块调用和循环,消除了间接调用开销。文章展示了内联前后 HIR 的变化与微基准测试结果(如 cfunc_itself 达到 35 倍加速),并说明当前块内联尚未完全实现,内联阈值等参数仍在调优。适合对编译器设计、JIT 优化和 Ruby 运行时性能感兴趣的读者。
本文深入剖析了 ZJIT 内联器的设计动机、实现细节和实际收益,通过具体示例和基准数据展示了如何解决动态语言中块调用的优化难题。它对编译器开发者、语言虚拟机工程师和关注 Ruby 高性能优化的从业者具有直接的参考价值,其中基于调用上下文的代码重组思路也可迁移到其他 JIT 系统。
技术文章 Max Bernstein 2026/06/03
这篇文章系统梳理了动态语言 JIT 和多种编译器中的内联启发式,重点讨论“何时内联”比“如何内联”更难。作者从代码体积、编译时延迟、缓存压力、递归、调用深度、调用频率、调用上下文和 profile 传播等维度,比较了 Cinder、PyPy、V8、JavaScriptCore、SpiderMonkey、HotSpot、.NET、Dart、ART、HHVM 等实现差异,并补充了机器学习、部分内联和 AOT 信息辅助等研究方向。文章的结论是:内联本质上是一个全局收益与局部预算之间的权衡问题,启发式设计必须结合目标运行时、可观测性和分层编译策略。
推荐收录,因为它不是泛泛而谈“内联能提速”,而是把多个真实编译器/JIT 的决策规则、预算约束和调用上下文处理方式放在一起比较,长期参考价值很高。对做编译器、语言运行时或性能优化的读者来说,这篇文章能直接提供可迁移的启发式设计框架和调参视角。
技术文章 Max Bernstein 2026/06/01
这篇文章记录了作者如何用 Z3 验证一段 JIT 生成的分支less 汇编条件,目标是证明 `FIXNUM_MIN / -1` 这一溢出特殊情况的判定与原始 C 逻辑等价。文章不仅说明了 Ruby fixnum 在二进制补码下的边界行为,还展示了如何把等价性证明转成“寻找反例”的 SMT 问题,并通过故意改错常量来验证脚本确实能抓到反例。
推荐收录,因为它把一个很具体的编译/JIT 边界 bug,抽象成了可复用的形式化验证流程,适合做低层代码正确性检查的参考。对做编译器、JIT、运行时或底层位运算逻辑的读者来说,这种“用 Z3 证明等价性”的方法具有很强的迁移价值。
技术文章 Max Bernstein 2026/05/12
文章围绕编译器中的 static single information form(SSI)展开,重点讨论“partial SSI”这一更轻量的实现路径:不必完整实现复杂的 into-SSI / out-of-SSI 算法,而是可以在 SSA 构建阶段、或借助优化阶段已有的支配式重写机制,逐步插入和消除类型细化节点。作者用动态语言 JIT 的例子说明如何根据分支条件、guard 和对象形态推导更精确的类型信息,并进一步利用这些信息消除冗余操作、提升优化效果。
推荐收录,因为它不是泛泛介绍 SSA/SSI,而是把抽象的中间表示理论落到可实现的编译器工程路径上,清楚说明了如何以较低复杂度获得可用的类型细化能力。文章还讨论了适用边界、与完整 SSI 的差异以及 JIT/动态语言场景中的实现权衡,对编译器和运行时开发者都有长期参考价值。
技术文章 Max Bernstein 2026/04/04
本文系统讲解了编译器中的 value numbering:先从 SSA 中“同形表达式是否可复用”的问题切入,说明它如何用于公共子表达式消除,并区分纯操作与带副作用操作。作者给出局部 value numbering 的实现思路:用哈希表为指令建立值号,遇到已存在的等价指令就用 union-find/Assign 形式替换,从而在单个基本块内消除重复计算。随后文章把问题推进到全局 value numbering,重点解释了为何必须借助支配关系而不是简单按块遍历,以及在分支、汇合和循环中 phi 节点为何需要特殊处理。文章还讨论了内存相关指令的失效与转发,例如 Load/Store forwarding、跨块的 kill set 管理,并对 Maxine、ART、V8、HotSpot 等实现做了对照。最后作者补充了统一哈希表、value partitioning、scoped hash map、JIT 场景中的强度削弱等相关方向,指出该方法对重复纯表达式很有效,但处理副作用和循环时需要额外的可用性与失效管理。
推荐收录:文章明确覆盖了 value numbering、SSA、dominators、phi 处理、内存失效与 load/store forwarding 等关键机制,并给出 Maxine 等真实实现片段作为直接证据。适合编译器、JIT 和程序优化读者参考,迁移价值在于可直接借鉴其“哈希表+支配关系+失效管理”的分析框架;主要边界是它对复杂内存建模与循环优化仍是概述性质。
工程实践 Max Bernstein 2026/03/27
文章围绕 Ruby JIT 实现 ZJIT 如何借助 Perfetto 做性能诊断展开,核心目标是把“侧退出栈计数”这类静态统计,升级为能看时间分布、调用栈和热点聚集位置的可视化追踪。作者先说明仅靠 --zjit-stats 只能知道退出原因数量,却难以定位它们发生在哪些 Ruby 方法中、集中在启动期还是稳态阶段,因此需要引入 trace。随后通过 Perfetto 的时间线和 SQL 接口,把 slice 与 args 表关联起来统计退出原因和顶层方法,直接找到了 ActiveRecord 相关的 shape/type guard miss 热点。实现部分展示了如何导出 trace、为何 JSON 格式会膨胀到 8GB,以及改用更紧凑的 FXT 二进制格式和采样后将体积降到约 100MB。文章也提到还可以继续追踪编译阶段、代码大小、失效、分配和 GC 等事件,但当前结论依赖采样与单次基准,适合做定位和直觉建立,不适合替代完整性能评测。
文章给出了从计数器到可视化 trace 的完整落地路径,并用真实 JIT 热点证明 Perfetto 能直接帮助定位 side-exit 归因。适合做编译器、运行时和性能排障的参考,尤其对需要把追踪数据转成可查询、可视化分析流程的工程场景有可迁移价值。
技术文章 Max Bernstein 2026/02/25
文章延续 Toy Optimizer 系列,讲作者如何为一个玩具编译器优化器构建模糊测试器,目标不是找崩溃,而是检出优化引入的语义错误。作者随机生成由 load、store 和 escape 组成的小程序,再用解释器在“无别名”和“完全别名”两种参数环境下执行,比较优化前后 heap 与逃逸结果是否一致。文中展示了这种不变量如何迅速暴露故意注入的错误:一旦去掉别名写回的关键逻辑,测试会几乎立刻失败并给出具体差异。作者也说明了局限性,例如只覆盖两种极端别名情况,且该等价定义不适用于会删除分配的优化。整体上,这是一个关于编译器优化测试、属性测试和语义 oracle 设计的实用案例。
推荐收录,因为文章给出了可复用的编译器优化 fuzzing 方案:随机程序生成、语义解释器和基于别名场景的正确性判定,而且能用最小反例迅速暴露优化错误。适合编译器、语言实现和测试工程读者参考;但要注意它的 oracle 依赖当前优化模型,不能直接套到会改变分配语义的场景。
技术文章 Max Bernstein 2026/02/16
文章延续 Toy Optimizer 系列,围绕加载/存储转发中的别名分析展开,先指出仅按偏移量划分 alias class 太粗,会把不同类型对象上同一偏移的访问误判为冲突。作者借鉴 type-based alias analysis,用类型层次树的前序/后序区间表示各 heap region,将“是否可能别名”转化为区间重叠查询,并在缺少类型信息时退化到 Any。随后又补充了对象来源、分配点、常量对象和已知内建函数副作用等更强的别名线索,用于局部保留或部分失效缓存的 heap 信息。文章还讨论了未知调用、逃逸对象与保守失效的边界,强调这种做法在 JIT 和受控语言中能以较低成本提升优化精度,但在通用 C-like 场景下需要更强的分析配合。
推荐收录,因为文章给出了从偏移量别名到类型层次 TBAA 的具体改造路径,还展示了与对象来源、内建副作用和未知调用的联动处理。适合做编译器、JIT 和语言运行时优化的参考,尤其对需要在精度与分析成本之间取舍的读者很有迁移价值。
技术文章 Max Bernstein 2026/01/22
文章讨论 ZJIT 在编译 Ruby 字节码时遇到的多入口控制流图设计难题。由于 Ruby 默认参数在调用时求值,编译器需要把默认参数逻辑放在被调函数内部,并同时支持解释器入口、JIT 入口和若干默认参数入口。作者展示了这种 HIR 设计如何让 SSA、RPO 遍历和 Cooper 风格支配树算法都变得别扭,因为图里不再存在唯一的起始块。文中系统比较了三种方案:保留特殊处理、合成超级入口块、或按入口复制整张 CFG,并说明复制方案虽然简单但会带来代码膨胀。最终更新里给出团队选择了 superblock/EBB 方案,接受了更复杂的 dominator 与 predecessor 处理,以换取更清晰的入口模型。文章的边界也很明确:结论主要适用于多入口 IR 设计,后续复杂分析仍需继续验证。
收录价值在于它不是泛泛谈“编译器设计”,而是拿真实的多入口函数 IR、支配树失配和三种可选方案做了具体权衡。适合编译器、语言运行时和 IR 设计读者参考,尤其是需要处理入口分裂、默认参数或多返回点的实现者。
技术文章 Max Bernstein 2025/12/30
文章系统梳理了 GDB 如何借助 JIT 接口恢复 JIT 代码的符号、函数名和行号信息,从而在断点、回溯和反汇编时避免大量“???”。作者先解释旧接口的工作流:JIT 在内存中生成一份包含 DWARF 的临时对象文件,再通过 __jit_debug_descriptor 和 __jit_debug_register_code 通知 GDB 读取。随后又介绍了新版自定义调试信息接口,说明 reader 需要实现的回调、匹配代码区间与帧信息的职责,以及目前各运行时的支持现状。文章还讨论了将 Linux perf map 复用到 GDB 的可行性、GDB JIT 链表导致的 O(n²) 问题,以及 GC/代码移动对符号稳定性的约束。整体来看,它不仅讲清了接口机制,也点出了工程实现中的性能与生命周期边界。
文中直接给出 GDB JIT 旧/新接口的调用链、reader 回调和典型坑位,是理解 JIT 调试基础设施的实用材料。适合做运行时、调试器或语言实现相关工作的读者参考,尤其能迁移到符号注册、代码生命周期管理和可观测性设计中。