| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package runtime | |
| import "unsafe" | |
| // Memory allocator, based on tcmalloc. | |
| // http://goog-perftools.sourceforge.net/doc/tcmalloc.html | |
| // The main allocator works in runs of pages. | |
| // Small allocation sizes (up to and including 32 kB) are | |
| // rounded to one of about 100 size classes, each of which | |
| // has its own free list of objects of exactly that size. | |
| // Any free page of memory can be split into a set of objects | |
| // of one size class, which are then managed using free list | |
| // allocators. | |
| // | |
| // The allocator's data structures are: | |
| // | |
| // FixAlloc: a free-list allocator for fixed-size objects, | |
| // used to manage storage used by the allocator. | |
| // MHeap: the malloc heap, managed at page (4096-byte) granularity. | |
| // MSpan: a run of pages managed by the MHeap. | |
| // MCentral: a shared free list for a given size class. | |
| // MCache: a per-thread (in Go, per-P) cache for small objects. | |
| // MStats: allocation statistics. | |
| // | |
| // Allocating a small object proceeds up a hierarchy of caches: | |
| // | |
| // 1. Round the size up to one of the small size classes | |
| // and look in the corresponding MCache free list. | |
| // If the list is not empty, allocate an object from it. | |
| // This can all be done without acquiring a lock. | |
| // | |
| // 2. If the MCache free list is empty, replenish it by | |
| // taking a bunch of objects from the MCentral free list. | |
| // Moving a bunch amortizes the cost of acquiring the MCentral lock. | |
| // | |
| // 3. If the MCentral free list is empty, replenish it by | |
| // allocating a run of pages from the MHeap and then | |
| // chopping that memory into objects of the given size. | |
| // Allocating many objects amortizes the cost of locking | |
| // the heap. | |
| // | |
| // 4. If the MHeap is empty or has no page runs large enough, | |
| // allocate a new group of pages (at least 1MB) from the | |
| // operating system. Allocating a large run of pages | |
| // amortizes the cost of talking to the operating system. | |
| // | |
| // Freeing a small object proceeds up the same hierarchy: | |
| // | |
| // 1. Look up the size class for the object and add it to | |
| // the MCache free list. | |
| // | |
| // 2. If the MCache free list is too long or the MCache has | |
| // too much memory, return some to the MCentral free lists. | |
| // | |
| // 3. If all the objects in a given span have returned to | |
| // the MCentral list, return that span to the page heap. | |
| // | |
| // 4. If the heap has too much memory, return some to the | |
| // operating system. | |
| // | |
| // TODO(rsc): Step 4 is not implemented. | |
| // | |
| // Allocating and freeing a large object uses the page heap | |
| // directly, bypassing the MCache and MCentral free lists. | |
| // | |
| // The small objects on the MCache and MCentral free lists | |
| // may or may not be zeroed. They are zeroed if and only if | |
| // the second word of the object is zero. A span in the | |
| // page heap is zeroed unless s->needzero is set. When a span | |
| // is allocated to break into small objects, it is zeroed if needed | |
| // and s->needzero is set. There are two main benefits to delaying the | |
| // zeroing this way: | |
| // | |
| // 1. stack frames allocated from the small object lists | |
| // or the page heap can avoid zeroing altogether. | |
| // 2. the cost of zeroing when reusing a small object is | |
| // charged to the mutator, not the garbage collector. | |
| // | |
| // This C code was written with an eye toward translating to Go | |
| // in the future. Methods have the form Type_Method(Type *t, ...). | |
| const ( | |
| _PageShift = 13 | |
| _PageSize = 1 << _PageShift | |
| _PageMask = _PageSize - 1 | |
| ) | |
| const ( | |
| // _64bit = 1 on 64-bit systems, 0 on 32-bit systems | |
| _64bit = 1 << (^uintptr(0) >> 63) / 2 | |
| // Computed constant. The definition of MaxSmallSize and the | |
| // algorithm in msize.c produce some number of different allocation | |
| // size classes. NumSizeClasses is that number. It's needed here | |
| // because there are static arrays of this length; when msize runs its | |
| // size choosing algorithm it double-checks that NumSizeClasses agrees. | |
| _NumSizeClasses = 67 | |
| // Tunable constants. | |
| _MaxSmallSize = 32 << 10 | |
| // Tiny allocator parameters, see "Tiny allocator" comment in malloc.go. | |
| _TinySize = 16 | |
| _TinySizeClass = 2 | |
| _FixAllocChunk = 16 << 10 // Chunk size for FixAlloc | |
| _MaxMHeapList = 1 << (20 - _PageShift) // Maximum page length for fixed-size list in MHeap. | |
| _HeapAllocChunk = 1 << 20 // Chunk size for heap growth | |
| // Per-P, per order stack segment cache size. | |
| _StackCacheSize = 32 * 1024 | |
| // Number of orders that get caching. Order 0 is FixedStack | |
| // and each successive order is twice as large. | |
| // We want to cache 2KB, 4KB, 8KB, and 16KB stacks. Larger stacks | |
| // will be allocated directly. | |
| // Since FixedStack is different on different systems, we | |
| // must vary NumStackOrders to keep the same maximum cached size. | |
| // OS | FixedStack | NumStackOrders | |
| // -----------------+------------+--------------- | |
| // linux/darwin/bsd | 2KB | 4 | |
| // windows/32 | 4KB | 3 | |
| // windows/64 | 8KB | 2 | |
| // plan9 | 4KB | 3 | |
| _NumStackOrders = 4 - ptrSize/4*goos_windows - 1*goos_plan9 | |
| // Number of bits in page to span calculations (4k pages). | |
| // On Windows 64-bit we limit the arena to 32GB or 35 bits. | |
| // Windows counts memory used by page table into committed memory | |
| // of the process, so we can't reserve too much memory. | |
| // See http://golang.org/issue/5402 and http://golang.org/issue/5236. | |
| // On other 64-bit platforms, we limit the arena to 128GB, or 37 bits. | |
| // On 32-bit, we don't bother limiting anything, so we use the full 32-bit address. | |
| _MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows))*37 + (1-_64bit)*32 | |
| _MHeapMap_Bits = _MHeapMap_TotalBits - _PageShift | |
| _MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1) | |
| // Max number of threads to run garbage collection. | |
| // 2, 3, and 4 are all plausible maximums depending | |
| // on the hardware details of the machine. The garbage | |
| // collector scales well to 32 cpus. | |
| _MaxGcproc = 32 | |
| ) | |
| // A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).) | |
| // Since assignments to mlink.next will result in a write barrier being preformed | |
| // this can not be used by some of the internal GC structures. For example when | |
| // the sweeper is placing an unmarked object on the free list it does not want the | |
| // write barrier to be called since that could result in the object being reachable. | |
| type mlink struct { | |
| next *mlink | |
| } | |
| // A gclink is a node in a linked list of blocks, like mlink, | |
| // but it is opaque to the garbage collector. | |
| // The GC does not trace the pointers during collection, | |
| // and the compiler does not emit write barriers for assignments | |
| // of gclinkptr values. Code should store references to gclinks | |
| // as gclinkptr, not as *gclink. | |
| type gclink struct { | |
| next gclinkptr | |
| } | |
| // A gclinkptr is a pointer to a gclink, but it is opaque | |
| // to the garbage collector. | |
| type gclinkptr uintptr | |
| // ptr returns the *gclink form of p. | |
| // The result should be used for accessing fields, not stored | |
| // in other data structures. | |
| func (p gclinkptr) ptr() *gclink { | |
| return (*gclink)(unsafe.Pointer(p)) | |
| } | |
| // sysAlloc obtains a large chunk of zeroed memory from the | |
| // operating system, typically on the order of a hundred kilobytes | |
| // or a megabyte. | |
| // NOTE: sysAlloc returns OS-aligned memory, but the heap allocator | |
| // may use larger alignment, so the caller must be careful to realign the | |
| // memory obtained by sysAlloc. | |
| // | |
| // SysUnused notifies the operating system that the contents | |
| // of the memory region are no longer needed and can be reused | |
| // for other purposes. | |
| // SysUsed notifies the operating system that the contents | |
| // of the memory region are needed again. | |
| // | |
| // SysFree returns it unconditionally; this is only used if | |
| // an out-of-memory error has been detected midway through | |
| // an allocation. It is okay if SysFree is a no-op. | |
| // | |
| // SysReserve reserves address space without allocating memory. | |
| // If the pointer passed to it is non-nil, the caller wants the | |
| // reservation there, but SysReserve can still choose another | |
| // location if that one is unavailable. On some systems and in some | |
| // cases SysReserve will simply check that the address space is | |
| // available and not actually reserve it. If SysReserve returns | |
| // non-nil, it sets *reserved to true if the address space is | |
| // reserved, false if it has merely been checked. | |
| // NOTE: SysReserve returns OS-aligned memory, but the heap allocator | |
| // may use larger alignment, so the caller must be careful to realign the | |
| // memory obtained by sysAlloc. | |
| // | |
| // SysMap maps previously reserved address space for use. | |
| // The reserved argument is true if the address space was really | |
| // reserved, not merely checked. | |
| // | |
| // SysFault marks a (already sysAlloc'd) region to fault | |
| // if accessed. Used only for debugging the runtime. | |
| // FixAlloc is a simple free-list allocator for fixed size objects. | |
| // Malloc uses a FixAlloc wrapped around sysAlloc to manages its | |
| // MCache and MSpan objects. | |
| // | |
| // Memory returned by FixAlloc_Alloc is not zeroed. | |
| // The caller is responsible for locking around FixAlloc calls. | |
| // Callers can keep state in the object but the first word is | |
| // smashed by freeing and reallocating. | |
| type fixalloc struct { | |
| size uintptr | |
| first unsafe.Pointer // go func(unsafe.pointer, unsafe.pointer); f(arg, p) called first time p is returned | |
| arg unsafe.Pointer | |
| list *mlink | |
| chunk *byte | |
| nchunk uint32 | |
| inuse uintptr // in-use bytes now | |
| stat *uint64 | |
| } | |
| // Statistics. | |
| // Shared with Go: if you edit this structure, also edit type MemStats in mem.go. | |
| type mstats struct { | |
| // General statistics. | |
| alloc uint64 // bytes allocated and still in use | |
| total_alloc uint64 // bytes allocated (even if freed) | |
| sys uint64 // bytes obtained from system (should be sum of xxx_sys below, no locking, approximate) | |
| nlookup uint64 // number of pointer lookups | |
| nmalloc uint64 // number of mallocs | |
| nfree uint64 // number of frees | |
| // Statistics about malloc heap. | |
| // protected by mheap.lock | |
| heap_alloc uint64 // bytes allocated and still in use | |
| heap_sys uint64 // bytes obtained from system | |
| heap_idle uint64 // bytes in idle spans | |
| heap_inuse uint64 // bytes in non-idle spans | |
| heap_released uint64 // bytes released to the os | |
| heap_objects uint64 // total number of allocated objects | |
| // Statistics about allocation of low-level fixed-size structures. | |
| // Protected by FixAlloc locks. | |
| stacks_inuse uint64 // this number is included in heap_inuse above | |
| stacks_sys uint64 // always 0 in mstats | |
| mspan_inuse uint64 // mspan structures | |
| mspan_sys uint64 | |
| mcache_inuse uint64 // mcache structures | |
| mcache_sys uint64 | |
| buckhash_sys uint64 // profiling bucket hash table | |
| gc_sys uint64 | |
| other_sys uint64 | |
| // Statistics about garbage collector. | |
| // Protected by mheap or stopping the world during GC. | |
| next_gc uint64 // next gc (in heap_alloc time) | |
| last_gc uint64 // last gc (in absolute time) | |
| pause_total_ns uint64 | |
| pause_ns [256]uint64 // circular buffer of recent gc pause lengths | |
| pause_end [256]uint64 // circular buffer of recent gc end times (nanoseconds since 1970) | |
| numgc uint32 | |
| enablegc bool | |
| debuggc bool | |
| // Statistics about allocation size classes. | |
| by_size [_NumSizeClasses]struct { | |
| size uint32 | |
| nmalloc uint64 | |
| nfree uint64 | |
| } | |
| tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly | |
| } | |
| var memstats mstats | |
| // Size classes. Computed and initialized by InitSizes. | |
| // | |
| // SizeToClass(0 <= n <= MaxSmallSize) returns the size class, | |
| // 1 <= sizeclass < NumSizeClasses, for n. | |
| // Size class 0 is reserved to mean "not small". | |
| // | |
| // class_to_size[i] = largest size in class i | |
| // class_to_allocnpages[i] = number of pages to allocate when | |
| // making new objects in class i | |
| var class_to_size [_NumSizeClasses]int32 | |
| var class_to_allocnpages [_NumSizeClasses]int32 | |
| var size_to_class8 [1024/8 + 1]int8 | |
| var size_to_class128 [(_MaxSmallSize-1024)/128 + 1]int8 | |
| type mcachelist struct { | |
| list *mlink | |
| nlist uint32 | |
| } | |
| type stackfreelist struct { | |
| list gclinkptr // linked list of free stacks | |
| size uintptr // total size of stacks in list | |
| } | |
| // Per-thread (in Go, per-P) cache for small objects. | |
| // No locking needed because it is per-thread (per-P). | |
| type mcache struct { | |
| // The following members are accessed on every malloc, | |
| // so they are grouped here for better caching. | |
| next_sample int32 // trigger heap sample after allocating this many bytes | |
| local_cachealloc intptr // bytes allocated (or freed) from cache since last lock of heap | |
| // Allocator cache for tiny objects w/o pointers. | |
| // See "Tiny allocator" comment in malloc.go. | |
| tiny unsafe.Pointer | |
| tinyoffset uintptr | |
| local_tinyallocs uintptr // number of tiny allocs not counted in other stats | |
| // The rest is not accessed on every malloc. | |
| alloc [_NumSizeClasses]*mspan // spans to allocate from | |
| stackcache [_NumStackOrders]stackfreelist | |
| sudogcache *sudog | |
| // Local allocator stats, flushed during GC. | |
| local_nlookup uintptr // number of pointer lookups | |
| local_largefree uintptr // bytes freed for large objects (>maxsmallsize) | |
| local_nlargefree uintptr // number of frees for large objects (>maxsmallsize) | |
| local_nsmallfree [_NumSizeClasses]uintptr // number of frees for small objects (<=maxsmallsize) | |
| } | |
| const ( | |
| _KindSpecialFinalizer = 1 | |
| _KindSpecialProfile = 2 | |
| // Note: The finalizer special must be first because if we're freeing | |
| // an object, a finalizer special will cause the freeing operation | |
| // to abort, and we want to keep the other special records around | |
| // if that happens. | |
| ) | |
| type special struct { | |
| next *special // linked list in span | |
| offset uint16 // span offset of object | |
| kind byte // kind of special | |
| } | |
| // The described object has a finalizer set for it. | |
| type specialfinalizer struct { | |
| special special | |
| fn *funcval | |
| nret uintptr | |
| fint *_type | |
| ot *ptrtype | |
| } | |
| // The described object is being heap profiled. | |
| type specialprofile struct { | |
| special special | |
| b *bucket | |
| } | |
| // An MSpan is a run of pages. | |
| const ( | |
| _MSpanInUse = iota // allocated for garbage collected heap | |
| _MSpanStack // allocated for use by stack allocator | |
| _MSpanFree | |
| _MSpanListHead | |
| _MSpanDead | |
| ) | |
| type mspan struct { | |
| next *mspan // in a span linked list | |
| prev *mspan // in a span linked list | |
| start pageID // starting page number | |
| npages uintptr // number of pages in span | |
| freelist gclinkptr // list of free objects | |
| // sweep generation: | |
| // if sweepgen == h->sweepgen - 2, the span needs sweeping | |
| // if sweepgen == h->sweepgen - 1, the span is currently being swept | |
| // if sweepgen == h->sweepgen, the span is swept and ready to use | |
| // h->sweepgen is incremented by 2 after every GC | |
| sweepgen uint32 | |
| ref uint16 // capacity - number of objects in freelist | |
| sizeclass uint8 // size class | |
| incache bool // being used by an mcache | |
| state uint8 // mspaninuse etc | |
| needzero uint8 // needs to be zeroed before allocation | |
| elemsize uintptr // computed from sizeclass or from npages | |
| unusedsince int64 // first time spotted by gc in mspanfree state | |
| npreleased uintptr // number of pages released to the os | |
| limit uintptr // end of data in span | |
| speciallock mutex // guards specials list | |
| specials *special // linked list of special records sorted by offset. | |
| } | |
| func (s *mspan) base() uintptr { | |
| return uintptr(s.start << _PageShift) | |
| } | |
| func (s *mspan) layout() (size, n, total uintptr) { | |
| total = s.npages << _PageShift | |
| size = s.elemsize | |
| if size > 0 { | |
| n = total / size | |
| } | |
| return | |
| } | |
| // Every MSpan is in one doubly-linked list, | |
| // either one of the MHeap's free lists or one of the | |
| // MCentral's span lists. We use empty MSpan structures as list heads. | |
| // Central list of free objects of a given size. | |
| type mcentral struct { | |
| lock mutex | |
| sizeclass int32 | |
| nonempty mspan // list of spans with a free object | |
| empty mspan // list of spans with no free objects (or cached in an mcache) | |
| } | |
| // Main malloc heap. | |
| // The heap itself is the "free[]" and "large" arrays, | |
| // but all the other global data is here too. | |
| type mheap struct { | |
| lock mutex | |
| free [_MaxMHeapList]mspan // free lists of given length | |
| freelarge mspan // free lists length >= _MaxMHeapList | |
| busy [_MaxMHeapList]mspan // busy lists of large objects of given length | |
| busylarge mspan // busy lists of large objects length >= _MaxMHeapList | |
| allspans **mspan // all spans out there | |
| gcspans **mspan // copy of allspans referenced by gc marker or sweeper | |
| nspan uint32 | |
| sweepgen uint32 // sweep generation, see comment in mspan | |
| sweepdone uint32 // all spans are swept | |
| // span lookup | |
| spans **mspan | |
| spans_mapped uintptr | |
| // range of addresses we might see in the heap | |
| bitmap uintptr | |
| bitmap_mapped uintptr | |
| arena_start uintptr | |
| arena_used uintptr | |
| arena_end uintptr | |
| arena_reserved bool | |
| // write barrier shadow data+heap. | |
| // 64-bit systems only, enabled by GODEBUG=wbshadow=1. | |
| shadow_enabled bool // shadow should be updated and checked | |
| shadow_reserved bool // shadow memory is reserved | |
| shadow_heap uintptr // heap-addr + shadow_heap = shadow heap addr | |
| shadow_data uintptr // data-addr + shadow_data = shadow data addr | |
| data_start uintptr // start of shadowed data addresses | |
| data_end uintptr // end of shadowed data addresses | |
| // central free lists for small size classes. | |
| // the padding makes sure that the MCentrals are | |
| // spaced CacheLineSize bytes apart, so that each MCentral.lock | |
| // gets its own cache line. | |
| central [_NumSizeClasses]struct { | |
| mcentral mcentral | |
| pad [_CacheLineSize]byte | |
| } | |
| spanalloc fixalloc // allocator for span* | |
| cachealloc fixalloc // allocator for mcache* | |
| specialfinalizeralloc fixalloc // allocator for specialfinalizer* | |
| specialprofilealloc fixalloc // allocator for specialprofile* | |
| speciallock mutex // lock for sepcial record allocators. | |
| // Malloc stats. | |
| largefree uint64 // bytes freed for large objects (>maxsmallsize) | |
| nlargefree uint64 // number of frees for large objects (>maxsmallsize) | |
| nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize) | |
| } | |
| var mheap_ mheap | |
| const ( | |
| // flags to malloc | |
| _FlagNoScan = 1 << 0 // GC doesn't have to scan object | |
| _FlagNoZero = 1 << 1 // don't zero memory | |
| ) | |
| // NOTE: Layout known to queuefinalizer. | |
| type finalizer struct { | |
| fn *funcval // function to call | |
| arg unsafe.Pointer // ptr to object | |
| nret uintptr // bytes of return values from fn | |
| fint *_type // type of first argument of fn | |
| ot *ptrtype // type of ptr to object | |
| } | |
| type finblock struct { | |
| alllink *finblock | |
| next *finblock | |
| cnt int32 | |
| _ int32 | |
| fin [(_FinBlockSize - 2*ptrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer | |
| } | |
| // Information from the compiler about the layout of stack frames. | |
| type bitvector struct { | |
| n int32 // # of bits | |
| bytedata *uint8 | |
| } | |
| type stackmap struct { | |
| n int32 // number of bitmaps | |
| nbit int32 // number of bits in each bitmap | |
| bytedata [1]byte // bitmaps, each starting on a 32-bit boundary | |
| } | |
| // Returns pointer map data for the given stackmap index | |
| // (the index is encoded in PCDATA_StackMapIndex). | |
| // defined in mgc0.go |