1

我的问题:

我需要在指向对象的指针中编码有关对象的附加信息。我认为我可以做的是使用指针的一部分来做到这一点。也就是说,使用几位编码布尔标志。据我所知,Windows内核中某些类型的句柄也是如此。

背景:

我正在编写一个小型内存管理系统,可以垃圾收集未使用的对象。为了减少对象引用的内存消耗并加快复制速度,我想使用带有附加编码数据的指针,例如对象的状态(活动或准备好被收集)、锁定位和可由单个位表示的类似事物。

我的问题:

如何在不实际覆盖指针的重要位的情况下将此类信息编码为 64 位指针?

由于 x64 windows 的地址空间有限,我相信并不是指针的所有 64 位都被使用,所以我相信应该是可以的。但是,我无法找到哪些位窗口实际用于指针,哪些没有。为了澄清,这个问题是关于 64 位窗口上的用户模式。

提前致谢。

4

1 回答 1

2

这在很大程度上取决于所使用的体系结构、操作系统和编译器,但如果你知道这些,你可以用它做一些事情。

x86_64 在硬件中定义了一个 48 位1字节的虚拟地址空间,这意味着基本上所有的操作系​​统和编译器都会使用它。这意味着:

  • 所有有效地址的前 17 位必须全部相同(全 0 或全 1)
  • 任何2 k字节对齐地址的底部k位必须全为 0
  • 此外,几乎所有操作系统(至少是 Windows、Linux 和 OSX)都保留将高位设置为内核地址的地址——所有用户地址的高 17 位必须全为 0

因此,这为您提供了多种将有效指针打包成小于 64 位的方法,然后使用移位和/或掩码指令重建原始指针。

如果您只需要 3 位并始终使用 8 字节对齐的指针,则可以使用底部 3 位来编码额外信息,并在使用指针之前将它们屏蔽掉。

如果您需要更多位,您可以将指针向上(向左)移动 16 位,并使用低 16 位作为信息。要重建指针,只需右移 16 位。

要对指针进行移位和屏蔽操作,您需要将它们转换为intptr_tor int64_t(在 C 或 C++ 的任何 64 位实现上,它们都是相同的类型)


1有一些提示可能很快会有硬件将其扩展到 56 位,因此只有前 9 位需要为 0 或 1,但任何操作系统都支持此功能还需要一段时间

于 2020-05-25T20:03:22.153 回答