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/mgcsweep.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/mgcsweep.go')
| -rw-r--r-- | src/runtime/mgcsweep.go | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 701e0b8125..5670b1b8d5 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -552,31 +552,44 @@ func (sl *sweepLocked) sweep(preserve bool) bool { mbits := s.markBitsForIndex(objIndex) if !mbits.isMarked() { // This object is not marked and has at least one special record. - // Pass 1: see if it has at least one finalizer. - hasFin := false + // Pass 1: see if it has a finalizer. + hasFinAndRevived := false endOffset := p - s.base() + size for tmp := siter.s; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next { if tmp.kind == _KindSpecialFinalizer { // Stop freeing of object if it has a finalizer. mbits.setMarkedNonAtomic() - hasFin = true + hasFinAndRevived = true break } } - // Pass 2: queue all finalizers _or_ handle profile record. - for siter.valid() && uintptr(siter.s.offset) < endOffset { - // Find the exact byte for which the special was setup - // (as opposed to object beginning). - special := siter.s - p := s.base() + uintptr(special.offset) - if special.kind == _KindSpecialFinalizer || !hasFin { + if hasFinAndRevived { + // Pass 2: queue all finalizers and clear any weak handles. Weak handles are cleared + // before finalization as specified by the internal/weak package. See the documentation + // for that package for more details. + for siter.valid() && uintptr(siter.s.offset) < endOffset { + // Find the exact byte for which the special was setup + // (as opposed to object beginning). + special := siter.s + p := s.base() + uintptr(special.offset) + if special.kind == _KindSpecialFinalizer || special.kind == _KindSpecialWeakHandle { + siter.unlinkAndNext() + freeSpecial(special, unsafe.Pointer(p), size) + } else { + // All other specials only apply when an object is freed, + // so just keep the special record. + siter.next() + } + } + } else { + // Pass 2: the object is truly dead, free (and handle) all specials. + for siter.valid() && uintptr(siter.s.offset) < endOffset { + // Find the exact byte for which the special was setup + // (as opposed to object beginning). + special := siter.s + p := s.base() + uintptr(special.offset) siter.unlinkAndNext() freeSpecial(special, unsafe.Pointer(p), size) - } else { - // The object has finalizers, so we're keeping it alive. - // All other specials only apply when an object is freed, - // so just keep the special record. - siter.next() } } } else { |
