Кодировать дополнительную информацию в указателе - PullRequest
1 голос
/ 25 мая 2020

Моя проблема:

Мне нужно закодировать дополнительную информацию об объекте в указателе на объект. Я думал, что могу использовать для этого часть указателя. То есть используйте несколько битов для кодирования логических флагов. Насколько мне известно, то же самое происходит с определенными типами дескрипторов в ядре windows.

Предпосылки:

Я пишу небольшую систему управления памятью, которая может мусорить- собирать неиспользуемые предметы. Чтобы уменьшить потребление памяти ссылками на объекты и ускорить копирование, я хочу использовать указатели с дополнительными закодированными данными, например, состояние объекта (активен или готов к сбору), бит блокировки и подобные вещи, которые могут быть представлены одним битом.

Мой вопрос:

Как я могу закодировать такую ​​информацию в 64-битный указатель без фактической перезаписи важных битов указателя?

Поскольку x64 windows имеет ограниченное адресное пространство, я считаю, что используются не все 64 бита указателя, поэтому я считаю, что это должно быть возможно. Однако мне не удалось найти, какие биты windows фактически используются для указателя, а какие нет. Чтобы уточнить, этот вопрос касается режима пользователя на 64-битной windows.

Заранее спасибо.

1 Ответ

2 голосов
/ 25 мая 2020

Это сильно зависит от используемой архитектуры, ОС и компилятора, но если вы знаете эти вещи, вы можете что-то с этим делать.

x86_64 определяет 48-битный 1 байтовое виртуальное адресное пространство в аппаратном обеспечении, что означает, что практически все операционные системы и компиляторы будут его использовать. Это означает:

  • верхние 17 бит всех действительных адресов должны быть одинаковыми (все нули или все единицы)
  • нижние k биты любого 2 k адреса, выровненного по байтам, должны быть все 0s
  • вдобавок, почти все операционные системы (Windows, Linux и OSX по крайней мере ) зарезервировать адреса с старшими битами, установленными как адреса ядра - все адреса пользователей должны иметь старшие 17 битов все 0

Таким образом, это дает вам множество способов упаковки действительного указателя в меньшее, чем 64 бита, а затем реконструкция исходного указателя с помощью инструкций сдвига и / или маски.

Если вам нужно только 3 бита и всегда использовать 8-байтовые выровненные указатели, вы можете использовать нижние 3 бита для кодирования дополнительной информации , и замаскируйте их перед использованием указателя.

Если вам нужно больше бит, вы можете сдвинуть указатель вверх (влево) на 16 бит и использовать эти младшие 16 бит для информации. Чтобы восстановить указатель, просто сдвиньте вправо на 16.

Чтобы выполнять операции сдвига и маскирования для указателей, вам необходимо преобразовать их в intptr_t или int64_t (они будут одного типа на любых 64- битовая реализация C или C ++)


1 Есть некоторые намеки на то, что вскоре может появиться оборудование, которое расширяет это до 56 бит, поэтому только верхние 9 бит должно быть 0 или 1, но пройдет некоторое время, прежде чем какая-либо ОС будет поддерживать это

...