Max Bernstein

RSS: https://bernsteinbear.com/feed.xml
Max Bernstein 的博客。

支持局部变量:Ruby ZJIT 编译器的 SSA 优化实践

ZJIT 团队在 VMIL 2026 发表论文,介绍 Ruby 新 JIT 编译器 ZJIT 如何将局部变量提升为 SSA 值。与 YJIT 等现有 Ruby JIT 不同,ZJIT 通过多轮全局和局部优化,把局部变量从内存读写转为 SSA 形式,解决了 Ruby 动态类型下局部变量编译的特殊挑战。
评论点赞收藏26 天前

Another partial SSI trick with canonicalize

After reading Chris Fallin’s aegraph post, new ZJIT contributor dak2 landed a block-local version of the canonicalize function in #16828. The pseudocode of the block-local canonicalize function looks ...
评论点赞收藏47 天前

零知识证明的极简实现:30行代码讲清图3染色协议

用30行Python代码实现图3染色的零知识证明交互协议,不依赖加密货币。证明方通过哈希加随机盐锁定颜色,验证方随机选边要求打开,重复m²轮使作弊概率趋近于零。 作者与Chris合作部署了可交互的网络演示,并扩展到数独等NP完全问题。
评论点赞收藏53 天前

ZJIT 的内联器带来显著收益

ZJIT 的 inliner 功能已启用,显著优化了 Ruby 程序中 block 的执行效率。文章通过 YARV 字节码分析展示了 inliner 如何减少 invokeblock 调用开销,并给出具体性能提升数据。 适合对 Ruby 虚拟机和 JIT 编译感兴趣的开发者阅读。
评论点赞收藏64 天前

PLDI 2026 参会手记:从 e-graph 教程到编译器优化的实战交流

作者记录了参加 PLDI 2026 的经历,重点在于技术社交与动手实践。文中提到在研讨会现场促成“自建 e-graph”教程,并与多位研究者深入探讨编译器优化、线性扫描寄存器分配及 Datalog 实现。 作者还分享了在 Ruby 中实现 Knuth-Bendix 补全时的具体踩坑细节。内容充满一线程序员的真实互动和技术探索过程,对关注编译器原理和学术社区互动的开发者有参考价值。
评论点赞收藏87 天前

内联启发式方法综述

Compilers, especially method just-in-time compilers, operate on one function at a time. It is a natural code unit size, especially for a dynamic language JIT: at a given point in time, what more infor...
评论点赞收藏117 天前

Checking Assembly with Z3

Short post today. New ZJIT contributor dak2 submitted a PR to fix an overflow bug in fixnum division in ZJIT. We did the division fine, but lied about the type of the result in the case of dividing FI...
评论点赞收藏120 天前

旅行笔记:RubyKaigi函馆之旅

I just got back from a three and a half week trip to Japan. It was the longest trip I have ever been on (aside from studying abroad in Germany, which felt different). I made the following wild circuit...
评论点赞收藏135 天前

编译器中的部分静态单信息形式(Partial SSI):动机、实现与权衡

<p>在编译器中,静态单一信息形式(SSI)是常见的扩展 静态单一转让表(SSA)。它由C. Scott Ananian在 1999年,他的硕士论文(PDF)1.</p><p>SSI通过查明事实,延长您现有的SSA中级代理 从你现有的程序中,将其具体化为路径依赖/流敏感 红外节点。这听起来可能很复杂,但至少基本想法很漂亮 自然的。我在《我谈论IR时的谈话》中稍微谈过,这里我会更深入地复述,先从一些开始 激励人的例子。请考虑这个明显牵强的例子:</p><p>我们应该能从比较中学到,在国际关系的某些分支中, v0为阳性。在该区域,我们可以添加一个新的IR指令v2,使得 它直接将这些知识附加在指令的类型字段中(耶, 稀疏!)然后将v0的使用重写为v2。</p><p>因为我们已经做到了,我们的(虚构的)优化规则去除了 已知正整数的绝对值可以生效,我们可以删除 呼唤绝对值。优化,太棒了!</p><p>但至少对我来说,还有几个问题:</p><p>1. 编译器流水线中何时何地插入和移除这些类型 改进?</p><p>2. 我们是否需要在每个条件句后进行精炼?</p><p>3. 我们是否需要实现整个进入SSI和退出SSI的算法,从 那些看起来很复杂的文件?</p><p>我们将从编译器流水线开始逐一介绍。</p><p>我们什么时候插入类型细化?</p><p>最初的SSI论文开头是(我记得是这样?)SSA形式及位置 基于条件句的新精炼节点。说实话,我并没有怎么尝试过 很难,但进入SSI的算法看起来复杂且有点重。作为 奖励是你获得“线性”进入SSI…</p>
评论点赞收藏141 天前

值编号:用于消除公共子表达式的编译器优化技术

<p>欢迎重返编译器的世界。今天,我们将探讨“值编号”这一概念——它与 SSA 有些相似,但又有所不同。</p><p>静态单赋值(SSA)为变量赋予了名称:每个表达式都有一个唯一的名称,而每一个名称都对应着且仅对应一个表达式。通过这种转换,我们可以将如下程序:</p><p>其中变量 x 在程序代码中被多次赋值,转化为如下形式:</p><p>其中对 x 的每一次赋值,都被替换为对一个全新的、全新的名字的赋值。</p><p>这种方法非常出色,因为它清晰地揭示了两个 x + 1 表达式之间的差异:尽管它们在文本上看起来几乎相同,但计算结果却截然不同——第一个表达式计算出 1,而第二个表达式则计算出 2。<br><br>在这个例子中,我们无法直接将某个变量的值代入到表达式中并重复使用 x + 1 的值,因为这两个表达式的 x 值是不同的。</p><p>那么,如果我们在 SSA 中看到两条“在文本上”完全相同的指令,会怎样呢? 这听起来比非 SSA 的方式要更有前景,因为经过 SSA 形式的转换,原本复杂的程序状态得到了极大的简化。 那么,我们什么时候才能重新利用这些结果呢?</p><p>识别那些在编译时已知,但在运行时总是会产生相同值的指令,就称为“值编号”。</p><p>消除公共子表达式</p><p>为了更好地理解值编号,我们先在上述 IR 片段的基础上,新增两条指令:v3 和 v4。</p><p>在新片段中,v3 与 v1 的外观完全一致:都是将 v0 与 1 相加。假设我们的加法运算是一种理想的数学运算,那么我们完全可以复用 v…</p>
评论点赞收藏179 天前

为玩具优化器编写的模糊测试器

Another entry in the Toy Optimizer series. It’s hard to get compiler optimizers right. Even if you build up a painstaking test suite by hand, you will likely miss corner cases, especially corner case...
评论点赞收藏217 天前

基于类型的别名分析在玩具优化器中的应用

<p>在中,又一项新成果。</p><p>上一次,我们是在玩具优化器的背景下实现了“加载-存储转发”机制。我们成功地在编译时对从堆中读取和向堆中写入的结果进行了缓存!</p><p>我们特别注意对象别名问题:根据读取/写入所引用的偏移量,我们将堆信息划分为不同的别名类。 这样一来,即使我们不知道对象 a 和 b 是否存在别名关系,至少也能确定不同偏移量永远不会发生别名(前提是我们的对象不会重叠, 且内存访问发生在字大小的槽位上)。这是一种较为粗略的启发式方法。</p><p>幸运的是,在编译时我们往往能获得比偏移量更丰富的信息,因此应当充分利用这些信息。 我在脚注中提到过,我们还可以利用类型信息来改进别名分析。 在这篇文章中,我们将引入一种轻量级的基于类型别名分析(TBAA)技术(PDF)。</p><p>表示类型</p><p>我们再次回到菲利普·皮兹洛的领域——具体来说是。在我们的实现中,我们将沿用上一篇文章中介绍的分层堆效应表示法; 不过,如果你已经有自己独特的类型表示法,也可以直接使用。</p><p>这种表示法通过类型将堆划分为互不相交的区域。 例如,我们可以假设数组对象与字符串对象之间不存在重叠关系。 链表指针绝不会与整数指针发生别名关系。 因此,我们可以分别对它们进行推理和处理。</p><p>然而,有时我们并不能获得完美的类型信息。 如果某种语言中存在一个用于所有对象的“Object”基类,那么“Object”堆就可能与“Array”堆产生重叠…</p>
评论点赞收藏226 天前

多入口CFG设计难题

Background and bytecode design The ZJIT compiler compiles Ruby bytecode (YARV) to machine code. It starts by transforming the stack machine bytecode into a high-level graph-based intermediate represe...
评论点赞收藏251 天前

GDB JIT接口:调试JIT编译代码

本文详细介绍了如何在GDB中调试JIT编译代码的两种接口:旧方法需要生成ELF/Mach-O等可执行文件并嵌入DWARF调试信息,而新方法允许自定义二进制格式。 文章还分析了实现难点,如GC稳定性、符号表维护以及性能问题(O(n²)复杂度),并讨论了与Linux perf map接口的潜在整合方案。内容技术性强,对开发者有实用价值。
评论点赞收藏257 天前

如何为perf/samply标注JIT代码

本文介绍了如何在YJIT/ZJIT和samply中使用perf映射接口来标注JIT代码,适用于Linux和macOS。作者提供了一个具体的实现示例,并解释了如何生成函数映射文件以便在perf或samply记录中显示JIT帧。 文章还指出了当前实现的一个小错误,建议使用{:x}而不是{:#x}来避免输出0x前缀。
评论点赞收藏266 天前

GDB JIT 接口详解:从原理到实践

深入解析GDB的JIT调试接口,对比传统的DWARF对象生成方式与新的自定义调试信息读取器接口。文章梳理了V8、.NET、QEMU等主流运行时对GDB JIT的支持实现,指出了旧接口的O(n^2)性能瓶颈和GC移动问题,并探讨了复用Linux perf map接口的可能性及作者实现的插件。
评论点赞收藏274 天前

ZJIT现已在 Ruby 4.0 中可用

Originally published on Rails At Scale. ZJIT is a new just-in-time (JIT) Ruby compiler built into the reference Ruby implementation, YARV, by the same compiler group that brought you YJIT. We (Aaron ...
评论点赞收藏280 天前

Toy Optimizer中的加载与存储转发

Another entry in the Toy Optimizer series. A long, long time ago (two years!) CF Bolz-Tereick and I made a video about load/store forwarding and an accompanying GitHub Gist about load/store forwardi...
评论点赞收藏280 天前

登录芦苇

登录后关注作者、收藏内容和参与讨论。