编译器内部原理

让 Perry 快速运行的关键设计决策

01NaN-Boxing

值以 64 位浮点数存储,使用特殊位模式表示指针,实现无运行时开销的联合类型。这使得 (string | number)[] 能够高效工作。

通过将类型信息直接编码在 IEEE 754 NaN 有效载荷位中,Perry 无需使用标记联合或装箱值。单个 64 位字可以表示任何 JavaScript 值类型——数字使用其自然表示,而字符串、对象和其他堆分配值使用落在 NaN 范围内的指针位模式。

02Monomorphization

泛型在编译时进行特化,与 Rust 相同。每次类型实例化都生成优化后的代码,消除运行时类型检查开销。

当您编写 Array'<'number'>' 和 Array'<'string'>' 时,Perry 会生成两个独立的、完全优化的实现。这意味着数组对数字的操作使用直接的机器算术——没有类型守卫,没有动态分派,没有装箱。

03Static Dispatch

没有虚表。方法调用在编译时解析,支持直接函数调用和内联优化。

传统 OOP 运行时使用虚表进行方法解析,每次调用都增加一层间接。Perry 在编译期间静态解析所有方法调用,将接口方法调用转换为直接跳转。这也释放了激进的内联——小方法通常直接折叠到调用点。

04Zero-Cost Abstractions

TypeScript 类、接口和泛型编译为高效的原生代码,无运行时表示开销。

TypeScript 的类型系统仅存在于编译时——Perry 将此贯彻到底。接口不产生任何运行时代码。类层次结构被扁平化。泛型约束被解析为具体类型。编译后的二进制文件仅包含实际逻辑,没有解释器通常携带的抽象机制。