V8 指针压缩机制
在 64 位 V8 中,很多 JavaScript 值都以 tagged value 形式存放。若全部按 64 位保存,会明显增加对象字段、元素槽和属性槽的内存成本。Pointer Compression 的目标就是在不改变语义的前提下,降低这部分存储开销。
核心思路¶
指针压缩不是把“所有地址都变成 32 位”,而是把大量 tagged value 以 32 位紧凑表示写入内存,使用时再恢复为可计算的 64 位形式。
它依赖一个前提:相关堆对象位于可由 32 位偏移描述的 4GB 范围内。
tagged value 简化理解¶
V8 中常见的 tagged value 主要有两类:
Smi:小整数,直接编码在值里HeapObject:指向堆对象的引用(压缩后保存为可恢复地址的表示)
常见调试语义里,最低位 0 更接近 Smi,1 更接近对象引用;但这只适用于 tagged value 语义,不等于任意 C++ 指针字段都可这样解释。
压缩后形态(示意)¶
w 表示 strong/weak 等附加标记位。对象引用保存的是压缩表示,Smi 仍是内联整数编码(更接近 int31)。
两个常见误区¶
- 误区 1:对象地址只剩 32 位
实际上压缩的是存储表示,运行时会解压为 64 位再参与解引用和计算。 - 误区 2:V8 只有 4GB 内存
4GB 约束的是压缩表示依赖的地址窗口,不是整个进程的总可用内存。