V8 Pointer Tagging Exercise
Description
In v8, JSValues are "Tagged Values" (aka "Tagged Pointers") which can either be a pointer or an integer. If the Least Significant Bit is set, the value (minus that bit) is a pointer. Otherwise the value is a shifted integer.
For 32 bit JSValues, integers are encoded as:
tagged_jsval = some_int << 1
For 64 bit JSValues, integers are encoded as:
tagged_jsval = some_int << 32
For both 32 bit and 64 bit JSValues, pointers are encoded as:
tagged_jsval = some_ptr | 1
Steps
First let's practice decoding some Tagged JSValues:
- What is the decoded value of this 64 bit JSValue:
0x0414243400000000
Reveal Answer
The integer0x4142434
- What is the decoded value of this 32 bit JSValue:
0x41424340
Reveal Answer
The integer0x20a121a0
(which is0x41424340 >> 1
)
- What is the decoded value of this 64 bit JSValue:
0x00001b4a72c8b4d9
Reveal Answer
The pointer0x1b4a72c8b4d8
For JavaScript objects, the properties and other pointers are usually stored as tagged JSValues. If we construct an object with several properties of different types, we should be able to see how they are encoded in memory.
WarningIf you haven't already, read through the VM overview to understand the VM / exercise setup.
Run the V8 REPL under GDB:
exercise run v8 --gdb
- Create an object with several properties of different types. Make sure to have at least one small-ish integer (< 31 bits aka SMI) as well as a reference type. For example
foo = {a:0x414243, b:{}, c: 1.1, d:null}
.
WarningIntegers > 30 bits will be converted to a 64 bit double and the JSValue will be pointer to a heap allocation
Print the address of the object by calling
%DebugPrint(o)
Break in gdb (with ctrl-c) and print memory at the object's address (e.g.
x/16gx <object-addr>
).Locate the integer property (it should be shifted up as a 64-bit tagged value). Does it match the "tagged SMI" value you expected?
Examine how other properties are stored as "tagged pointers". Take note of how:
- Each pointer has
1
added to it - The floating point number (
c: 1.1
) is actually a pointer to a heap allocation- Bonus: Dump memory at that pointer and you'll find the 64-bit float!
- Other pointers in the object are also tagged pointers (for example the first QWORD in the dump)
- Each pointer has