Go 中指向结构体成员的指针如何使结构体保持活动状态

yyy*_*yyy 5 garbage-collection go

给出以下 golang 代码:

type Pointer struct { x, y int }

func foo(p *Pointer) *int {
    return &p.y
}
Run Code Online (Sandbox Code Playgroud)

CompilerExplorer显示return &p.y编译为

TESTB   AL, (AX)
ADDQ    $8, AX
RET
Run Code Online (Sandbox Code Playgroud)

这很容易理解。TESTB是空检查,然后通过添加to的偏移量来ADDQ生成指向的指针。p.yPointer::yp

我不明白的是,给定一个指向 的指针p.y,垃圾收集器如何知道它不仅仅是一个任意的*int,而是一个指向 a 的指针Pointer::y,因此p只要指向的指针p.y仍然存在,它就必须保持活动状态?

yyy*_*yyy 3

阅读源代码后我找到了答案。

  1. 使用基于 Arena/span 的分配。
  2. Arenas 和 Span 与页面对齐,因此计算指针指向哪个 arena 很简单。
  3. 有一个全局向量存储所有领域和跨度的元数据。
  4. 每个跨度都有固定的“元素大小”。同一跨度中的所有对象都具有相同的大小。
  5. 给定指针p、 span 的基地址b和 span 的元素大小s,我们知道指针指向 span 中的第 n 个元素,其中n = (p - b) / s
  6. 所以是span中第n个对象的地址b + s * n,需要将其标记为活动的。