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 all 0 or 1, 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