var sweep … type sweepdata … type sweepClass … const numSweepClasses … const sweepClassDone … func (s *sweepClass) load() sweepClass { … } func (s *sweepClass) update(sNew sweepClass) { … } func (s *sweepClass) clear() { … } // split returns the underlying span class as well as // whether we're interested in the full or partial // unswept lists for that class, indicated as a boolean // (true means "full"). func (s sweepClass) split() (spc spanClass, full bool) { … } // nextSpanForSweep finds and pops the next span for sweeping from the // central sweep buffers. It returns ownership of the span to the caller. // Returns nil if no such span exists. func (h *mheap) nextSpanForSweep() *mspan { … } const sweepDrainedMask … type activeSweep … // begin registers a new sweeper. Returns a sweepLocker // for acquiring spans for sweeping. Any outstanding sweeper blocks // sweep termination. // // If the sweepLocker is invalid, the caller can be sure that all // outstanding sweep work has been drained, so there is nothing left // to sweep. Note that there may be sweepers currently running, so // this does not indicate that all sweeping has completed. // // Even if the sweepLocker is invalid, its sweepGen is always valid. func (a *activeSweep) begin() sweepLocker { … } // end deregisters a sweeper. Must be called once for each time // begin is called if the sweepLocker is valid. func (a *activeSweep) end(sl sweepLocker) { … } // markDrained marks the active sweep cycle as having drained // all remaining work. This is safe to be called concurrently // with all other methods of activeSweep, though may race. // // Returns true if this call was the one that actually performed // the mark. func (a *activeSweep) markDrained() bool { … } // sweepers returns the current number of active sweepers. func (a *activeSweep) sweepers() uint32 { … } // isDone returns true if all sweep work has been drained and no more // outstanding sweepers exist. That is, when the sweep phase is // completely done. func (a *activeSweep) isDone() bool { … } // reset sets up the activeSweep for the next sweep cycle. // // The world must be stopped. func (a *activeSweep) reset() { … } // finishsweep_m ensures that all spans are swept. // // The world must be stopped. This ensures there are no sweeps in // progress. // //go:nowritebarrier func finishsweep_m() { … } func bgsweep(c chan int) { … } type sweepLocker … type sweepLocked … // tryAcquire attempts to acquire sweep ownership of span s. If it // successfully acquires ownership, it blocks sweep completion. func (l *sweepLocker) tryAcquire(s *mspan) (sweepLocked, bool) { … } // sweepone sweeps some unswept heap span and returns the number of pages returned // to the heap, or ^uintptr(0) if there was nothing to sweep. func sweepone() uintptr { … } // isSweepDone reports whether all spans are swept. // // Note that this condition may transition from false to true at any // time as the sweeper runs. It may transition from true to false if a // GC runs; to prevent that the caller must be non-preemptible or must // somehow block GC progress. func isSweepDone() bool { … } // Returns only when span s has been swept. // //go:nowritebarrier func (s *mspan) ensureSwept() { … } // sweep frees or collects finalizers for blocks not marked in the mark phase. // It clears the mark bits in preparation for the next GC round. // Returns true if the span was returned to heap. // If preserve=true, don't return it to heap nor relink in mcentral lists; // caller takes care of it. func (sl *sweepLocked) sweep(preserve bool) bool { … } // reportZombies reports any marked but free objects in s and throws. // // This generally means one of the following: // // 1. User code converted a pointer to a uintptr and then back // unsafely, and a GC ran while the uintptr was the only reference to // an object. // // 2. User code (or a compiler bug) constructed a bad pointer that // points to a free slot, often a past-the-end pointer. // // 3. The GC two cycles ago missed a pointer and freed a live object, // but it was still live in the last cycle, so this GC cycle found a // pointer to that object and marked it. func (s *mspan) reportZombies() { … } // deductSweepCredit deducts sweep credit for allocating a span of // size spanBytes. This must be performed *before* the span is // allocated to ensure the system has enough credit. If necessary, it // performs sweeping to prevent going in to debt. If the caller will // also sweep pages (e.g., for a large allocation), it can pass a // non-zero callerSweepPages to leave that many pages unswept. // // deductSweepCredit makes a worst-case assumption that all spanBytes // bytes of the ultimately allocated span will be available for object // allocation. // // deductSweepCredit is the core of the "proportional sweep" system. // It uses statistics gathered by the garbage collector to perform // enough sweeping so that all pages are swept during the concurrent // sweep phase between GC cycles. // // mheap_ must NOT be locked. func deductSweepCredit(spanBytes uintptr, callerSweepPages uintptr) { … } // clobberfree sets the memory content at x to bad content, for debugging // purposes. func clobberfree(x unsafe.Pointer, size uintptr) { … } // gcPaceSweeper updates the sweeper's pacing parameters. // // Must be called whenever the GC's pacing is updated. // // The world must be stopped, or mheap_.lock must be held. func gcPaceSweeper(trigger uint64) { … }