指向结构体成员的指针如何在Go语言中保持结构体的生命周期

huangapple go评论105阅读模式
英文:

how a pointer to a struct member keeps the struct alive in Go

问题

给定以下的Go语言代码:

type Pointer struct { x, y int }

func foo(p *Pointer) *int {
    return &p.y
}

CompilerExplorer 显示return &p.y编译成了以下汇编代码:

TESTB   AL, (AX)
ADDQ    $8, AX
RET

很容易理解。TESTB是一个空指针检查,然后ADDQ通过将Pointer::y的偏移量加到p上来生成指向p.y的指针。

我不明白的是,给定一个指向p.y的指针,垃圾回收器如何知道它不仅仅是一个任意的*int,而是一个指向Pointer::y的指针,所以只要指向p.y的指针还活着,p就必须保持存活?

英文:

Given the following golang code:

type Pointer struct { x, y int }

func foo(p *Pointer) *int {
    return &p.y
}

CompilerExplorer shows that return &p.y compiles to

TESTB   AL, (AX)
ADDQ    $8, AX
RET

It's easy to understand. TESTB is a null check, then ADDQ produce a pointer to p.y by adding offset of Pointer::y to p.

What I don't understand is, given a pointer to p.y, how does the garbage collector knows it's not just an arbitrary *int, but a pointer to a Pointer::y, so p must remain alive as long as a pointer to p.y is still alive?

答案1

得分: 3

阅读了源代码后(链接:https://github.com/golang/go/blob/85a482fc244f6f118b1d063063a51eb8b0feadd8/src/runtime/mbitmap.go#L391),我找到了答案。

  1. Go使用基于arena/span的分配方式。
  2. Arenas和spans与页面对齐,因此可以轻松计算指针指向的是哪个arena。
  3. 有一个全局向量存储所有arenas和spans的元数据。
  4. 每个span都有一个固定的“元素大小”。同一span中的所有对象大小相同。
  5. 给定指针p,span的基地址b和span的元素大小s,我们可以知道指针指向span中的第n个元素,其中n = (p - b) / s
  6. 因此,span中第n个对象的地址为b + s * n,需要将其标记为存活。
英文:

After reading the source code I found the answer.

  1. Go use arena / span based allocation.
  2. Arenas and spans are aligned with pages, so it's trivial to calculate which arena is the pointer pointing to.
  3. There's a global vector stores metadata of all arenas and spans.
  4. Each span has a fixed "element size". All objects in the same span have the same size.
  5. Given the pointer p, base address of span b and element size of span s, we know the pointer is pointing n-th element in the span, where n = (p - b) / s.
  6. So the address of n-th object in the span b + s * n, which needs to be marked as alive.

huangapple
  • 本文由 发表于 2022年7月19日 22:53:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/73039175.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定