在指针中对其他信息进行编码



我的问题:

我需要在指向对象的指针中对有关该对象的其他信息进行编码。 我认为我能做的是使用部分指针来做到这一点。也就是说,使用一些位编码布尔标志。据我所知,同样的事情也发生在窗口内核中的某些类型的句柄上。

背景:

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

我的问题:

如何将此类信息编码为 64 位指针,而不会实际覆盖指针的重要位?

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

提前谢谢。

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

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

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

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

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

如果需要更多位,可以将指针向上(向左(移动 16 位,并使用较低的 16 位获取信息。 要重建指针,请正好移位 16。

要对指针执行移位和掩码操作,您需要将它们强制转换为intptr_tint64_t(在任何 C 或 C++ 的 64 位实现上,这些类型将是相同的(

1

有一些迹象表明,可能很快就会有硬件将其扩展到 56 位,因此只有前 9 位需要是 0 或 1,但任何操作系统都支持这一点还需要一段时间

最新更新