diff options
| author | Michael Anthony Knyszek <mknyszek@google.com> | 2024-04-04 04:50:13 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-04-18 21:25:11 +0000 |
| commit | dfc86e922cd033155339c22aff64e109f6c8cc89 (patch) | |
| tree | de0ed468258f04af1eaa6b60c16a13dd4698347e /src/runtime/mgcmark.go | |
| parent | fa470f6245191b3c2f0b715194edf7cdf951af48 (diff) | |
| download | go-dfc86e922cd033155339c22aff64e109f6c8cc89.tar.xz | |
internal/weak: add package implementing weak pointers
This change adds the internal/weak package, which exposes GC-supported
weak pointers to the standard library. This is for the upcoming weak
package, but may be useful for other future constructs.
For #62483.
Change-Id: I4aa8fa9400110ad5ea022a43c094051699ccab9d
Reviewed-on: https://go-review.googlesource.com/c/go/+/576297
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/runtime/mgcmark.go')
| -rw-r--r-- | src/runtime/mgcmark.go | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index a42912e1ca..61e917df41 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -328,6 +328,13 @@ func markrootSpans(gcw *gcWork, shard int) { // 2) Finalizer specials (which are not in the garbage // collected heap) are roots. In practice, this means the fn // field must be scanned. + // + // Objects with weak handles have only one invariant related + // to this function: weak handle specials (which are not in the + // garbage collected heap) are roots. In practice, this means + // the handle field must be scanned. Note that the value the + // handle pointer referenced does *not* need to be scanned. See + // the definition of specialWeakHandle for details. sg := mheap_.sweepgen // Find the arena and page index into that arena for this shard. @@ -373,24 +380,28 @@ func markrootSpans(gcw *gcWork, shard int) { // removed from the list while we're traversing it. lock(&s.speciallock) for sp := s.specials; sp != nil; sp = sp.next { - if sp.kind != _KindSpecialFinalizer { - continue - } - // don't mark finalized object, but scan it so we - // retain everything it points to. - spf := (*specialfinalizer)(unsafe.Pointer(sp)) - // A finalizer can be set for an inner byte of an object, find object beginning. - p := s.base() + uintptr(spf.special.offset)/s.elemsize*s.elemsize + switch sp.kind { + case _KindSpecialFinalizer: + // don't mark finalized object, but scan it so we + // retain everything it points to. + spf := (*specialfinalizer)(unsafe.Pointer(sp)) + // A finalizer can be set for an inner byte of an object, find object beginning. + p := s.base() + uintptr(spf.special.offset)/s.elemsize*s.elemsize - // Mark everything that can be reached from - // the object (but *not* the object itself or - // we'll never collect it). - if !s.spanclass.noscan() { - scanobject(p, gcw) - } + // Mark everything that can be reached from + // the object (but *not* the object itself or + // we'll never collect it). + if !s.spanclass.noscan() { + scanobject(p, gcw) + } - // The special itself is a root. - scanblock(uintptr(unsafe.Pointer(&spf.fn)), goarch.PtrSize, &oneptrmask[0], gcw, nil) + // The special itself is a root. + scanblock(uintptr(unsafe.Pointer(&spf.fn)), goarch.PtrSize, &oneptrmask[0], gcw, nil) + case _KindSpecialWeakHandle: + // The special itself is a root. + spw := (*specialWeakHandle)(unsafe.Pointer(sp)) + scanblock(uintptr(unsafe.Pointer(&spw.handle)), goarch.PtrSize, &oneptrmask[0], gcw, nil) + } } unlock(&s.speciallock) } |
