aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgcsweep.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2024-04-04 04:50:13 +0000
committerGopher Robot <gobot@golang.org>2024-04-18 21:25:11 +0000
commitdfc86e922cd033155339c22aff64e109f6c8cc89 (patch)
treede0ed468258f04af1eaa6b60c16a13dd4698347e /src/runtime/mgcsweep.go
parentfa470f6245191b3c2f0b715194edf7cdf951af48 (diff)
downloadgo-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.go43
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 {