yyyy
yyyy

Reputation: 672

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

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?

Upvotes: 5

Views: 836

Answers (1)

yyyy
yyyy

Reputation: 672

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.

Upvotes: 3

Related Questions