Swift 标签指针

Swift 中的标签指针

在 iOS 和 MacOS 等 64 位系统中,指针只需要 44 位!

这意味着我们有额外的 20 位可以利用!使用这个库,你可以通过 Swift 类型 TaggedPointer<> 轻松实现这一点。

用法

let x = 5
withUnsafePointer(to: x) { p in
    var tp = TaggedPointer(p)
    tp.bitTag0 = true
    tp.bitTag1 = true
    tp.bitTag2 = true
    tp.dataInt17 = 23
    assert(tp.getPointer() == p)
}

你也可以查看测试作为示例。

指针布局

以下是指针在内存中的布局方式。

               Raw storage:  |-----------------------------64 bits----------------------------|
           Pointer anatomy:  |--16 bits--|------1 bit-----|---- 44 bits ---|------3 bits------|
                             |unused bits|is kernel space?|the pointer guts|alignment artifact|
                             |   all 0s  |       0        |      ???       |      all 0s      |
               Raw storage:  |-----------------------------64 bits----------------------------|
Simplified Pointer anatomy:  |-----17 bits-----|--------------44 bits--------------|--3 bits--|
                             |     all 0s      |    significant bits of pointer    |  all 0s  |
                             |----------------------------------------------------------------|

前 16 位始终为 0,因为操作系统假设内存永远不会超过 48 位指针可以寻址的范围(48 位指针可以寻址 256 TB 的内存)。当指针位于内核空间时,内核空间标志为 1,当指针位于用户空间时,内核空间标志为 0。我们假设程序运行在用户空间中。 后 3 位始终为 0,因为指针是 8 字节对齐的,即第一个地址将是 0x0,然后是 0x8,然后是 0x10,依此类推。 如果你将指针十六进制值转换为二进制,你会发现后 3 位始终为 0。

TaggedPointer<> 布局

TaggedPointer<> 利用指针中的额外位来让你塞入你自己的数据和位标志。

          Raw storage:  |-----------------------------64 bits----------------------------|
TaggedPointer anatomy:  |-------17 bits-------|------44 bits-------|--------3 bits-------|
                        | custom 17 bit data  |    pointer data    |  custom 3 bit tag   |
                        |                     |    `getPointer`    |                     |
                        |                     |    `setPointer`    |                     |
                        |----------------------------------------------------------------|

                        |-----------------------------64 bits----------------------------|
                        |--------61 bits-------|-----------------3 bits------------------|
                        |                      |               `tagUInt3`                |
                        |                      |----1 bit----|----1 bit----|----1 bit----|
                        |                      |   `bitTag2` |  `bitTag1`  |  `bitTag0`  |
                        |----------------------------------------------------------------|

                        |-----------------------------64 bits----------------------------|
                        |------------17 bits----------|--------------47 bits-------------|
                        |          `dataInt17`        |                                  |
                        |-----16 bits-----|---1 bit---|                                  |
                        |   magnitude     | `signBit` |                                  |
                        |----------------------------------------------------------------|

                        |-----------------------------64 bits----------------------------|
                        |-----16 bits-----|---------------------48 bits------------------|
                        |   `dataUInt16`  |                                              |
                        |   `dataInt16`   |                                              |
                        |----------------------------------------------------------------|

你可以将标签用作 3 位整数(表示为 UInt8 tagAsUInt8)或用作 3 个单独的位(bitTag0bitTag1bitTag2)。 你可以将数据用作 17 位有符号整数 (data17) 或用作 16 位无符号整数 (dataUInt16)。 你也可以直接访问数据的符号位 (signBit)。

安装

你可以简单地复制实现(只有一个文件)这里,或者你可以将其添加为 Swift 包。

// swift-tools-version:5.9
import PackageDescription

let package = Package(
  name: "MyPackage",
  dependencies: [
    .package(
      url: "https://github.com/joehinkle11/SwiftTaggedPointer.git", 
      .upToNextMajor(from: "1.0.0") // or `.upToNextMinor
    )
  ],
  targets: [
    .target(
      name: "MyTarget",
      dependencies: [
        .product(name: "SwiftTaggedPointer", package: "SwiftTaggedPointer")
      ]
    )
  ]
)