javascriptmemorymemory-managementv8javascript-engine

Where primitives inside objects are actually stored


When i Declare an Object and inside of that object i made a property that holds a primitive value

so in this Example

const foo =  {
  firstName: 'bar'
}

where the bar actually stored is it points the specific memory on the stack then and the value in there or it stored as it is in a some address in the heap


Solution

  • (V8 developer here.)

    As a general rule, in JavaScript all values, all objects, and all of their properties are stored on the heap.

    There appears to be some long-standing myth that StackOverflow users keep telling each other about primitive values being stored on the stack. That is incorrect, and a few folks have posted explanations why it can't work (in short: scopes and lifetimes). Primitives are not stored on the stack, neither when they're object properties nor otherwise. All values are stored on the heap. There are one or two very old answers that claim otherwise, and then dozens of newer answers refer to those, so it seems to be a self-sustaining myth at this point (people keep repeating what they read elsewhere), but that doesn't make it true.


    If you insist on nitpicking:
    There is one kind-of exception to this general statement, and that's engine-internal optimizations that may or may not trigger for certain specific situations that may or may not have the specific kind of value as one of their preconditions.
    For example, once a function is hot enough to get optimized, the optimizing compiler may recognize non-escaping local variables and may avoid the usual heap allocation for the value(s) that they hold. This most typically affects number values, which might even be kept only in the CPU's registers (i.e. temporary/intermediate results wouldn't be written into memory at all).
    A variant of this is "escape analysis" for objects, which detects that an entire object is short-lived and invisible outside the function, and can avoid the allocation of that object; essentially it turns its properties into local variables when it can prove that doing so preserves observable behavior.
    Another example of engine-specific internal optimizations is when even without an optimizing compiler, some subset of values is special-cased in the internal representation of values, which can make them eligible for opportunistic stack storage in some situations. Depending on architectural choices of the engine, this might apply to "Smis" (small integers) or all Number values or possibly even short strings (no more than a handful of characters); in V8 it's only the former case (Smis).

    But, just to be unmistakably clear, none of this means that "primitive values are stored on the stack". The summary is that sometimes, a sufficiently advanced engine may be able to put some values (primitive or not) that are usually on the heap onto the stack instead as an unobservable optimization. A simple engine would not do that, and no engine can possibly do it for all values (or all primitives), because (1) the stack is way too small for that and (2) lifetime of values often prevents it. Nothing in JavaScript as a language says anything about stack allocation of (primitive) values.