正在查看这个V8 设计文档,其中有一个部分Constant Pool Entries
它说
\n\n\n常量池用于存储堆对象和小整数,这些对象和小整数在生成的字节码中作为常量引用。\n
\n
\n\n...小整数和强引用的奇怪类型\xe2\x80\x99s 有字节码可以直接加载它们,并且不会进入常量池。
\n
所以我很困惑:小整数是否被合并?
\n我的理解是,如果sizeof(int) < sizeof(int *)- 因为只复制实际整数而不是复制指向常量池中整数的指针更便宜,所以不值得池化小整数。此外,保存整数的变量可以优化为直接存储在 CPU 寄存器中,并跳过首先在内存中分配。
另外,它们位于 V8 堆还是堆栈上?我的理解一直是 smis 只是在堆栈上分配的立即值,而不是在堆上分配的指针+整数。另外,如果您使用 chrome devtool 拍摄堆快照,则无法在堆快照中找到 smis - 只有堆编号(例如大整数或双精度(如 3.14))位于堆上,直到我看到这篇文章https://v8.dev/blog/pointer -压缩#v8 中的值标记
\n\n\nV8 中的 JavaScript 值都表示为对象并分配在 V8 堆上,无论它们是对象、数组、数字还是字符串。这允许我们将任何值表示为指向对象的指针。
\n
现在我很困惑 - smis 也分配在堆上吗?
\nV8 开发者在这里。
小整数是否被合并?
他们不是(至少现在不是)。也就是说,这是一个很小的实现细节,可以通过任何一种方式完成:完全可以使用 Smis 的常量池。我想,之所以做出为 Smis 构建特殊机制(而不是重用通用常量池)的决定,是因为事实证明,这样会更高效。
如果以下情况,则不值得汇集小整数
sizeof(int) < sizeof(int *)
细节有所不同( Smi 不是int,并且常量池槽是通过索引而不是 C++ 指针引用的),但这种推理确实朝着正确的方向发展:避免间接可以节省时间和内存。
smis 也分配在堆上吗?
是的,所有内容都分配在堆上。堆栈仅对临时(且足够小的)事物有用;这很大程度上与事物的类型无关。
Smis 的“技巧”是它们不存储为单独的对象:当您有一个引用 Smi 的对象时,例如let foo = {smi: 42},则可以对值42进行 smi 编码并直接存储在“foo”对象内(而如果值为42.5,则该对象将存储指向单独的“HeapNumber”的指针)。但由于对象在堆上,Smi 也在堆上。
@丹尼尔克鲁兹
我的理解是,恒定的小整数被汇集在一起。可变的小整数则不然。
没有。源代码中出现的任何文字都是“常量”。无论您使用let还是const用于变量都与此无关。
| 归档时间: |
|
| 查看次数: |
451 次 |
| 最近记录: |