//go:nowritebarrier
func markroot(desc *parfor, i uint32) {
- var gcw gcWorkProducer
+ var gcw gcWork
// Note: if you add a case here, please also update heapdump.go:dumproots.
switch i {
throw("can't scan gchelper stack")
}
- var gcw gcWorkProducer
+ var gcw gcWork
gcw.initFromCache()
scanframe := func(frame *stkframe, unused unsafe.Pointer) bool {
// Pick up gcw as free variable so gentraceback and friends can
// Scan a stack frame: local variables and function arguments/results.
//go:nowritebarrier
-func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWorkProducer) {
+func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
f := frame.fn
targetpc := frame.continpc
// out of the wbuf passed in + a single object placed
// into an empty wbuf in scanobject so there could be
// a performance hit as we keep fetching fresh wbufs.
- scanobject(b, 0, nil, &gcw.gcWorkProducer)
+ scanobject(b, 0, nil, gcw)
}
checknocurrentwbuf()
}
if b == 0 {
return
}
- scanobject(b, 0, nil, &gcw.gcWorkProducer)
+ scanobject(b, 0, nil, gcw)
}
}
// scanblock scans b as scanobject would.
// If the gcphase is GCscan, scanblock performs additional checks.
//go:nowritebarrier
-func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWorkProducer) {
+func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
// Use local copies of original parameters, so that a stack trace
// due to one of the throws below shows the original block
// base and extent.
// In this case, n may be an overestimate of the size; the GC bitmap
// must also be used to make sure the scan stops at the end of b.
//go:nowritebarrier
-func scanobject(b, n uintptr, ptrmask *uint8, gcw *gcWorkProducer) {
+func scanobject(b, n uintptr, ptrmask *uint8, gcw *gcWork) {
arena_start := mheap_.arena_start
arena_used := mheap_.arena_used
// throw("shade during harvest")
// }
- var gcw gcWorkProducer
+ var gcw gcWork
greyobject(obj, 0, 0, hbits, &gcw)
// This is part of the write barrier so put the wbuf back.
if gcphase == _GCmarktermination {
// Return possibly new workbuf to use.
// base and off are for debugging only and could be removed.
//go:nowritebarrier
-func greyobject(obj, base, off uintptr, hbits heapBits, gcw *gcWorkProducer) {
+func greyobject(obj, base, off uintptr, hbits heapBits, gcw *gcWork) {
// obj should be start of allocation, and so must be at least pointer-aligned.
if obj&(ptrSize-1) != 0 {
throw("greyobject: obj not pointer-aligned")
return (*workbuf)(unsafe.Pointer(wp))
}
-// A gcWorkProducer provides the interface to produce work for the
+// A gcWork provides the interface to produce and consume work for the
// garbage collector.
//
-// The usual pattern for using gcWorkProducer is:
+// The usual pattern for using gcWork is:
//
-// var gcw gcWorkProducer
-// .. call gcw.put() ..
+// var gcw gcWork
+// .. call gcw.put() to produce and gcw.get() to consume ..
// gcw.dispose()
-type gcWorkProducer struct {
+type gcWork struct {
// Invariant: wbuf is never full or empty
wbuf wbufptr
}
-// A gcWork provides the interface to both produce and consume work
-// for the garbage collector.
-//
-// The pattern for using gcWork is the same as gcWorkProducer.
-type gcWork struct {
- gcWorkProducer
-}
-
-// Note that there is no need for a gcWorkConsumer because everything
-// that consumes pointers also produces them.
-
// initFromCache fetches work from this M's currentwbuf cache.
//go:nowritebarrier
-func (w *gcWorkProducer) initFromCache() {
- // TODO: Instead of making gcWorkProducer pull from the
- // currentwbuf cache, use a gcWorkProducer as the cache and
- // make shade pass around that gcWorkProducer.
+func (w *gcWork) initFromCache() {
+ // TODO: Instead of making gcWork pull from the currentwbuf
+ // cache, use a gcWork as the cache and make shade pass around
+ // that gcWork.
if w.wbuf == 0 {
w.wbuf = wbufptr(xchguintptr(&getg().m.currentwbuf, 0))
}
// put enqueues a pointer for the garbage collector to trace.
//go:nowritebarrier
-func (ww *gcWorkProducer) put(obj uintptr) {
- w := (*gcWorkProducer)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
+func (ww *gcWork) put(obj uintptr) {
+ w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
wbuf := w.wbuf.ptr()
if wbuf == nil {
}
}
-// dispose returns any cached pointers to the global queue.
-//go:nowritebarrier
-func (w *gcWorkProducer) dispose() {
- if wbuf := w.wbuf; wbuf != 0 {
- putpartial(wbuf.ptr(), 58)
- w.wbuf = 0
- }
-}
-
-// disposeToCache returns any cached pointers to this M's currentwbuf.
-// It calls throw if currentwbuf is non-nil.
-//go:nowritebarrier
-func (w *gcWorkProducer) disposeToCache() {
- if wbuf := w.wbuf; wbuf != 0 {
- wbuf = wbufptr(xchguintptr(&getg().m.currentwbuf, uintptr(wbuf)))
- if wbuf != 0 {
- throw("m.currentwbuf non-nil in disposeToCache")
- }
- w.wbuf = 0
- }
-}
-
// tryGet dequeues a pointer for the garbage collector to trace.
//
// If there are no pointers remaining in this gcWork or in the global
//go:nowritebarrier
func (w *gcWork) dispose() {
if wbuf := w.wbuf; wbuf != 0 {
- // Even though wbuf may only be partially full, we
- // want to keep it on the consumer's queues rather
- // than putting it back on the producer's queues.
- // Hence, we use putfull here.
- putfull(wbuf.ptr(), 133)
+ putpartial(wbuf.ptr(), 167)
+ w.wbuf = 0
+ }
+}
+
+// disposeToCache returns any cached pointers to this M's currentwbuf.
+// It calls throw if currentwbuf is non-nil.
+//go:nowritebarrier
+func (w *gcWork) disposeToCache() {
+ if wbuf := w.wbuf; wbuf != 0 {
+ wbuf = wbufptr(xchguintptr(&getg().m.currentwbuf, uintptr(wbuf)))
+ if wbuf != 0 {
+ throw("m.currentwbuf non-nil in disposeToCache")
+ }
w.wbuf = 0
}
}