I've been building a bytecode VM in Rust and recently implemented NaN boxing for value representation. Sharing here for anyone interested.
I needed all VM values (booleans, integers, string pool indices, bytecode references) to fit in 64 bits (stack is Vec<u64>).
My implementation encodes 5 distinct types using a 3-bit tag and 32-bit payload, all within a single u64. It also has 15 unused bits, they may be used later for types expansion.
I'm using a 64-bit layout:
- Bits 63-51: Quiet NaN signature (0x7FFC...)
- Bits 50-18: 32-bit payload (integers, string pool indices, etc.)
- Bits 17-3: Unused/ (15 bits)
- Bits 2-0: 3-bit type tag
I needed all VM values (booleans, integers, string pool indices, bytecode references) to fit in 64 bits (stack is Vec<u64>). My implementation encodes 5 distinct types using a 3-bit tag and 32-bit payload, all within a single u64. It also has 15 unused bits, they may be used later for types expansion.
I'm using a 64-bit layout: - Bits 63-51: Quiet NaN signature (0x7FFC...) - Bits 50-18: 32-bit payload (integers, string pool indices, etc.) - Bits 17-3: Unused/ (15 bits) - Bits 2-0: 3-bit type tag