Отображение той же памяти (mmap
на POSIX, как упоминает Игнасио, MapViewOfFile
на Windows) для нескольких виртуальных адресов может предоставить вам некоторые интересные головоломки когерентности (есть запись в один адрес виден при чтении по другому адресу?). А может и нет. Я не уверен, что все гарантии платформы.
Чаще всего, каждый просто резервирует несколько бит в указателе и перемещает по мере необходимости.
Если все ваши объекты выровнены с 8-байтовыми границами, обычно просто хранить теги в 3 наименее значимых битах указателя и маскировать их перед разыменованием (как упоминается thkala). Если вы выберете более высокое выравнивание, например 16-байтовое или 32-байтовое, то есть 3 или 5 наименее значимых бит, которые можно использовать для пометки. Эквивалентно, выберите несколько наиболее значимых бит для пометки и сдвиньте их до разыменования. (Иногда несмежные биты используются, например, при упаковке указателей в сигнализации NaNs из IEEE-754 поплавков (2 значения) или двойные (2 значения).)
Продолжая на высоком конце указателя, текущие реализации x86-64 используют не более 48 бит из 64-разрядного указателя (0x0000000000000000-0x00007fffffffffff + 0xffff800000000000-0xffffffffffffffff), а Linux и Windows только передают адреса в первом диапазоне в пользовательское пространство, оставляя 17 наиболее популярных, значимые биты, которые можно безопасно замаскировать. (Это не является ни переносимым, ни гарантированным, чтобы оставаться в силе в будущем.)
Другой подход заключается в том, чтобы перестать рассматривать «указатели» и просто использовать индексы в массив больших массивов, поскольку JVM работает с -XX:+UseCompressedOops
.Если вы выделили пул размером 512 Мбайт и сохранили 8-байтовые выровненные объекты, есть 2 возможных мест размещения объектов, поэтому 32-значное значение дополнительно содержит 6 бит. Для разыменования потребуется добавить индекс времени выравнивания к базовому адресу массива, сохраненного в другом месте (для каждого «указателя» он одинаковый). Если вы внимательно посмотрите на вещи, это просто обобщение предыдущей техники (которая всегда имеет базу в 0, где вещи выстраиваются в линию с реальными указателями).