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 all0or1, 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, 64 byte granularity, 1 GiB address space
 +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
 | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ | ┊ ┊ ┊ ┊ ┊ ┊ ┊ |
 +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
  ╰──────────────┬──────────────────────────────────────────────────╯ ╰──────────┬──────────────────────────────────╯ ╰───┬─────╯
      bits 63 to 30 (34 bits): unused                 bits 29 to 6 (24 bits): address                 bits 5 to 0 (6 bits): unused
→ 24 bits address, 40 “free” bits