const minPhysPageSize … const maxPhysPageSize … const maxPhysHugePageSize … const pagesPerReclaimerChunk … const physPageAlignedStacks … type mheap … var mheap_ … type heapArena … type arenaHint … type mSpanState … const mSpanDead … const mSpanInUse … const mSpanManual … var mSpanStateNames … type mSpanStateBox … //go:nosplit func (b *mSpanStateBox) set(s mSpanState) { … } //go:nosplit func (b *mSpanStateBox) get() mSpanState { … } type mSpanList … type mspan … func (s *mspan) base() uintptr { … } func (s *mspan) layout() (size, n, total uintptr) { … } // recordspan adds a newly allocated span to h.allspans. // // This only happens the first time a span is allocated from // mheap.spanalloc (it is not called when a span is reused). // // Write barriers are disallowed here because it can be called from // gcWork when allocating new workbufs. However, because it's an // indirect call from the fixalloc initializer, the compiler can't see // this. // // The heap lock must be held. // //go:nowritebarrierrec func recordspan(vh unsafe.Pointer, p unsafe.Pointer) { … } type spanClass … const numSpanClasses … const tinySpanClass … func makeSpanClass(sizeclass uint8, noscan bool) spanClass { … } //go:nosplit func (sc spanClass) sizeclass() int8 { … } //go:nosplit func (sc spanClass) noscan() bool { … } // arenaIndex returns the index into mheap_.arenas of the arena // containing metadata for p. This index combines of an index into the // L1 map and an index into the L2 map and should be used as // mheap_.arenas[ai.l1()][ai.l2()]. // // If p is outside the range of valid heap addresses, either l1() or // l2() will be out of bounds. // // It is nosplit because it's called by spanOf and several other // nosplit functions. // //go:nosplit func arenaIndex(p uintptr) arenaIdx { … } // arenaBase returns the low address of the region covered by heap // arena i. func arenaBase(i arenaIdx) uintptr { … } type arenaIdx … // l1 returns the "l1" portion of an arenaIdx. // // Marked nosplit because it's called by spanOf and other nosplit // functions. // //go:nosplit func (i arenaIdx) l1() uint { … } // l2 returns the "l2" portion of an arenaIdx. // // Marked nosplit because it's called by spanOf and other nosplit funcs. // functions. // //go:nosplit func (i arenaIdx) l2() uint { … } // inheap reports whether b is a pointer into a (potentially dead) heap object. // It returns false for pointers into mSpanManual spans. // Non-preemptible because it is used by write barriers. // //go:nowritebarrier //go:nosplit func inheap(b uintptr) bool { … } // inHeapOrStack is a variant of inheap that returns true for pointers // into any allocated heap span. // //go:nowritebarrier //go:nosplit func inHeapOrStack(b uintptr) bool { … } // spanOf returns the span of p. If p does not point into the heap // arena or no span has ever contained p, spanOf returns nil. // // If p does not point to allocated memory, this may return a non-nil // span that does *not* contain p. If this is a possibility, the // caller should either call spanOfHeap or check the span bounds // explicitly. // // Must be nosplit because it has callers that are nosplit. // //go:nosplit func spanOf(p uintptr) *mspan { … } // spanOfUnchecked is equivalent to spanOf, but the caller must ensure // that p points into an allocated heap arena. // // Must be nosplit because it has callers that are nosplit. // //go:nosplit func spanOfUnchecked(p uintptr) *mspan { … } // spanOfHeap is like spanOf, but returns nil if p does not point to a // heap object. // // Must be nosplit because it has callers that are nosplit. // //go:nosplit func spanOfHeap(p uintptr) *mspan { … } // pageIndexOf returns the arena, page index, and page mask for pointer p. // The caller must ensure p is in the heap. func pageIndexOf(p uintptr) (arena *heapArena, pageIdx uintptr, pageMask uint8) { … } // Initialize the heap. func (h *mheap) init() { … } // reclaim sweeps and reclaims at least npage pages into the heap. // It is called before allocating npage pages to keep growth in check. // // reclaim implements the page-reclaimer half of the sweeper. // // h.lock must NOT be held. func (h *mheap) reclaim(npage uintptr) { … } // reclaimChunk sweeps unmarked spans that start at page indexes [pageIdx, pageIdx+n). // It returns the number of pages returned to the heap. // // h.lock must be held and the caller must be non-preemptible. Note: h.lock may be // temporarily unlocked and re-locked in order to do sweeping or if tracing is // enabled. func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { … } type spanAllocType … const spanAllocHeap … const spanAllocStack … const spanAllocPtrScalarBits … const spanAllocWorkBuf … // manual returns true if the span allocation is manually managed. func (s spanAllocType) manual() bool { … } // alloc allocates a new span of npage pages from the GC'd heap. // // spanclass indicates the span's size class and scannability. // // Returns a span that has been fully initialized. span.needzero indicates // whether the span has been zeroed. Note that it may not be. func (h *mheap) alloc(npages uintptr, spanclass spanClass) *mspan { … } // allocManual allocates a manually-managed span of npage pages. // allocManual returns nil if allocation fails. // // allocManual adds the bytes used to *stat, which should be a // memstats in-use field. Unlike allocations in the GC'd heap, the // allocation does *not* count toward heapInUse. // // The memory backing the returned span may not be zeroed if // span.needzero is set. // // allocManual must be called on the system stack because it may // acquire the heap lock via allocSpan. See mheap for details. // // If new code is written to call allocManual, do NOT use an // existing spanAllocType value and instead declare a new one. // //go:systemstack func (h *mheap) allocManual(npages uintptr, typ spanAllocType) *mspan { … } // setSpans modifies the span map so [spanOf(base), spanOf(base+npage*pageSize)) // is s. func (h *mheap) setSpans(base, npage uintptr, s *mspan) { … } // allocNeedsZero checks if the region of address space [base, base+npage*pageSize), // assumed to be allocated, needs to be zeroed, updating heap arena metadata for // future allocations. // // This must be called each time pages are allocated from the heap, even if the page // allocator can otherwise prove the memory it's allocating is already zero because // they're fresh from the operating system. It updates heapArena metadata that is // critical for future page allocations. // // There are no locking constraints on this method. func (h *mheap) allocNeedsZero(base, npage uintptr) (needZero bool) { … } // tryAllocMSpan attempts to allocate an mspan object from // the P-local cache, but may fail. // // h.lock need not be held. // // This caller must ensure that its P won't change underneath // it during this function. Currently to ensure that we enforce // that the function is run on the system stack, because that's // the only place it is used now. In the future, this requirement // may be relaxed if its use is necessary elsewhere. // //go:systemstack func (h *mheap) tryAllocMSpan() *mspan { … } // allocMSpanLocked allocates an mspan object. // // h.lock must be held. // // allocMSpanLocked must be called on the system stack because // its caller holds the heap lock. See mheap for details. // Running on the system stack also ensures that we won't // switch Ps during this function. See tryAllocMSpan for details. // //go:systemstack func (h *mheap) allocMSpanLocked() *mspan { … } // freeMSpanLocked free an mspan object. // // h.lock must be held. // // freeMSpanLocked must be called on the system stack because // its caller holds the heap lock. See mheap for details. // Running on the system stack also ensures that we won't // switch Ps during this function. See tryAllocMSpan for details. // //go:systemstack func (h *mheap) freeMSpanLocked(s *mspan) { … } // allocSpan allocates an mspan which owns npages worth of memory. // // If typ.manual() == false, allocSpan allocates a heap span of class spanclass // and updates heap accounting. If manual == true, allocSpan allocates a // manually-managed span (spanclass is ignored), and the caller is // responsible for any accounting related to its use of the span. Either // way, allocSpan will atomically add the bytes in the newly allocated // span to *sysStat. // // The returned span is fully initialized. // // h.lock must not be held. // // allocSpan must be called on the system stack both because it acquires // the heap lock and because it must block GC transitions. // //go:systemstack func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass) (s *mspan) { … } // initSpan initializes a blank span s which will represent the range // [base, base+npages*pageSize). typ is the type of span being allocated. func (h *mheap) initSpan(s *mspan, typ spanAllocType, spanclass spanClass, base, npages uintptr) { … } // Try to add at least npage pages of memory to the heap, // returning how much the heap grew by and whether it worked. // // h.lock must be held. func (h *mheap) grow(npage uintptr) (uintptr, bool) { … } // Free the span back into the heap. func (h *mheap) freeSpan(s *mspan) { … } // freeManual frees a manually-managed span returned by allocManual. // typ must be the same as the spanAllocType passed to the allocManual that // allocated s. // // This must only be called when gcphase == _GCoff. See mSpanState for // an explanation. // // freeManual must be called on the system stack because it acquires // the heap lock. See mheap for details. // //go:systemstack func (h *mheap) freeManual(s *mspan, typ spanAllocType) { … } func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { … } // scavengeAll acquires the heap lock (blocking any additional // manipulation of the page allocator) and iterates over the whole // heap, scavenging every free page available. // // Must run on the system stack because it acquires the heap lock. // //go:systemstack func (h *mheap) scavengeAll() { … } //go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory func runtime_debug_freeOSMemory() { … } // Initialize a new span with the given start and npages. func (span *mspan) init(base uintptr, npages uintptr) { … } func (span *mspan) inList() bool { … } // Initialize an empty doubly-linked list. func (list *mSpanList) init() { … } func (list *mSpanList) remove(span *mspan) { … } func (list *mSpanList) isEmpty() bool { … } func (list *mSpanList) insert(span *mspan) { … } func (list *mSpanList) insertBack(span *mspan) { … } // takeAll removes all spans from other and inserts them at the front // of list. func (list *mSpanList) takeAll(other *mSpanList) { … } const _KindSpecialFinalizer … const _KindSpecialWeakHandle … const _KindSpecialProfile … const _KindSpecialReachable … const _KindSpecialPinCounter … type special … // spanHasSpecials marks a span as having specials in the arena bitmap. func spanHasSpecials(s *mspan) { … } // spanHasNoSpecials marks a span as having no specials in the arena bitmap. func spanHasNoSpecials(s *mspan) { … } // Adds the special record s to the list of special records for // the object p. All fields of s should be filled in except for // offset & next, which this routine will fill in. // Returns true if the special was successfully added, false otherwise. // (The add will fail only if a record with the same p and s->kind // already exists.) func addspecial(p unsafe.Pointer, s *special) bool { … } // Removes the Special record of the given kind for the object p. // Returns the record if the record existed, nil otherwise. // The caller must FixAlloc_Free the result. func removespecial(p unsafe.Pointer, kind uint8) *special { … } // Find a splice point in the sorted list and check for an already existing // record. Returns a pointer to the next-reference in the list predecessor. // Returns true, if the referenced item is an exact match. func (span *mspan) specialFindSplicePoint(offset uintptr, kind byte) (**special, bool) { … } type specialfinalizer … // Adds a finalizer to the object p. Returns true if it succeeded. func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *ptrtype) bool { … } // Removes the finalizer (if any) from the object p. func removefinalizer(p unsafe.Pointer) { … } type specialWeakHandle … //go:linkname internal_weak_runtime_registerWeakPointer internal/weak.runtime_registerWeakPointer func internal_weak_runtime_registerWeakPointer(p unsafe.Pointer) unsafe.Pointer { … } //go:linkname internal_weak_runtime_makeStrongFromWeak internal/weak.runtime_makeStrongFromWeak func internal_weak_runtime_makeStrongFromWeak(u unsafe.Pointer) unsafe.Pointer { … } // Retrieves or creates a weak pointer handle for the object p. func getOrAddWeakHandle(p unsafe.Pointer) *atomic.Uintptr { … } func getWeakHandle(p unsafe.Pointer) *atomic.Uintptr { … } type specialprofile … // Set the heap profile bucket associated with addr to b. func setprofilebucket(p unsafe.Pointer, b *bucket) { … } type specialReachable … type specialPinCounter … type specialsIter … func newSpecialsIter(span *mspan) specialsIter { … } func (i *specialsIter) valid() bool { … } func (i *specialsIter) next() { … } // unlinkAndNext removes the current special from the list and moves // the iterator to the next special. It returns the unlinked special. func (i *specialsIter) unlinkAndNext() *special { … } // freeSpecial performs any cleanup on special s and deallocates it. // s must already be unlinked from the specials list. func freeSpecial(s *special, p unsafe.Pointer, size uintptr) { … } type gcBits … // bytep returns a pointer to the n'th byte of b. func (b *gcBits) bytep(n uintptr) *uint8 { … } // bitp returns a pointer to the byte containing bit n and a mask for // selecting that bit from *bytep. func (b *gcBits) bitp(n uintptr) (bytep *uint8, mask uint8) { … } const gcBitsChunkBytes … const gcBitsHeaderBytes … type gcBitsHeader … type gcBitsArena … var gcBitsArenas … // tryAlloc allocates from b or returns nil if b does not have enough room. // This is safe to call concurrently. func (b *gcBitsArena) tryAlloc(bytes uintptr) *gcBits { … } // newMarkBits returns a pointer to 8 byte aligned bytes // to be used for a span's mark bits. func newMarkBits(nelems uintptr) *gcBits { … } // newAllocBits returns a pointer to 8 byte aligned bytes // to be used for this span's alloc bits. // newAllocBits is used to provide newly initialized spans // allocation bits. For spans not being initialized the // mark bits are repurposed as allocation bits when // the span is swept. func newAllocBits(nelems uintptr) *gcBits { … } // nextMarkBitArenaEpoch establishes a new epoch for the arenas // holding the mark bits. The arenas are named relative to the // current GC cycle which is demarcated by the call to finishweep_m. // // All current spans have been swept. // During that sweep each span allocated room for its gcmarkBits in // gcBitsArenas.next block. gcBitsArenas.next becomes the gcBitsArenas.current // where the GC will mark objects and after each span is swept these bits // will be used to allocate objects. // gcBitsArenas.current becomes gcBitsArenas.previous where the span's // gcAllocBits live until all the spans have been swept during this GC cycle. // The span's sweep extinguishes all the references to gcBitsArenas.previous // by pointing gcAllocBits into the gcBitsArenas.current. // The gcBitsArenas.previous is released to the gcBitsArenas.free list. func nextMarkBitArenaEpoch() { … } // newArenaMayUnlock allocates and zeroes a gcBits arena. // The caller must hold gcBitsArena.lock. This may temporarily release it. func newArenaMayUnlock() *gcBitsArena { … }