Pointer Compression
Published on 2022-11-29. Last updated on 2025-07-12
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.
Possible Designs
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, 128 TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬────────────────╯ ╰──────────────────────────────┬──────────────────────────────────────────────────────╯ ╰─┬─╯
bits 63 to 47 (17 bits): unused bits 46 to 3 (44 bits): address bits 2 to 0 (3 bits): unused
→ 44 bits address, 20 “free” bits
type 3: normal reference, 8 byte granularity, 8 TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬────────────────────────╯ ╰──────────────────────┬──────────────────────────────────────────────────────╯ ╰─┬─╯
bits 63 to 43 (21 bits): unused bits 42 to 3 (40 bits): address bits 2 to 0 (3 bits): unused
→ 40 bits address, 24 “free” bits
type 4: normal reference, 8 byte granularity, 512 GiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬────────────────────────────────╯ ╰──────────────┬──────────────────────────────────────────────────────╯ ╰─┬─╯
bits 63 to 39 (25 bits): unused bits 38 to 3 (36 bits): address bits 2 to 0 (3 bits): unused
→ 36 bits address, 28 “free” bits
type 5: vtable/type/class reference, 128 byte granularity, 128 TiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬────────────────╯ ╰──────────────────────────────┬──────────────────────────────────────────────╯ ╰─────┬─────╯
bits 63 to 47 (17 bits): unused bits 46 to 7 (40 bits): address bits 6 to 0 (7 bits): unused
→ 40 bits address, 24 “free” bits
type 6: vtable/type/class reference, 128 byte granularity, 512 GiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬────────────────────────────────╯ ╰──────────────┬──────────────────────────────────────────────╯ ╰─────┬─────╯
bits 63 to 39 (25 bits): unused bits 38 to 7 (32 bits): address bits 6 to 0 (7 bits): unused
→ 32 bits address, 32 “free” bits
type 7: vtable/type/class reference, 128 byte granularity, 2GiB address space
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
╰──────────────┬────────────────────────────────────────────────╯ ╰──────────────┬──────────────────────────────╯ ╰─────┬─────╯
bits 63 to 31 (33 bits): unused bits 30 to 7 (24 bits): address bits 6 to 0 (7 bits): unused
→ 24 bits address, 40 “free” bits