JavaScript Code
var str = "hi";
Memory allocation:
Address | Value | Description |
---|---|---|
...... |
... | |
0x1001 |
call object | Start of a call object's memory |
0x1002 |
0x00af | Reference to invoked function |
0x1003 |
1 | Number of references in this call object |
0x1004 |
str | Name of variable (in practice would not be in a single address) |
0x1005 |
0x1001 |
Memory address of "hi" |
...... |
... | |
0x2001 |
string | type identifier |
0x2002 |
2 | number of bytes |
0x2003 |
h | byte of first character |
0x2004 |
i | byte of second character |
When JS runs: var str = "hi";
by calling some function, it first hoists all variable declarations and creates a spot in memory for the variable. This might leave memory something like:
Address | Value | Description |
---|---|---|
...... |
... | |
0x1001 |
call object | Start of a call object's memory |
0x1002 |
0x00af | Reference to invoked function |
0x1003 |
1 | Number of references in this call object |
0x1004 |
str | Name of variable |
0x1005 |
empty | |
...... |
... |
In practice, the name of the variable, str
, would not be held in a single memory address. Also, the variable names and locations would not be stored in a fixed-memory array (possibly in a hash-table).
Next, the string "hi"
would be created in memory like:
Address | Value | Description |
---|---|---|
...... |
... | |
0x2001 |
string | type identifier |
0x2002 |
2 | number of bytes |
0x2003 |
h | byte of first character |
0x2004 |
i | byte of second character |
Finally, the pointer address of str
would be set to the memory address of "hi"
(0x2001
), leaving memory as indicated at the top of the page.
Let take a look at what V8 actually does when it runs something like:
First of all, allocation of string
"str"
does not happen every time you run this function. It is allocated once by a parser. Every time you execute this code the very same string object will be used again and again. It looks like this:where hidden class is actually the first word of every object, it points to a structure describing object type and layout. Three first fields all have the same size a normal pointer would have. In other words it is 4 bytes on 32bit, 8 bytes on 64bit architectures. The rest is for the string's content which is padded on the right so that overall size of object is divisible by pointer size. In the example above I assume 4 byte pointers and so I added 1 byte of padding (■).
There are actually numerous ways to represent a string in V8 and the one above is called sequential string, because it carries its payload in the body.
Now lets get back to the function parsing. As I said the string itself is allocated once by a parser. The same, in some sense, is true for a variable as well. V8 does not recompute the scope every time you enter the function, it does it once when it parses foo. For a simple function above it'll compute the scope with a parameter
x
(parameter index 1) and a single local variablehi
(local index 0). When JIT compiler starts emitting the code it'll use indices to access variables not names.The call object that you are describing above does not really exist in the heap. Instead the native machine stack is used.
When you enter the function
foo
you end up with something like this:this
)x
x
foo
)undefined
hi
(Every slot in the "picture" above is of pointer size. I am using → to highlight that the value itself is not stored on the stack. Only pointer to it is.)
As you can notice there is no variable names here (the mapping is retained somewhere in the scope object produced by a parser, but it is not used by the code generated by JIT compiler). There is also no explicit size this information can be computed if needed from stack registers (
ebp
andesp
) when required.If initialisation
var hi = "str"
is executed then pointer toundefined
will be replaced with a pointer to a string"str"
allocated as described above and the stack will start looking like this:this
)x
x
foo
)"str"
hi
[Things will look differently if
x
is a captured variable or ifx
was introduced byeval
but lets leave these complexities aside for now]