JAVASCRIPT:V8问题:小整数是否共享?

2022-07-21 00:00:00 javascript v8

正在查看V8 design doc,其中有一个Constant Pool Entries

部分

上面写着

常量池用于存储堆对象和小整数,这些对象和小整数在生成的字节码中作为常量引用。 和

.小整数和强引用的奇数类型具有直接加载它们的字节码,并且不进入常量池。

所以我很困惑:小整数是否汇集在一起?

我的理解是,如果sizeof(int) < sizeof(int *),将小整数放入池中是不值得的,因为只复制实际的整数比复制指向常量池中整数的指针更便宜。此外,保存整数的变量可以优化为直接存储在CPU寄存器中,并跳过首先在内存中分配的操作。

另外,它们位于V8堆还是堆栈上?我的理解一直是,SMI只是堆栈上分配的立即值,而不是指针+堆上分配的整数。此外,如果您使用Chrome DevTool拍摄堆快照,则在堆快照中找不到SMI-只有大整数或双精度的3.14之类的堆编号在堆上,直到我看到这篇文章https://v8.dev/blog/pointer-compression#value-tagging-in-v8

V8中的JAVASCRIPT值被表示为对象,并在V8堆上分配,无论它们是对象、数组、数字还是字符串。这允许我们将任何值表示为指向对象的指针。

现在我就不明白了-SMI也在堆上分配吗?


解决方案

V8开发人员此处。

小整数是否合并?

他们不是(至少现在不是)。也就是说,这是一个很小的实现细节,可以通过任何一种方式来完成:完全可以使用SMI的常量池。我认为,决定为SMI构建特殊的机器(而不是重用通用常量池)是因为这样做会更有效率。

如果sizeof(int) < sizeof(int *)

,则不值得将小整数放在一起

细节不同(SMI不是int,常量池槽由索引而不是C++指针引用),但这个推理确实是正确的:避免间接访问可以节省时间和内存。

是否也在堆上分配SMI?

是的,所有内容都在堆上分配。堆栈仅对临时的(且足够小的)对象有用;这在很大程度上与对象的类型无关。

SMI的诀窍在于它们不作为单独的对象存储:当您有一个引用SMI的对象(如let foo = {smi: 42})时,可以对42值进行SMI编码,并将其直接存储在Foo";对象内(而如果该值为42.5,则该对象将存储一个指向单独&q;HeapNumber&q;的指针)。但由于对象在堆上,所以SMI也在堆上。

@DanielCruz

我所理解的[...]是恒定的小整数被汇集在一起。变量小整数不是。

没有。源代码中出现的任何文字都是";常量。变量使用let还是const与此无关。

相关文章