Search code examples
javascriptv8

JavaScript: V8 question: are small integers pooled?


was looking at this V8 design doc where it has a section for Constant Pool Entries

it says

Constant pools are used to store heap objects and small integers that are referenced as constants in generated bytecode. and

... Small integers and the strong referenced oddball type’s have bytecodes to load them directly and do not go into the constant pool.

So I am confused: are small integers pooled or not?

My understanding is that it is not worth it pooling small integers if sizeof(int) < sizeof(int *) - because it is cheaper to just copy the actual integer instead of copying the pointer that points to the integer in the constant pool. Also variables that hold integers can be optimised to be stored directly in CPU registers and skip being allocated in memory first.

Also, are they located on the V8 heap or the stack? My understanding had always been that smis are just be the immediate values allocated on the stack instead of being a pointer + an integer allocated on heap. Also if you take a heap snapshot using chrome devtool you cannot find smis in the heap snapshot - only heap number such as big integers or double like 3.14 are on the heap until I saw this article https://v8.dev/blog/pointer-compression#value-tagging-in-v8

JavaScript values in V8 are represented as objects and allocated on the V8 heap, no matter if they are objects, arrays, numbers or strings. This allows us to represent any value as a pointer to an object.

Now I am just baffled - are smis also allocated on the heap?


Solution

  • V8 developer here.

    are small integers pooled or not?

    They are not (at least not right now). That said, this is a small implementation detail and could be done either way: it would totally be possible to use the constant pool for Smis. I suppose the decision to build special machinery for Smis (instead of reusing the general-purpose constant pool) was made because things turned out to be more efficient that way.

    it is not worth it pooling small integers if sizeof(int) < sizeof(int *)

    The details are different (a Smi is not an int, and constant pool slots are referenced by index rather than C++ pointer), but this reasoning does go in the right direction: avoiding indirections can save time and memory.

    are smis also allocated on the heap?

    Yes, everything is allocated on the heap. The stack is only useful for temporary (and sufficiently small) things; that's largely unrelated to the type of thing.

    The "trick" of Smis is that they're not stored as separate objects: when you have an object that refers to a Smi, such as let foo = {smi: 42}, then the value 42 can be smi-encoded and stored directly inside the "foo" object (whereas if the value was 42.5, then the object would store a pointer to a separate "HeapNumber"). But since the object is on the heap, so is the Smi.

    @DanielCruz

    What I understand [...] is that constant small integers are pooled. Variable small integers are not.

    Nope. Any literal that occurs in source code is "constant". Whether you use let or const for your variables has nothing to do with this.