Pointer Compression
Published on 2022-11-29.
TL;DR: How large is a pointer on 64-bit systems – and how small can it practically be made?
Basics
- AMD64 and ARMv8 architectures support 48 bits of virtual address space.
Even though a canonical pointer requires that the untranslated bits are either all0
or1
, they can be reused for other purposes, as long as the bits are masked before memory is accessed. - Shaving off upper bits of the pointer reduces the addressable space.
- Shaving off lower bits of the pointer reduces the granularity.
type 1: normal reference, 1 byte granularity, 256 TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────╯ ╰──────────────────────────────┬──────────────────────────────────────────────────────────────╯
bits 63 to 48 (16 bits): unused bits 47 to 0 (48 bits): address
→ 48 bits address, 16 “free” bits
type 2: normal reference, 8 byte granularity, 256 TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────╯ ╰──────────────────────────────┬──────────────────────────────────────────────────────╯ ╰──┬──╯
bits 63 to 48 (16 bits): unused bits 47 to 4 (44 bits): address bits 3 to 0 (4 bits): unused
→ 44 bits address, 20 “free” bits
type 3: normal reference, 8 byte granularity, 16TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────────────╯ ╰──────────────────────┬──────────────────────────────────────────────────────╯ ╰──┬──╯
bits 63 to 44 (20 bits): unused bits 43 to 4 (40 bits): address bits 3 to 0 (4 bits): unused
→ 40 bits address, 24 “free” bits
type 4: normal reference, 8 byte granularity, 1TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────────────────────╯ ╰──────────────┬──────────────────────────────────────────────────────╯ ╰──┬──╯
bits 63 to 40 (24 bits): unused bits 39 to 4 (36 bits): address bits 3 to 0 (4 bits): unused
→ 36 bits address, 28 “free” bits
type 5: vtable/type/klass reference, 128 byte granularity, 256 TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────╯ ╰──────────────────────────────┬──────────────────────────────────────────────╯ ╰──────┬──────╯
bits 63 to 48 (16 bits): unused bits 47 to 8 (40 bits): address bits 7 to 0 (8 bits): unused
→ 40 bits address, 24 “free” bits
type 6: vtable/type/klass reference, 128 byte granularity, 1TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────────────────────╯ ╰──────────────┬──────────────────────────────────────────────╯ ╰──────┬──────╯
bits 63 to 40 (24 bits): unused bits 39 to 8 (32 bits): address bits 7 to 0 (8 bits): unused
→ 32 bits address, 32 “free” bits
type 7: vtable/type/klass reference, 128 byte granularity, 4GiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬──────────────────────────────────────────────╯ ╰──────────────┬──────────────────────────────╯ ╰──────┬──────╯
bits 63 to 32 (32 bits): unused bits 31 to 8 (24 bits): address bits 7 to 0 (8 bits): unused
→ 24 bits address, 40 “free” bits