Source file src/runtime/malloc.go
1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Memory allocator. 6 // 7 // This was originally based on tcmalloc, but has diverged quite a bit. 8 // http://goog-perftools.sourceforge.net/doc/tcmalloc.html 9 10 // The main allocator works in runs of pages. 11 // Small allocation sizes (up to and including 32 kB) are 12 // rounded to one of about 70 size classes, each of which 13 // has its own free set of objects of exactly that size. 14 // Any free page of memory can be split into a set of objects 15 // of one size class, which are then managed using a free bitmap. 16 // 17 // The allocator's data structures are: 18 // 19 // fixalloc: a free-list allocator for fixed-size off-heap objects, 20 // used to manage storage used by the allocator. 21 // mheap: the malloc heap, managed at page (8192-byte) granularity. 22 // mspan: a run of in-use pages managed by the mheap. 23 // mcentral: collects all spans of a given size class. 24 // mcache: a per-P cache of mspans with free space. 25 // mstats: allocation statistics. 26 // 27 // Allocating a small object proceeds up a hierarchy of caches: 28 // 29 // 1. Round the size up to one of the small size classes 30 // and look in the corresponding mspan in this P's mcache. 31 // Scan the mspan's free bitmap to find a free slot. 32 // If there is a free slot, allocate it. 33 // This can all be done without acquiring a lock. 34 // 35 // 2. If the mspan has no free slots, obtain a new mspan 36 // from the mcentral's list of mspans of the required size 37 // class that have free space. 38 // Obtaining a whole span amortizes the cost of locking 39 // the mcentral. 40 // 41 // 3. If the mcentral's mspan list is empty, obtain a run 42 // of pages from the mheap to use for the mspan. 43 // 44 // 4. If the mheap is empty or has no page runs large enough, 45 // allocate a new group of pages (at least 1MB) from the 46 // operating system. Allocating a large run of pages 47 // amortizes the cost of talking to the operating system. 48 // 49 // Sweeping an mspan and freeing objects on it proceeds up a similar 50 // hierarchy: 51 // 52 // 1. If the mspan is being swept in response to allocation, it 53 // is returned to the mcache to satisfy the allocation. 54 // 55 // 2. Otherwise, if the mspan still has allocated objects in it, 56 // it is placed on the mcentral free list for the mspan's size 57 // class. 58 // 59 // 3. Otherwise, if all objects in the mspan are free, the mspan's 60 // pages are returned to the mheap and the mspan is now dead. 61 // 62 // Allocating and freeing a large object uses the mheap 63 // directly, bypassing the mcache and mcentral. 64 // 65 // If mspan.needzero is false, then free object slots in the mspan are 66 // already zeroed. Otherwise if needzero is true, objects are zeroed as 67 // they are allocated. There are various benefits to delaying zeroing 68 // this way: 69 // 70 // 1. Stack frame allocation can avoid zeroing altogether. 71 // 72 // 2. It exhibits better temporal locality, since the program is 73 // probably about to write to the memory. 74 // 75 // 3. We don't zero pages that never get reused. 76 77 // Virtual memory layout 78 // 79 // The heap consists of a set of arenas, which are 64MB on 64-bit and 80 // 4MB on 32-bit (heapArenaBytes). Each arena's start address is also 81 // aligned to the arena size. 82 // 83 // Each arena has an associated heapArena object that stores the 84 // metadata for that arena: the heap bitmap for all words in the arena 85 // and the span map for all pages in the arena. heapArena objects are 86 // themselves allocated off-heap. 87 // 88 // Since arenas are aligned, the address space can be viewed as a 89 // series of arena frames. The arena map (mheap_.arenas) maps from 90 // arena frame number to *heapArena, or nil for parts of the address 91 // space not backed by the Go heap. The arena map is structured as a 92 // two-level array consisting of a "L1" arena map and many "L2" arena 93 // maps; however, since arenas are large, on many architectures, the 94 // arena map consists of a single, large L2 map. 95 // 96 // The arena map covers the entire possible address space, allowing 97 // the Go heap to use any part of the address space. The allocator 98 // attempts to keep arenas contiguous so that large spans (and hence 99 // large objects) can cross arenas. 100 101 package runtime 102 103 import ( 104 "internal/goarch" 105 "internal/goexperiment" 106 "internal/goos" 107 "internal/runtime/atomic" 108 "internal/runtime/gc" 109 "internal/runtime/math" 110 "internal/runtime/sys" 111 "unsafe" 112 ) 113 114 const ( 115 maxTinySize = _TinySize 116 tinySizeClass = _TinySizeClass 117 maxSmallSize = gc.MaxSmallSize 118 pageSize = 1 << gc.PageShift 119 pageMask = pageSize - 1 120 121 // Unused. Left for viewcore. 122 _PageSize = pageSize 123 minSizeForMallocHeader = gc.MinSizeForMallocHeader 124 mallocHeaderSize = gc.MallocHeaderSize 125 126 // _64bit = 1 on 64-bit systems, 0 on 32-bit systems 127 _64bit = 1 << (^uintptr(0) >> 63) / 2 128 129 // Tiny allocator parameters, see "Tiny allocator" comment in malloc.go. 130 _TinySize = gc.TinySize 131 _TinySizeClass = int8(gc.TinySizeClass) 132 133 _FixAllocChunk = 16 << 10 // Chunk size for FixAlloc 134 135 // Per-P, per order stack segment cache size. 136 _StackCacheSize = 32 * 1024 137 138 // Number of orders that get caching. Order 0 is FixedStack 139 // and each successive order is twice as large. 140 // We want to cache 2KB, 4KB, 8KB, and 16KB stacks. Larger stacks 141 // will be allocated directly. 142 // Since FixedStack is different on different systems, we 143 // must vary NumStackOrders to keep the same maximum cached size. 144 // OS | FixedStack | NumStackOrders 145 // -----------------+------------+--------------- 146 // linux/darwin/bsd | 2KB | 4 147 // windows/32 | 4KB | 3 148 // windows/64 | 8KB | 2 149 // plan9 | 4KB | 3 150 _NumStackOrders = 4 - goarch.PtrSize/4*goos.IsWindows - 1*goos.IsPlan9 151 152 // heapAddrBits is the number of bits in a heap address. On 153 // amd64, addresses are sign-extended beyond heapAddrBits. On 154 // other arches, they are zero-extended. 155 // 156 // On most 64-bit platforms, we limit this to 48 bits based on a 157 // combination of hardware and OS limitations. 158 // 159 // amd64 hardware limits addresses to 48 bits, sign-extended 160 // to 64 bits. Addresses where the top 16 bits are not either 161 // all 0 or all 1 are "non-canonical" and invalid. Because of 162 // these "negative" addresses, we offset addresses by 1<<47 163 // (arenaBaseOffset) on amd64 before computing indexes into 164 // the heap arenas index. In 2017, amd64 hardware added 165 // support for 57 bit addresses; however, currently only Linux 166 // supports this extension and the kernel will never choose an 167 // address above 1<<47 unless mmap is called with a hint 168 // address above 1<<47 (which we never do). 169 // 170 // arm64 hardware (as of ARMv8) limits user addresses to 48 171 // bits, in the range [0, 1<<48). 172 // 173 // ppc64, mips64, and s390x support arbitrary 64 bit addresses 174 // in hardware. On Linux, Go leans on stricter OS limits. Based 175 // on Linux's processor.h, the user address space is limited as 176 // follows on 64-bit architectures: 177 // 178 // Architecture Name Maximum Value (exclusive) 179 // --------------------------------------------------------------------- 180 // amd64 TASK_SIZE_MAX 0x007ffffffff000 (47 bit addresses) 181 // arm64 TASK_SIZE_64 0x01000000000000 (48 bit addresses) 182 // ppc64{,le} TASK_SIZE_USER64 0x00400000000000 (46 bit addresses) 183 // mips64{,le} TASK_SIZE64 0x00010000000000 (40 bit addresses) 184 // s390x TASK_SIZE 1<<64 (64 bit addresses) 185 // 186 // These limits may increase over time, but are currently at 187 // most 48 bits except on s390x. On all architectures, Linux 188 // starts placing mmap'd regions at addresses that are 189 // significantly below 48 bits, so even if it's possible to 190 // exceed Go's 48 bit limit, it's extremely unlikely in 191 // practice. 192 // 193 // On 32-bit platforms, we accept the full 32-bit address 194 // space because doing so is cheap. 195 // mips32 only has access to the low 2GB of virtual memory, so 196 // we further limit it to 31 bits. 197 // 198 // On ios/arm64, although 64-bit pointers are presumably 199 // available, pointers are truncated to 33 bits in iOS <14. 200 // Furthermore, only the top 4 GiB of the address space are 201 // actually available to the application. In iOS >=14, more 202 // of the address space is available, and the OS can now 203 // provide addresses outside of those 33 bits. Pick 40 bits 204 // as a reasonable balance between address space usage by the 205 // page allocator, and flexibility for what mmap'd regions 206 // we'll accept for the heap. We can't just move to the full 207 // 48 bits because this uses too much address space for older 208 // iOS versions. 209 // TODO(mknyszek): Once iOS <14 is deprecated, promote ios/arm64 210 // to a 48-bit address space like every other arm64 platform. 211 // 212 // WebAssembly currently has a limit of 4GB linear memory. 213 heapAddrBits = (_64bit*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64))*48 + (1-_64bit+goarch.IsWasm)*(32-(goarch.IsMips+goarch.IsMipsle)) + 40*goos.IsIos*goarch.IsArm64 214 215 // maxAlloc is the maximum size of an allocation. On 64-bit, 216 // it's theoretically possible to allocate 1<<heapAddrBits bytes. On 217 // 32-bit, however, this is one less than 1<<32 because the 218 // number of bytes in the address space doesn't actually fit 219 // in a uintptr. 220 maxAlloc = (1 << heapAddrBits) - (1-_64bit)*1 221 222 // The number of bits in a heap address, the size of heap 223 // arenas, and the L1 and L2 arena map sizes are related by 224 // 225 // (1 << addr bits) = arena size * L1 entries * L2 entries 226 // 227 // Currently, we balance these as follows: 228 // 229 // Platform Addr bits Arena size L1 entries L2 entries 230 // -------------- --------- ---------- ---------- ----------- 231 // */64-bit 48 64MB 1 4M (32MB) 232 // windows/64-bit 48 4MB 64 1M (8MB) 233 // ios/arm64 40 4MB 1 256K (2MB) 234 // */32-bit 32 4MB 1 1024 (4KB) 235 // */mips(le) 31 4MB 1 512 (2KB) 236 // wasm 32 512KB 1 8192 (64KB) 237 238 // heapArenaBytes is the size of a heap arena. The heap 239 // consists of mappings of size heapArenaBytes, aligned to 240 // heapArenaBytes. The initial heap mapping is one arena. 241 // 242 // This is currently 64MB on 64-bit non-Windows, 4MB on 243 // 32-bit and on Windows, and 512KB on Wasm. We use smaller 244 // arenas on Windows because all committed memory is charged 245 // to the process, even if it's not touched. Hence, for 246 // processes with small heaps, the mapped arena space needs 247 // to be commensurate. This is particularly important with 248 // the race detector, since it significantly amplifies the 249 // cost of committed memory. We use smaller arenas on Wasm 250 // because some Wasm programs have very small heap, and 251 // everything in the Wasm linear memory is charged. 252 heapArenaBytes = 1 << logHeapArenaBytes 253 254 heapArenaWords = heapArenaBytes / goarch.PtrSize 255 256 // logHeapArenaBytes is log_2 of heapArenaBytes. For clarity, 257 // prefer using heapArenaBytes where possible (we need the 258 // constant to compute some other constants). 259 logHeapArenaBytes = (6+20)*(_64bit*(1-goos.IsWindows)*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64)) + (2+20)*(_64bit*goos.IsWindows) + (2+20)*(1-_64bit) + (9+10)*goarch.IsWasm + (2+20)*goos.IsIos*goarch.IsArm64 260 261 // heapArenaBitmapWords is the size of each heap arena's bitmap in uintptrs. 262 heapArenaBitmapWords = heapArenaWords / (8 * goarch.PtrSize) 263 264 pagesPerArena = heapArenaBytes / pageSize 265 266 // arenaL1Bits is the number of bits of the arena number 267 // covered by the first level arena map. 268 // 269 // This number should be small, since the first level arena 270 // map requires PtrSize*(1<<arenaL1Bits) of space in the 271 // binary's BSS. It can be zero, in which case the first level 272 // index is effectively unused. There is a performance benefit 273 // to this, since the generated code can be more efficient, 274 // but comes at the cost of having a large L2 mapping. 275 // 276 // We use the L1 map on 64-bit Windows because the arena size 277 // is small, but the address space is still 48 bits, and 278 // there's a high cost to having a large L2. 279 arenaL1Bits = 6 * (_64bit * goos.IsWindows) 280 281 // arenaL2Bits is the number of bits of the arena number 282 // covered by the second level arena index. 283 // 284 // The size of each arena map allocation is proportional to 285 // 1<<arenaL2Bits, so it's important that this not be too 286 // large. 48 bits leads to 32MB arena index allocations, which 287 // is about the practical threshold. 288 arenaL2Bits = heapAddrBits - logHeapArenaBytes - arenaL1Bits 289 290 // arenaL1Shift is the number of bits to shift an arena frame 291 // number by to compute an index into the first level arena map. 292 arenaL1Shift = arenaL2Bits 293 294 // arenaBits is the total bits in a combined arena map index. 295 // This is split between the index into the L1 arena map and 296 // the L2 arena map. 297 arenaBits = arenaL1Bits + arenaL2Bits 298 299 // arenaBaseOffset is the pointer value that corresponds to 300 // index 0 in the heap arena map. 301 // 302 // On amd64, the address space is 48 bits, sign extended to 64 303 // bits. This offset lets us handle "negative" addresses (or 304 // high addresses if viewed as unsigned). 305 // 306 // On aix/ppc64, this offset allows to keep the heapAddrBits to 307 // 48. Otherwise, it would be 60 in order to handle mmap addresses 308 // (in range 0x0a00000000000000 - 0x0afffffffffffff). But in this 309 // case, the memory reserved in (s *pageAlloc).init for chunks 310 // is causing important slowdowns. 311 // 312 // On other platforms, the user address space is contiguous 313 // and starts at 0, so no offset is necessary. 314 arenaBaseOffset = 0xffff800000000000*goarch.IsAmd64 + 0x0a00000000000000*goos.IsAix 315 // A typed version of this constant that will make it into DWARF (for viewcore). 316 arenaBaseOffsetUintptr = uintptr(arenaBaseOffset) 317 318 // Max number of threads to run garbage collection. 319 // 2, 3, and 4 are all plausible maximums depending 320 // on the hardware details of the machine. The garbage 321 // collector scales well to 32 cpus. 322 _MaxGcproc = 32 323 324 // minLegalPointer is the smallest possible legal pointer. 325 // This is the smallest possible architectural page size, 326 // since we assume that the first page is never mapped. 327 // 328 // This should agree with minZeroPage in the compiler. 329 minLegalPointer uintptr = 4096 330 331 // minHeapForMetadataHugePages sets a threshold on when certain kinds of 332 // heap metadata, currently the arenas map L2 entries and page alloc bitmap 333 // mappings, are allowed to be backed by huge pages. If the heap goal ever 334 // exceeds this threshold, then huge pages are enabled. 335 // 336 // These numbers are chosen with the assumption that huge pages are on the 337 // order of a few MiB in size. 338 // 339 // The kind of metadata this applies to has a very low overhead when compared 340 // to address space used, but their constant overheads for small heaps would 341 // be very high if they were to be backed by huge pages (e.g. a few MiB makes 342 // a huge difference for an 8 MiB heap, but barely any difference for a 1 GiB 343 // heap). The benefit of huge pages is also not worth it for small heaps, 344 // because only a very, very small part of the metadata is used for small heaps. 345 // 346 // N.B. If the heap goal exceeds the threshold then shrinks to a very small size 347 // again, then huge pages will still be enabled for this mapping. The reason is that 348 // there's no point unless we're also returning the physical memory for these 349 // metadata mappings back to the OS. That would be quite complex to do in general 350 // as the heap is likely fragmented after a reduction in heap size. 351 minHeapForMetadataHugePages = 1 << 30 352 353 // randomizeHeapBase indicates if the heap base address should be randomized. 354 // See comment in mallocinit for how the randomization is performed. 355 randomizeHeapBase = goexperiment.RandomizedHeapBase64 && goarch.PtrSize == 8 && !isSbrkPlatform && !raceenabled && !msanenabled && !asanenabled 356 357 // randHeapAddrBits is the number of address bits usable by the randomized 358 // heap base. heapAddrBits is 48 on most platforms, but we only use 47 of 359 // those bits in order to provide a good amount of room for the heap to 360 // grow contiguously. On amd64, there are 48 bits, but the top bit is sign 361 // extended, so we throw away another bit, just to be safe. 362 randHeapAddrBits = heapAddrBits - 1 - goarch.IsAmd64 363 364 // randHeapBasePrefixMask clears the top byte of the randomized heap base 365 // address -- the byte hint generation replaces with randHeapBasePrefix+i. 366 // The prefix occupies bits [randHeapAddrBits-8, randHeapAddrBits), so the 367 // mask must be defined from randHeapAddrBits, not heapAddrBits: a wider 368 // mask would let stray randHeapBase bits overlap the prefix byte in the 369 // OR that hint generation performs, and wherever such a stray bit is 1, 370 // the corresponding bit of every generated prefix is forced to 1, 371 // collapsing distinct prefixes into duplicate hint addresses. 372 randHeapBasePrefixMask = ^uintptr(0xff << (randHeapAddrBits - 8)) 373 ) 374 375 // physPageSize is the size in bytes of the OS's physical pages. 376 // Mapping and unmapping operations must be done at multiples of 377 // physPageSize. 378 // 379 // This must be set by the OS init code (typically in osinit) before 380 // mallocinit. 381 var physPageSize uintptr 382 383 // physHugePageSize is the size in bytes of the OS's default physical huge 384 // page size whose allocation is opaque to the application. It is assumed 385 // and verified to be a power of two. 386 // 387 // If set, this must be set by the OS init code (typically in osinit) before 388 // mallocinit. However, setting it at all is optional, and leaving the default 389 // value is always safe (though potentially less efficient). 390 // 391 // Since physHugePageSize is always assumed to be a power of two, 392 // physHugePageShift is defined as physHugePageSize == 1 << physHugePageShift. 393 // The purpose of physHugePageShift is to avoid doing divisions in 394 // performance critical functions. 395 var ( 396 physHugePageSize uintptr 397 physHugePageShift uint 398 ) 399 400 var ( 401 // heapRandSeed is a random value that is populated in mallocinit if 402 // randomizeHeapBase is set. It is used in mallocinit, and mheap.grow, to 403 // randomize the base heap address. 404 heapRandSeed uintptr 405 heapRandSeedBitsRemaining int 406 ) 407 408 func nextHeapRandBits(bits int) uintptr { 409 if bits > heapRandSeedBitsRemaining { 410 throw("not enough heapRandSeed bits remaining") 411 } 412 r := heapRandSeed >> (64 - bits) 413 heapRandSeed <<= bits 414 heapRandSeedBitsRemaining -= bits 415 return r 416 } 417 418 func mallocinit() { 419 if gc.SizeClassToSize[tinySizeClass] != maxTinySize { 420 throw("bad TinySizeClass") 421 } 422 423 if heapArenaBitmapWords&(heapArenaBitmapWords-1) != 0 { 424 // heapBits expects modular arithmetic on bitmap 425 // addresses to work. 426 throw("heapArenaBitmapWords not a power of 2") 427 } 428 429 // Check physPageSize. 430 if physPageSize == 0 { 431 // The OS init code failed to fetch the physical page size. 432 throw("failed to get system page size") 433 } 434 if physPageSize > maxPhysPageSize { 435 print("system page size (", physPageSize, ") is larger than maximum page size (", maxPhysPageSize, ")\n") 436 throw("bad system page size") 437 } 438 if physPageSize < minPhysPageSize { 439 print("system page size (", physPageSize, ") is smaller than minimum page size (", minPhysPageSize, ")\n") 440 throw("bad system page size") 441 } 442 if physPageSize&(physPageSize-1) != 0 { 443 print("system page size (", physPageSize, ") must be a power of 2\n") 444 throw("bad system page size") 445 } 446 if physHugePageSize&(physHugePageSize-1) != 0 { 447 print("system huge page size (", physHugePageSize, ") must be a power of 2\n") 448 throw("bad system huge page size") 449 } 450 if physHugePageSize > maxPhysHugePageSize { 451 // physHugePageSize is greater than the maximum supported huge page size. 452 // Don't throw here, like in the other cases, since a system configured 453 // in this way isn't wrong, we just don't have the code to support them. 454 // Instead, silently set the huge page size to zero. 455 physHugePageSize = 0 456 } 457 if physHugePageSize != 0 { 458 // Since physHugePageSize is a power of 2, it suffices to increase 459 // physHugePageShift until 1<<physHugePageShift == physHugePageSize. 460 for 1<<physHugePageShift != physHugePageSize { 461 physHugePageShift++ 462 } 463 } 464 if pagesPerArena%pagesPerSpanRoot != 0 { 465 print("pagesPerArena (", pagesPerArena, ") is not divisible by pagesPerSpanRoot (", pagesPerSpanRoot, ")\n") 466 throw("bad pagesPerSpanRoot") 467 } 468 if pagesPerArena%pagesPerReclaimerChunk != 0 { 469 print("pagesPerArena (", pagesPerArena, ") is not divisible by pagesPerReclaimerChunk (", pagesPerReclaimerChunk, ")\n") 470 throw("bad pagesPerReclaimerChunk") 471 } 472 // Check that the minimum size (exclusive) for a malloc header is also 473 // a size class boundary. This is important to making sure checks align 474 // across different parts of the runtime. 475 // 476 // While we're here, also check to make sure all these size classes' 477 // span sizes are one page. Some code relies on this. 478 minSizeForMallocHeaderIsSizeClass := false 479 sizeClassesUpToMinSizeForMallocHeaderAreOnePage := true 480 for i := 0; i < len(gc.SizeClassToSize); i++ { 481 if gc.SizeClassToNPages[i] > 1 { 482 sizeClassesUpToMinSizeForMallocHeaderAreOnePage = false 483 } 484 if gc.MinSizeForMallocHeader == uintptr(gc.SizeClassToSize[i]) { 485 minSizeForMallocHeaderIsSizeClass = true 486 break 487 } 488 } 489 if !minSizeForMallocHeaderIsSizeClass { 490 throw("min size of malloc header is not a size class boundary") 491 } 492 if !sizeClassesUpToMinSizeForMallocHeaderAreOnePage { 493 throw("expected all size classes up to min size for malloc header to fit in one-page spans") 494 } 495 // Check that the pointer bitmap for all small sizes without a malloc header 496 // fits in a word. 497 if gc.MinSizeForMallocHeader/goarch.PtrSize > 8*goarch.PtrSize { 498 throw("max pointer/scan bitmap size for headerless objects is too large") 499 } 500 501 if minTagBits > tagBits { 502 throw("tagBits too small") 503 } 504 505 // Initialize the heap. 506 mheap_.init() 507 mcache0 = allocmcache() 508 lockInit(&gcBitsArenas.lock, lockRankGcBitsArenas) 509 lockInit(&profInsertLock, lockRankProfInsert) 510 lockInit(&profBlockLock, lockRankProfBlock) 511 lockInit(&profMemActiveLock, lockRankProfMemActive) 512 for i := range profMemFutureLock { 513 lockInit(&profMemFutureLock[i], lockRankProfMemFuture) 514 } 515 lockInit(&globalAlloc.mutex, lockRankGlobalAlloc) 516 517 // Create initial arena growth hints. 518 if isSbrkPlatform { 519 // Don't generate hints on sbrk platforms. We can 520 // only grow the break sequentially. 521 } else if goarch.PtrSize == 8 { 522 // On a 64-bit machine, we pick the following hints 523 // because: 524 // 525 // 1. Starting from the middle of the address space 526 // makes it easier to grow out a contiguous range 527 // without running in to some other mapping. 528 // 529 // 2. This makes Go heap addresses more easily 530 // recognizable when debugging. 531 // 532 // 3. Stack scanning in gccgo is still conservative, 533 // so it's important that addresses be distinguishable 534 // from other data. 535 // 536 // Starting at 0x00c0 means that the valid memory addresses 537 // will begin 0x00c0, 0x00c1, ... 538 // In little-endian, that's c0 00, c1 00, ... None of those are valid 539 // UTF-8 sequences, and they are otherwise as far away from 540 // ff (likely a common byte) as possible. If that fails, we try other 0xXXc0 541 // addresses. An earlier attempt to use 0x11f8 caused out of memory errors 542 // on OS X during thread allocations. 0x00c0 causes conflicts with 543 // AddressSanitizer which reserves all memory up to 0x0100. 544 // These choices reduce the odds of a conservative garbage collector 545 // not collecting memory because some non-pointer block of memory 546 // had a bit pattern that matched a memory address. 547 // 548 // However, on arm64, we ignore all this advice above and slam the 549 // allocation at 0x40 << 32 because when using 4k pages with 3-level 550 // translation buffers, the user address space is limited to 39 bits 551 // On ios/arm64, the address space is even smaller. 552 // 553 // On AIX, mmaps starts at 0x0A00000000000000 for 64-bit. 554 // processes. 555 // 556 // Space mapped for user arenas comes immediately after the range 557 // originally reserved for the regular heap when race mode is not 558 // enabled because user arena chunks can never be used for regular heap 559 // allocations and we want to avoid fragmenting the address space. 560 // 561 // In race mode we have no choice but to just use the same hints because 562 // the race detector requires that the heap be mapped contiguously. 563 // 564 // If randomizeHeapBase is set, we attempt to randomize the base address 565 // as much as possible. We do this by generating a random uint64 via 566 // bootstrapRand and using it's bits to randomize portions of the base 567 // address as follows: 568 // * We first generate a random heapArenaBytes aligned address that we use for 569 // generating the hints. 570 // * On the first call to mheap.grow, we then generate a random PallocChunkBytes 571 // aligned offset into the mmap'd heap region, which we use as the base for 572 // the heap region. 573 // * We then select a page offset in that PallocChunkBytes region to start the 574 // heap at, and mark all the pages up to that offset as allocated. 575 // 576 // Our final randomized "heap base address" becomes the first byte of 577 // the first available page returned by the page allocator. This results 578 // in an address with at least heapAddrBits-gc.PageShift-2-(1*goarch.IsAmd64) 579 // bits of entropy. 580 581 var randHeapBase uintptr 582 var randHeapBasePrefix byte 583 if randomizeHeapBase { 584 // Generate a random value, and take the bottom heapAddrBits-logHeapArenaBytes 585 // bits, using them as the top bits for randHeapBase. 586 heapRandSeed, heapRandSeedBitsRemaining = uintptr(bootstrapRand()), 64 587 588 topBits := (randHeapAddrBits - logHeapArenaBytes) 589 randHeapBase = nextHeapRandBits(topBits) << (randHeapAddrBits - topBits) 590 randHeapBase = alignUp(randHeapBase, heapArenaBytes) 591 randHeapBasePrefix = byte(randHeapBase >> (randHeapAddrBits - 8)) 592 } 593 594 var vmaSize int 595 if GOARCH == "riscv64" { 596 // Identify which memory layout is in use based on the system 597 // stack address, knowing that the bottom half of virtual memory 598 // is user space. This should result in 39, 48 or 57. It may be 599 // possible to use RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS at some 600 // point in the future - for now use the system stack address. 601 vmaSize = sys.Len64(uint64(getg().m.g0.stack.hi)) + 1 602 if raceenabled && vmaSize != 39 && vmaSize != 48 { 603 println("vma size = ", vmaSize) 604 throw("riscv64 vma size is unknown and race mode is enabled") 605 } 606 } 607 608 for i := 0x7f; i >= 0; i-- { 609 var p uintptr 610 switch { 611 case raceenabled && GOARCH == "riscv64" && vmaSize == 39: 612 p = uintptr(i)<<28 | uintptrMask&(0x0013<<28) 613 if p >= uintptrMask&0x000f00000000 { 614 continue 615 } 616 case raceenabled: 617 // The TSAN runtime requires the heap 618 // to be in the range [0x00c000000000, 619 // 0x00e000000000). 620 p = uintptr(i)<<32 | uintptrMask&(0x00c0<<32) 621 if p >= uintptrMask&0x00e000000000 { 622 continue 623 } 624 case randomizeHeapBase: 625 prefix := uintptr(randHeapBasePrefix+byte(i)) << (randHeapAddrBits - 8) 626 p = prefix | (randHeapBase & randHeapBasePrefixMask) 627 case GOARCH == "arm64" && GOOS == "ios": 628 p = uintptr(i)<<40 | uintptrMask&(0x0013<<28) 629 case GOARCH == "arm64": 630 p = uintptr(i)<<40 | uintptrMask&(0x0040<<32) 631 case GOARCH == "riscv64" && vmaSize == 39: 632 p = uintptr(i)<<32 | uintptrMask&(0x0013<<28) 633 case GOOS == "aix": 634 if i == 0 { 635 // We don't use addresses directly after 0x0A00000000000000 636 // to avoid collisions with others mmaps done by non-go programs. 637 continue 638 } 639 p = uintptr(i)<<40 | uintptrMask&(0xa0<<52) 640 default: 641 p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32) 642 } 643 // Switch to generating hints for user arenas if we've gone 644 // through about half the hints. In race mode, take only about 645 // a quarter; we don't have very much space to work with. 646 hintList := &mheap_.arenaHints 647 if (!raceenabled && i > 0x3f) || (raceenabled && i > 0x5f) { 648 hintList = &mheap_.userArena.arenaHints 649 } 650 hint := (*arenaHint)(mheap_.arenaHintAlloc.alloc()) 651 hint.addr = p 652 hint.next, *hintList = *hintList, hint 653 } 654 } else { 655 // On a 32-bit machine, we're much more concerned 656 // about keeping the usable heap contiguous. 657 // Hence: 658 // 659 // 1. We reserve space for all heapArenas up front so 660 // they don't get interleaved with the heap. They're 661 // ~258MB, so this isn't too bad. (We could reserve a 662 // smaller amount of space up front if this is a 663 // problem.) 664 // 665 // 2. We hint the heap to start right above the end of 666 // the binary so we have the best chance of keeping it 667 // contiguous. 668 // 669 // 3. We try to stake out a reasonably large initial 670 // heap reservation. 671 672 const arenaMetaSize = (1 << arenaBits) * unsafe.Sizeof(heapArena{}) 673 meta := uintptr(sysReserve(nil, arenaMetaSize, "heap reservation")) 674 if meta != 0 { 675 mheap_.heapArenaAlloc.init(meta, arenaMetaSize, true) 676 } 677 678 // We want to start the arena low, but if we're linked 679 // against C code, it's possible global constructors 680 // have called malloc and adjusted the process' brk. 681 // Query the brk so we can avoid trying to map the 682 // region over it (which will cause the kernel to put 683 // the region somewhere else, likely at a high 684 // address). 685 procBrk := sbrk0() 686 687 // If we ask for the end of the data segment but the 688 // operating system requires a little more space 689 // before we can start allocating, it will give out a 690 // slightly higher pointer. Except QEMU, which is 691 // buggy, as usual: it won't adjust the pointer 692 // upward. So adjust it upward a little bit ourselves: 693 // 1/4 MB to get away from the running binary image. 694 p := firstmoduledata.end 695 if p < procBrk { 696 p = procBrk 697 } 698 if mheap_.heapArenaAlloc.next <= p && p < mheap_.heapArenaAlloc.end { 699 p = mheap_.heapArenaAlloc.end 700 } 701 p = alignUp(p+(256<<10), heapArenaBytes) 702 // Because we're worried about fragmentation on 703 // 32-bit, we try to make a large initial reservation. 704 arenaSizes := []uintptr{ 705 512 << 20, 706 256 << 20, 707 128 << 20, 708 } 709 for _, arenaSize := range arenaSizes { 710 a, size := sysReserveAligned(unsafe.Pointer(p), arenaSize, heapArenaBytes, "heap reservation") 711 if a != nil { 712 mheap_.arena.init(uintptr(a), size, false) 713 p = mheap_.arena.end // For hint below 714 break 715 } 716 } 717 hint := (*arenaHint)(mheap_.arenaHintAlloc.alloc()) 718 hint.addr = p 719 hint.next, mheap_.arenaHints = mheap_.arenaHints, hint 720 721 // Place the hint for user arenas just after the large reservation. 722 // 723 // While this potentially competes with the hint above, in practice we probably 724 // aren't going to be getting this far anyway on 32-bit platforms. 725 userArenaHint := (*arenaHint)(mheap_.arenaHintAlloc.alloc()) 726 userArenaHint.addr = p 727 userArenaHint.next, mheap_.userArena.arenaHints = mheap_.userArena.arenaHints, userArenaHint 728 } 729 // Initialize the memory limit here because the allocator is going to look at it 730 // but we haven't called gcinit yet and we're definitely going to allocate memory before then. 731 gcController.memoryLimit.Store(math.MaxInt64) 732 } 733 734 // sysAlloc allocates heap arena space for at least n bytes. The 735 // returned pointer is always heapArenaBytes-aligned and backed by 736 // h.arenas metadata. The returned size is always a multiple of 737 // heapArenaBytes. sysAlloc returns nil on failure. 738 // There is no corresponding free function. 739 // 740 // hintList is a list of hint addresses for where to allocate new 741 // heap arenas. It must be non-nil. 742 // 743 // sysAlloc returns a memory region in the Reserved state. This region must 744 // be transitioned to Prepared and then Ready before use. 745 // 746 // arenaList is the list the arena should be added to. 747 // 748 // h must be locked. 749 func (h *mheap) sysAlloc(n uintptr, hintList **arenaHint, arenaList *[]arenaIdx) (v unsafe.Pointer, size uintptr) { 750 assertLockHeld(&h.lock) 751 752 n = alignUp(n, heapArenaBytes) 753 754 if hintList == &h.arenaHints { 755 // First, try the arena pre-reservation. 756 // Newly-used mappings are considered released. 757 // 758 // Only do this if we're using the regular heap arena hints. 759 // This behavior is only for the heap. 760 v = h.arena.alloc(n, heapArenaBytes, &gcController.heapReleased, "heap") 761 if v != nil { 762 size = n 763 goto mapped 764 } 765 } 766 767 // Try to grow the heap at a hint address. 768 for *hintList != nil { 769 hint := *hintList 770 p := hint.addr 771 if hint.down { 772 p -= n 773 } 774 if p+n < p { 775 // We can't use this, so don't ask. 776 v = nil 777 } else if arenaIndex(p+n-1) >= 1<<arenaBits { 778 // Outside addressable heap. Can't use. 779 v = nil 780 } else { 781 v = sysReserve(unsafe.Pointer(p), n, "heap reservation") 782 } 783 if p == uintptr(v) { 784 // Success. Update the hint. 785 if !hint.down { 786 p += n 787 } 788 hint.addr = p 789 size = n 790 break 791 } 792 // Failed. Discard this hint and try the next. 793 // 794 // TODO: This would be cleaner if sysReserve could be 795 // told to only return the requested address. In 796 // particular, this is already how Windows behaves, so 797 // it would simplify things there. 798 if v != nil { 799 sysUnreserve(v, n) 800 } 801 *hintList = hint.next 802 h.arenaHintAlloc.free(unsafe.Pointer(hint)) 803 } 804 805 if size == 0 { 806 if raceenabled { 807 // The race detector assumes the heap lives in 808 // [0x00c000000000, 0x00e000000000), but we 809 // just ran out of hints in this region. Give 810 // a nice failure. 811 throw("too many address space collisions for -race mode") 812 } 813 814 // All of the hints failed, so we'll take any 815 // (sufficiently aligned) address the kernel will give 816 // us. 817 v, size = sysReserveAligned(nil, n, heapArenaBytes, "heap") 818 if v == nil { 819 return nil, 0 820 } 821 822 // Create new hints for extending this region. 823 hint := (*arenaHint)(h.arenaHintAlloc.alloc()) 824 hint.addr, hint.down = uintptr(v), true 825 hint.next, mheap_.arenaHints = mheap_.arenaHints, hint 826 hint = (*arenaHint)(h.arenaHintAlloc.alloc()) 827 hint.addr = uintptr(v) + size 828 hint.next, mheap_.arenaHints = mheap_.arenaHints, hint 829 } 830 831 // Check for bad pointers or pointers we can't use. 832 { 833 var bad string 834 p := uintptr(v) 835 if p+size < p { 836 bad = "region exceeds uintptr range" 837 } else if arenaIndex(p) >= 1<<arenaBits { 838 bad = "base outside usable address space" 839 } else if arenaIndex(p+size-1) >= 1<<arenaBits { 840 bad = "end outside usable address space" 841 } 842 if bad != "" { 843 // This should be impossible on most architectures, 844 // but it would be really confusing to debug. 845 print("runtime: memory allocated by OS [", hex(p), ", ", hex(p+size), ") not in usable address space: ", bad, "\n") 846 throw("memory reservation exceeds address space limit") 847 } 848 } 849 850 if uintptr(v)&(heapArenaBytes-1) != 0 { 851 throw("misrounded allocation in sysAlloc") 852 } 853 854 mapped: 855 if valgrindenabled { 856 valgrindCreateMempool(v) 857 valgrindMakeMemNoAccess(v, size) 858 } 859 860 // Create arena metadata. 861 for ri := arenaIndex(uintptr(v)); ri <= arenaIndex(uintptr(v)+size-1); ri++ { 862 l2 := h.arenas[ri.l1()] 863 if l2 == nil { 864 // Allocate an L2 arena map. 865 // 866 // Use sysAllocOS instead of sysAlloc or persistentalloc because there's no 867 // statistic we can comfortably account for this space in. With this structure, 868 // we rely on demand paging to avoid large overheads, but tracking which memory 869 // is paged in is too expensive. Trying to account for the whole region means 870 // that it will appear like an enormous memory overhead in statistics, even though 871 // it is not. 872 l2 = (*[1 << arenaL2Bits]*heapArena)(sysAllocOS(unsafe.Sizeof(*l2), "heap index")) 873 if l2 == nil { 874 throw("out of memory allocating heap arena map") 875 } 876 if h.arenasHugePages { 877 sysHugePage(unsafe.Pointer(l2), unsafe.Sizeof(*l2)) 878 } else { 879 sysNoHugePage(unsafe.Pointer(l2), unsafe.Sizeof(*l2)) 880 } 881 atomic.StorepNoWB(unsafe.Pointer(&h.arenas[ri.l1()]), unsafe.Pointer(l2)) 882 } 883 884 if l2[ri.l2()] != nil { 885 throw("arena already initialized") 886 } 887 var r *heapArena 888 r = (*heapArena)(h.heapArenaAlloc.alloc(unsafe.Sizeof(*r), goarch.PtrSize, &memstats.gcMiscSys, "heap metadata")) 889 if r == nil { 890 r = (*heapArena)(persistentalloc(unsafe.Sizeof(*r), goarch.PtrSize, &memstats.gcMiscSys)) 891 if r == nil { 892 throw("out of memory allocating heap arena metadata") 893 } 894 } 895 896 // Register the arena in allArenas if requested. 897 if len((*arenaList)) == cap((*arenaList)) { 898 size := 2 * uintptr(cap((*arenaList))) * goarch.PtrSize 899 if size == 0 { 900 size = physPageSize 901 } 902 newArray := (*notInHeap)(persistentalloc(size, goarch.PtrSize, &memstats.gcMiscSys)) 903 if newArray == nil { 904 throw("out of memory allocating allArenas") 905 } 906 oldSlice := (*arenaList) 907 *(*notInHeapSlice)(unsafe.Pointer(&(*arenaList))) = notInHeapSlice{newArray, len((*arenaList)), int(size / goarch.PtrSize)} 908 copy((*arenaList), oldSlice) 909 // Do not free the old backing array because 910 // there may be concurrent readers. Since we 911 // double the array each time, this can lead 912 // to at most 2x waste. 913 } 914 (*arenaList) = (*arenaList)[:len((*arenaList))+1] 915 (*arenaList)[len((*arenaList))-1] = ri 916 917 // Store atomically just in case an object from the 918 // new heap arena becomes visible before the heap lock 919 // is released (which shouldn't happen, but there's 920 // little downside to this). 921 atomic.StorepNoWB(unsafe.Pointer(&l2[ri.l2()]), unsafe.Pointer(r)) 922 } 923 924 // Tell the race detector about the new heap memory. 925 if raceenabled { 926 racemapshadow(v, size) 927 } 928 929 return 930 } 931 932 // enableMetadataHugePages enables huge pages for various sources of heap metadata. 933 // 934 // A note on latency: for sufficiently small heaps (<10s of GiB) this function will take constant 935 // time, but may take time proportional to the size of the mapped heap beyond that. 936 // 937 // This function is idempotent. 938 // 939 // The heap lock must not be held over this operation, since it will briefly acquire 940 // the heap lock. 941 // 942 // Must be called on the system stack because it acquires the heap lock. 943 // 944 //go:systemstack 945 func (h *mheap) enableMetadataHugePages() { 946 // Enable huge pages for page structure. 947 h.pages.enableChunkHugePages() 948 949 // Grab the lock and set arenasHugePages if it's not. 950 // 951 // Once arenasHugePages is set, all new L2 entries will be eligible for 952 // huge pages. We'll set all the old entries after we release the lock. 953 lock(&h.lock) 954 if h.arenasHugePages { 955 unlock(&h.lock) 956 return 957 } 958 h.arenasHugePages = true 959 unlock(&h.lock) 960 961 // N.B. The arenas L1 map is quite small on all platforms, so it's fine to 962 // just iterate over the whole thing. 963 for i := range h.arenas { 964 l2 := (*[1 << arenaL2Bits]*heapArena)(atomic.Loadp(unsafe.Pointer(&h.arenas[i]))) 965 if l2 == nil { 966 continue 967 } 968 sysHugePage(unsafe.Pointer(l2), unsafe.Sizeof(*l2)) 969 } 970 } 971 972 // base address for all 0-byte allocations 973 var zerobase uintptr 974 975 // nextFreeFast returns the next free object if one is quickly available. 976 // Otherwise it returns 0. 977 func nextFreeFast(s *mspan) gclinkptr { 978 theBit := sys.TrailingZeros64(s.allocCache) // Is there a free object in the allocCache? 979 if theBit < 64 { 980 result := s.freeindex + uint16(theBit) 981 if result < s.nelems { 982 freeidx := result + 1 983 if freeidx%64 == 0 && freeidx != s.nelems { 984 return 0 985 } 986 s.allocCache >>= uint(theBit + 1) 987 s.freeindex = freeidx 988 s.allocCount++ 989 return gclinkptr(uintptr(result)*s.elemsize + s.base()) 990 } 991 } 992 return 0 993 } 994 995 // nextFree returns the next free object from the cached span if one is available. 996 // Otherwise it refills the cache with a span with an available object and 997 // returns that object along with a flag indicating that this was a heavy 998 // weight allocation. If it is a heavy weight allocation the caller must 999 // determine whether a new GC cycle needs to be started or if the GC is active 1000 // whether this goroutine needs to assist the GC. 1001 // 1002 // Must run in a non-preemptible context since otherwise the owner of 1003 // c could change. 1004 func (c *mcache) nextFree(spc spanClass) (v gclinkptr, s *mspan, checkGCTrigger bool) { 1005 s = c.alloc[spc] 1006 checkGCTrigger = false 1007 freeIndex := s.nextFreeIndex() 1008 if freeIndex == s.nelems { 1009 // The span is full. 1010 if s.allocCount != s.nelems { 1011 println("runtime: s.allocCount=", s.allocCount, "s.nelems=", s.nelems) 1012 throw("s.allocCount != s.nelems && freeIndex == s.nelems") 1013 } 1014 c.refill(spc) 1015 checkGCTrigger = true 1016 s = c.alloc[spc] 1017 1018 freeIndex = s.nextFreeIndex() 1019 } 1020 1021 if freeIndex >= s.nelems { 1022 throw("freeIndex is not valid") 1023 } 1024 1025 v = gclinkptr(uintptr(freeIndex)*s.elemsize + s.base()) 1026 s.allocCount++ 1027 if s.allocCount > s.nelems { 1028 println("s.allocCount=", s.allocCount, "s.nelems=", s.nelems) 1029 throw("s.allocCount > s.nelems") 1030 } 1031 return 1032 } 1033 1034 // doubleCheckMalloc enables a bunch of extra checks to malloc to double-check 1035 // that various invariants are upheld. 1036 // 1037 // We might consider turning these on by default; many of them previously were. 1038 // They account for a few % of mallocgc's cost though, which does matter somewhat 1039 // at scale. (When testing changes to malloc, consider enabling this, and also 1040 // some function-local 'doubleCheck' consts such as in mbitmap.go currently.) 1041 const doubleCheckMalloc = false 1042 1043 // sizeSpecializedMallocEnabled is the set of conditions where we enable the size-specialized 1044 // mallocgc implementation: none of the sanitizers should be enabled. The tables used to select 1045 // the size-specialized malloc function do not compile properly on plan9, so 1046 // size-specialized malloc is also disabled on plan9. 1047 const sizeSpecializedMallocEnabled = GOOS != "plan9" && !asanenabled && !raceenabled && !msanenabled && !valgrindenabled 1048 1049 // runtimeFreegcEnabled is the set of conditions where we enable the runtime.freegc 1050 // implementation and the corresponding allocation-related changes: the experiment must be 1051 // enabled, and none of the memory sanitizers should be enabled. We allow the race detector, 1052 // in contrast to sizeSpecializedMallocEnabled. 1053 // TODO(thepudds): it would be nice to check Valgrind integration, though there are some hints 1054 // there might not be any canned tests in tree for Go's integration with Valgrind. 1055 const runtimeFreegcEnabled = goexperiment.RuntimeFreegc && !asanenabled && !msanenabled && !valgrindenabled 1056 1057 // Allocate an object of size bytes. 1058 // Small objects are allocated from the per-P cache's free lists. 1059 // Large objects (> 32 kB) are allocated straight from the heap. 1060 // 1061 // mallocgc should be an internal detail, 1062 // but widely used packages access it using linkname. 1063 // Notable members of the hall of shame include: 1064 // - github.com/bytedance/gopkg 1065 // - github.com/bytedance/sonic 1066 // - github.com/cloudwego/frugal 1067 // - github.com/cockroachdb/cockroach 1068 // - github.com/cockroachdb/pebble 1069 // - github.com/ugorji/go/codec 1070 // 1071 // Do not remove or change the type signature. 1072 // See go.dev/issue/67401. 1073 // 1074 //go:linkname mallocgc 1075 func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { 1076 if doubleCheckMalloc { 1077 if gcphase == _GCmarktermination { 1078 throw("mallocgc called with gcphase == _GCmarktermination") 1079 } 1080 } 1081 1082 // Short-circuit zero-sized allocation requests. 1083 if size == 0 { 1084 return unsafe.Pointer(&zerobase) 1085 } 1086 1087 if sizeSpecializedMallocEnabled && size < uintptr(len(mallocNoScanTable)) { 1088 if typ == nil || !typ.Pointers() { 1089 if size >= maxTinySize { 1090 return mallocNoScanTable[size](size, typ, needzero) 1091 } 1092 return mallocgcTinySC2(size, typ, needzero) 1093 } else { 1094 if !needzero { 1095 throw("objects with pointers must be zeroed") 1096 } 1097 return mallocScanTable[size](size, typ, needzero) 1098 } 1099 } 1100 1101 // It's possible for any malloc to trigger sweeping, which may in 1102 // turn queue finalizers. Record this dynamic lock edge. 1103 // N.B. Compiled away if lockrank experiment is not enabled. 1104 lockRankMayQueueFinalizer() 1105 1106 // Pre-malloc debug hooks. 1107 if debug.malloc { 1108 if x := preMallocgcDebug(size, typ); x != nil { 1109 return x 1110 } 1111 } 1112 1113 // For ASAN, we allocate extra memory around each allocation called the "redzone." 1114 // These "redzones" are marked as unaddressable. 1115 var asanRZ uintptr 1116 if asanenabled { 1117 asanRZ = redZoneSize(size) 1118 size += asanRZ 1119 } 1120 1121 // Assist the GC if needed. (On the reuse path, we currently compensate for this; 1122 // changes here might require changes there.) 1123 if gcBlackenEnabled != 0 { 1124 deductAssistCredit(size) 1125 } 1126 1127 // Actually do the allocation. 1128 var x unsafe.Pointer 1129 var elemsize uintptr 1130 if sizeSpecializedMallocEnabled { 1131 if size <= maxSmallSize-gc.MallocHeaderSize { 1132 if typ == nil || !typ.Pointers() { 1133 x, elemsize = mallocgcSmallNoscan(size, typ, needzero) 1134 } else { 1135 if !needzero { 1136 throw("objects with pointers must be zeroed") 1137 } 1138 if heapBitsInSpan(size) { 1139 x, elemsize = mallocgcSmallScanNoHeader(size, typ) 1140 } else { 1141 x, elemsize = mallocgcSmallScanHeader(size, typ) 1142 } 1143 } 1144 } else { 1145 x, elemsize = mallocgcLarge(size, typ, needzero) 1146 } 1147 } else { 1148 if size <= maxSmallSize-gc.MallocHeaderSize { 1149 if typ == nil || !typ.Pointers() { 1150 // tiny allocations might be kept alive by other co-located values. 1151 // Make sure secret allocations get zeroed by avoiding the tiny allocator 1152 // See go.dev/issue/76356 1153 gp := getg() 1154 if size < maxTinySize && gp.secret == 0 { 1155 x, elemsize = mallocgcTiny(size, typ) 1156 } else { 1157 x, elemsize = mallocgcSmallNoscan(size, typ, needzero) 1158 } 1159 } else { 1160 if !needzero { 1161 throw("objects with pointers must be zeroed") 1162 } 1163 if heapBitsInSpan(size) { 1164 x, elemsize = mallocgcSmallScanNoHeader(size, typ) 1165 } else { 1166 x, elemsize = mallocgcSmallScanHeader(size, typ) 1167 } 1168 } 1169 } else { 1170 x, elemsize = mallocgcLarge(size, typ, needzero) 1171 } 1172 } 1173 1174 gp := getg() 1175 if goexperiment.RuntimeSecret && gp.secret > 0 { 1176 // Mark any object allocated while in secret mode as secret. 1177 // This ensures we zero it immediately when freeing it. 1178 addSecret(x, size) 1179 } 1180 1181 // Notify sanitizers, if enabled. 1182 if raceenabled { 1183 racemalloc(x, size-asanRZ) 1184 } 1185 if msanenabled { 1186 msanmalloc(x, size-asanRZ) 1187 } 1188 if asanenabled { 1189 // Poison the space between the end of the requested size of x 1190 // and the end of the slot. Unpoison the requested allocation. 1191 asanpoison(unsafe.Add(x, size-asanRZ), asanRZ) 1192 asanunpoison(x, size-asanRZ) 1193 } 1194 if valgrindenabled { 1195 valgrindMalloc(x, size-asanRZ) 1196 } 1197 1198 // Adjust our GC assist debt to account for internal fragmentation. 1199 if gcBlackenEnabled != 0 && elemsize != 0 { 1200 if assistG := getg().m.curg; assistG != nil { 1201 assistG.gcAssistBytes -= int64(elemsize - size) 1202 } 1203 } 1204 1205 // Post-malloc debug hooks. 1206 if debug.malloc { 1207 postMallocgcDebug(x, elemsize, typ) 1208 } 1209 return x 1210 } 1211 1212 func mallocgcTiny(size uintptr, typ *_type) (unsafe.Pointer, uintptr) { 1213 // Set mp.mallocing to keep from being preempted by GC. 1214 mp := acquirem() 1215 if doubleCheckMalloc { 1216 if mp.mallocing != 0 { 1217 throw("malloc deadlock") 1218 } 1219 if mp.gsignal == getg() { 1220 throw("malloc during signal") 1221 } 1222 if typ != nil && typ.Pointers() { 1223 throw("expected noscan for tiny alloc") 1224 } 1225 } 1226 mp.mallocing = 1 1227 1228 // Tiny allocator. 1229 // 1230 // Tiny allocator combines several tiny allocation requests 1231 // into a single memory block. The resulting memory block 1232 // is freed when all subobjects are unreachable. The subobjects 1233 // must be noscan (don't have pointers), this ensures that 1234 // the amount of potentially wasted memory is bounded. 1235 // 1236 // Size of the memory block used for combining (maxTinySize) is tunable. 1237 // Current setting is 16 bytes, which relates to 2x worst case memory 1238 // wastage (when all but one subobjects are unreachable). 1239 // 8 bytes would result in no wastage at all, but provides less 1240 // opportunities for combining. 1241 // 32 bytes provides more opportunities for combining, 1242 // but can lead to 4x worst case wastage. 1243 // The best case winning is 8x regardless of block size. 1244 // 1245 // Objects obtained from tiny allocator must not be freed explicitly. 1246 // So when an object will be freed explicitly, we ensure that 1247 // its size >= maxTinySize. 1248 // 1249 // SetFinalizer has a special case for objects potentially coming 1250 // from tiny allocator, it such case it allows to set finalizers 1251 // for an inner byte of a memory block. 1252 // 1253 // The main targets of tiny allocator are small strings and 1254 // standalone escaping variables. On a json benchmark 1255 // the allocator reduces number of allocations by ~12% and 1256 // reduces heap size by ~20%. 1257 c := getMCache(mp) 1258 off := c.tinyoffset 1259 // Align tiny pointer for required (conservative) alignment. 1260 if size&7 == 0 { 1261 off = alignUp(off, 8) 1262 } else if goarch.PtrSize == 4 && size == 12 { 1263 // Conservatively align 12-byte objects to 8 bytes on 32-bit 1264 // systems so that objects whose first field is a 64-bit 1265 // value is aligned to 8 bytes and does not cause a fault on 1266 // atomic access. See issue 37262. 1267 // TODO(mknyszek): Remove this workaround if/when issue 36606 1268 // is resolved. 1269 off = alignUp(off, 8) 1270 } else if size&3 == 0 { 1271 off = alignUp(off, 4) 1272 } else if size&1 == 0 { 1273 off = alignUp(off, 2) 1274 } 1275 if off+size <= maxTinySize && c.tiny != 0 { 1276 // The object fits into existing tiny block. 1277 x := unsafe.Pointer(c.tiny + off) 1278 c.tinyoffset = off + size 1279 c.tinyAllocs++ 1280 mp.mallocing = 0 1281 releasem(mp) 1282 return x, 0 1283 } 1284 // Allocate a new maxTinySize block. 1285 checkGCTrigger := false 1286 span := c.alloc[tinySpanClass] 1287 v := nextFreeFast(span) 1288 if v == 0 { 1289 v, span, checkGCTrigger = c.nextFree(tinySpanClass) 1290 } 1291 x := unsafe.Pointer(v) 1292 (*[2]uint64)(x)[0] = 0 // Always zero 1293 (*[2]uint64)(x)[1] = 0 1294 // See if we need to replace the existing tiny block with the new one 1295 // based on amount of remaining free space. 1296 if !raceenabled && (size < c.tinyoffset || c.tiny == 0) { 1297 // Note: disabled when race detector is on, see comment near end of this function. 1298 c.tiny = uintptr(x) 1299 c.tinyoffset = size 1300 } 1301 1302 // Ensure that the stores above that initialize x to 1303 // type-safe memory and set the heap bits occur before 1304 // the caller can make x observable to the garbage 1305 // collector. Otherwise, on weakly ordered machines, 1306 // the garbage collector could follow a pointer to x, 1307 // but see uninitialized memory or stale heap bits. 1308 publicationBarrier() 1309 1310 if writeBarrier.enabled { 1311 // Allocate black during GC. 1312 // All slots hold nil so no scanning is needed. 1313 // This may be racing with GC so do it atomically if there can be 1314 // a race marking the bit. 1315 gcmarknewobject(span, uintptr(x)) 1316 } else { 1317 // Track the last free index before the mark phase. This field 1318 // is only used by the garbage collector. During the mark phase 1319 // this is used by the conservative scanner to filter out objects 1320 // that are both free and recently-allocated. It's safe to do that 1321 // because we allocate-black if the GC is enabled. The conservative 1322 // scanner produces pointers out of thin air, so without additional 1323 // synchronization it might otherwise observe a partially-initialized 1324 // object, which could crash the program. 1325 span.freeIndexForScan = span.freeindex 1326 } 1327 1328 // Note cache c only valid while m acquired; see #47302 1329 // 1330 // N.B. Use the full size because that matches how the GC 1331 // will update the mem profile on the "free" side. 1332 // 1333 // TODO(mknyszek): We should really count the header as part 1334 // of gc_sys or something. The code below just pretends it is 1335 // internal fragmentation and matches the GC's accounting by 1336 // using the whole allocation slot. 1337 c.nextSample -= int64(span.elemsize) 1338 if c.nextSample < 0 || MemProfileRate != c.memProfRate { 1339 profilealloc(mp, x, span.elemsize) 1340 } 1341 mp.mallocing = 0 1342 releasem(mp) 1343 1344 if checkGCTrigger { 1345 if t := (gcTrigger{kind: gcTriggerHeap}); t.test() { 1346 gcStart(t) 1347 } 1348 } 1349 1350 if raceenabled { 1351 // Pad tinysize allocations so they are aligned with the end 1352 // of the tinyalloc region. This ensures that any arithmetic 1353 // that goes off the top end of the object will be detectable 1354 // by checkptr (issue 38872). 1355 // Note that we disable tinyalloc when raceenabled for this to work. 1356 // TODO: This padding is only performed when the race detector 1357 // is enabled. It would be nice to enable it if any package 1358 // was compiled with checkptr, but there's no easy way to 1359 // detect that (especially at compile time). 1360 // TODO: enable this padding for all allocations, not just 1361 // tinyalloc ones. It's tricky because of pointer maps. 1362 // Maybe just all noscan objects? 1363 x = add(x, span.elemsize-size) 1364 } 1365 return x, span.elemsize 1366 } 1367 1368 func mallocgcSmallNoscan(size uintptr, typ *_type, needzero bool) (unsafe.Pointer, uintptr) { 1369 // Set mp.mallocing to keep from being preempted by GC. 1370 mp := acquirem() 1371 if doubleCheckMalloc { 1372 if mp.mallocing != 0 { 1373 throw("malloc deadlock") 1374 } 1375 if mp.gsignal == getg() { 1376 throw("malloc during signal") 1377 } 1378 if typ != nil && typ.Pointers() { 1379 throw("expected noscan type for noscan alloc") 1380 } 1381 } 1382 mp.mallocing = 1 1383 1384 checkGCTrigger := false 1385 c := getMCache(mp) 1386 var sizeclass uint8 1387 if size <= gc.SmallSizeMax-8 { 1388 sizeclass = gc.SizeToSizeClass8[divRoundUp(size, gc.SmallSizeDiv)] 1389 } else { 1390 sizeclass = gc.SizeToSizeClass128[divRoundUp(size-gc.SmallSizeMax, gc.LargeSizeDiv)] 1391 } 1392 size = uintptr(gc.SizeClassToSize[sizeclass]) 1393 spc := makeSpanClass(sizeclass, true) 1394 span := c.alloc[spc] 1395 1396 // First, check for a reusable object. 1397 if runtimeFreegcEnabled && c.hasReusableNoscan(spc) { 1398 // We have a reusable object, use it. 1399 x := mallocgcSmallNoscanReuse(c, span, spc, size, needzero) 1400 mp.mallocing = 0 1401 releasem(mp) 1402 return x, size 1403 } 1404 1405 v := nextFreeFast(span) 1406 if v == 0 { 1407 v, span, checkGCTrigger = c.nextFree(spc) 1408 } 1409 x := unsafe.Pointer(v) 1410 if needzero && span.needzero != 0 { 1411 memclrNoHeapPointers(x, size) 1412 } 1413 1414 // Ensure that the stores above that initialize x to 1415 // type-safe memory and set the heap bits occur before 1416 // the caller can make x observable to the garbage 1417 // collector. Otherwise, on weakly ordered machines, 1418 // the garbage collector could follow a pointer to x, 1419 // but see uninitialized memory or stale heap bits. 1420 publicationBarrier() 1421 1422 if writeBarrier.enabled { 1423 // Allocate black during GC. 1424 // All slots hold nil so no scanning is needed. 1425 // This may be racing with GC so do it atomically if there can be 1426 // a race marking the bit. 1427 gcmarknewobject(span, uintptr(x)) 1428 } else { 1429 // Track the last free index before the mark phase. This field 1430 // is only used by the garbage collector. During the mark phase 1431 // this is used by the conservative scanner to filter out objects 1432 // that are both free and recently-allocated. It's safe to do that 1433 // because we allocate-black if the GC is enabled. The conservative 1434 // scanner produces pointers out of thin air, so without additional 1435 // synchronization it might otherwise observe a partially-initialized 1436 // object, which could crash the program. 1437 span.freeIndexForScan = span.freeindex 1438 } 1439 1440 // Note cache c only valid while m acquired; see #47302 1441 // 1442 // N.B. Use the full size because that matches how the GC 1443 // will update the mem profile on the "free" side. 1444 // 1445 // TODO(mknyszek): We should really count the header as part 1446 // of gc_sys or something. The code below just pretends it is 1447 // internal fragmentation and matches the GC's accounting by 1448 // using the whole allocation slot. 1449 c.nextSample -= int64(size) 1450 if c.nextSample < 0 || MemProfileRate != c.memProfRate { 1451 profilealloc(mp, x, size) 1452 } 1453 mp.mallocing = 0 1454 releasem(mp) 1455 1456 if checkGCTrigger { 1457 if t := (gcTrigger{kind: gcTriggerHeap}); t.test() { 1458 gcStart(t) 1459 } 1460 } 1461 return x, size 1462 } 1463 1464 // mallocgcSmallNoscanReuse returns a previously freed noscan object after preparing it for reuse. 1465 // It must only be called if hasReusableNoscan returned true. 1466 func mallocgcSmallNoscanReuse(c *mcache, span *mspan, spc spanClass, size uintptr, needzero bool) unsafe.Pointer { 1467 // TODO(thepudds): could nextFreeFast, nextFree and nextReusable return unsafe.Pointer? 1468 // Maybe doesn't matter. gclinkptr might be for historical reasons. 1469 v, span := c.nextReusableNoScan(span, spc) 1470 x := unsafe.Pointer(v) 1471 1472 // Compensate for the GC assist credit deducted in mallocgc (before calling us and 1473 // after we return) because this is not a newly allocated object. We use the full slot 1474 // size (elemsize) here because that's what mallocgc deducts overall. Note we only 1475 // adjust this when gcBlackenEnabled is true, which follows mallocgc behavior. 1476 // TODO(thepudds): a follow-up CL adds a more specific test of our assist credit 1477 // handling, including for validating internal fragmentation handling. 1478 if gcBlackenEnabled != 0 { 1479 addAssistCredit(size) 1480 } 1481 1482 // This is a previously used object, so only check needzero (and not span.needzero) 1483 // for clearing. 1484 if needzero { 1485 memclrNoHeapPointers(x, size) 1486 } 1487 1488 // See publicationBarrier comment in mallocgcSmallNoscan. 1489 publicationBarrier() 1490 1491 // Finish and return. Note that we do not update span.freeIndexForScan, profiling info, 1492 // nor do we check gcTrigger. 1493 // TODO(thepudds): the current approach is viable for a GOEXPERIMENT, but 1494 // means we do not profile reused heap objects. Ultimately, we will need a better 1495 // approach for profiling, or at least ensure we are not introducing bias in the 1496 // profiled allocations. 1497 // TODO(thepudds): related, we probably want to adjust how allocs and frees are counted 1498 // in the existing stats. Currently, reused objects are not counted as allocs nor 1499 // frees, but instead roughly appear as if the original heap object lived on. We 1500 // probably will also want some additional runtime/metrics, and generally think about 1501 // user-facing observability & diagnostics, though all this likely can wait for an 1502 // official proposal. 1503 if writeBarrier.enabled { 1504 // Allocate black during GC. 1505 // All slots hold nil so no scanning is needed. 1506 // This may be racing with GC so do it atomically if there can be 1507 // a race marking the bit. 1508 gcmarknewobject(span, uintptr(x)) 1509 } 1510 return x 1511 } 1512 1513 func mallocgcSmallScanNoHeader(size uintptr, typ *_type) (unsafe.Pointer, uintptr) { 1514 // Set mp.mallocing to keep from being preempted by GC. 1515 mp := acquirem() 1516 if doubleCheckMalloc { 1517 if mp.mallocing != 0 { 1518 throw("malloc deadlock") 1519 } 1520 if mp.gsignal == getg() { 1521 throw("malloc during signal") 1522 } 1523 if typ == nil || !typ.Pointers() { 1524 throw("noscan allocated in scan-only path") 1525 } 1526 if !heapBitsInSpan(size) { 1527 throw("heap bits in not in span for non-header-only path") 1528 } 1529 } 1530 mp.mallocing = 1 1531 1532 checkGCTrigger := false 1533 c := getMCache(mp) 1534 sizeclass := gc.SizeToSizeClass8[divRoundUp(size, gc.SmallSizeDiv)] 1535 spc := makeSpanClass(sizeclass, false) 1536 span := c.alloc[spc] 1537 v := nextFreeFast(span) 1538 if v == 0 { 1539 v, span, checkGCTrigger = c.nextFree(spc) 1540 } 1541 x := unsafe.Pointer(v) 1542 if span.needzero != 0 { 1543 memclrNoHeapPointers(x, size) 1544 } 1545 if goarch.PtrSize == 8 && sizeclass == 1 { 1546 // initHeapBits already set the pointer bits for the 8-byte sizeclass 1547 // on 64-bit platforms. 1548 c.scanAlloc += 8 1549 } else { 1550 c.scanAlloc += heapSetTypeNoHeader(uintptr(x), size, typ, span) 1551 } 1552 size = uintptr(gc.SizeClassToSize[sizeclass]) 1553 1554 // Ensure that the stores above that initialize x to 1555 // type-safe memory and set the heap bits occur before 1556 // the caller can make x observable to the garbage 1557 // collector. Otherwise, on weakly ordered machines, 1558 // the garbage collector could follow a pointer to x, 1559 // but see uninitialized memory or stale heap bits. 1560 publicationBarrier() 1561 1562 if writeBarrier.enabled { 1563 // Allocate black during GC. 1564 // All slots hold nil so no scanning is needed. 1565 // This may be racing with GC so do it atomically if there can be 1566 // a race marking the bit. 1567 gcmarknewobject(span, uintptr(x)) 1568 } else { 1569 // Track the last free index before the mark phase. This field 1570 // is only used by the garbage collector. During the mark phase 1571 // this is used by the conservative scanner to filter out objects 1572 // that are both free and recently-allocated. It's safe to do that 1573 // because we allocate-black if the GC is enabled. The conservative 1574 // scanner produces pointers out of thin air, so without additional 1575 // synchronization it might otherwise observe a partially-initialized 1576 // object, which could crash the program. 1577 span.freeIndexForScan = span.freeindex 1578 } 1579 1580 // Note cache c only valid while m acquired; see #47302 1581 // 1582 // N.B. Use the full size because that matches how the GC 1583 // will update the mem profile on the "free" side. 1584 // 1585 // TODO(mknyszek): We should really count the header as part 1586 // of gc_sys or something. The code below just pretends it is 1587 // internal fragmentation and matches the GC's accounting by 1588 // using the whole allocation slot. 1589 c.nextSample -= int64(size) 1590 if c.nextSample < 0 || MemProfileRate != c.memProfRate { 1591 profilealloc(mp, x, size) 1592 } 1593 mp.mallocing = 0 1594 releasem(mp) 1595 1596 if checkGCTrigger { 1597 if t := (gcTrigger{kind: gcTriggerHeap}); t.test() { 1598 gcStart(t) 1599 } 1600 } 1601 return x, size 1602 } 1603 1604 func mallocgcSmallScanHeader(size uintptr, typ *_type) (unsafe.Pointer, uintptr) { 1605 // Set mp.mallocing to keep from being preempted by GC. 1606 mp := acquirem() 1607 if doubleCheckMalloc { 1608 if mp.mallocing != 0 { 1609 throw("malloc deadlock") 1610 } 1611 if mp.gsignal == getg() { 1612 throw("malloc during signal") 1613 } 1614 if typ == nil || !typ.Pointers() { 1615 throw("noscan allocated in scan-only path") 1616 } 1617 if heapBitsInSpan(size) { 1618 throw("heap bits in span for header-only path") 1619 } 1620 } 1621 mp.mallocing = 1 1622 1623 checkGCTrigger := false 1624 c := getMCache(mp) 1625 size += gc.MallocHeaderSize 1626 var sizeclass uint8 1627 if size <= gc.SmallSizeMax-8 { 1628 sizeclass = gc.SizeToSizeClass8[divRoundUp(size, gc.SmallSizeDiv)] 1629 } else { 1630 sizeclass = gc.SizeToSizeClass128[divRoundUp(size-gc.SmallSizeMax, gc.LargeSizeDiv)] 1631 } 1632 size = uintptr(gc.SizeClassToSize[sizeclass]) 1633 spc := makeSpanClass(sizeclass, false) 1634 span := c.alloc[spc] 1635 v := nextFreeFast(span) 1636 if v == 0 { 1637 v, span, checkGCTrigger = c.nextFree(spc) 1638 } 1639 x := unsafe.Pointer(v) 1640 if span.needzero != 0 { 1641 memclrNoHeapPointers(x, size) 1642 } 1643 header := (**_type)(x) 1644 x = add(x, gc.MallocHeaderSize) 1645 c.scanAlloc += heapSetTypeSmallHeader(uintptr(x), size-gc.MallocHeaderSize, typ, header, span) 1646 1647 // Ensure that the stores above that initialize x to 1648 // type-safe memory and set the heap bits occur before 1649 // the caller can make x observable to the garbage 1650 // collector. Otherwise, on weakly ordered machines, 1651 // the garbage collector could follow a pointer to x, 1652 // but see uninitialized memory or stale heap bits. 1653 publicationBarrier() 1654 1655 if writeBarrier.enabled { 1656 // Allocate black during GC. 1657 // All slots hold nil so no scanning is needed. 1658 // This may be racing with GC so do it atomically if there can be 1659 // a race marking the bit. 1660 gcmarknewobject(span, uintptr(x)) 1661 } else { 1662 // Track the last free index before the mark phase. This field 1663 // is only used by the garbage collector. During the mark phase 1664 // this is used by the conservative scanner to filter out objects 1665 // that are both free and recently-allocated. It's safe to do that 1666 // because we allocate-black if the GC is enabled. The conservative 1667 // scanner produces pointers out of thin air, so without additional 1668 // synchronization it might otherwise observe a partially-initialized 1669 // object, which could crash the program. 1670 span.freeIndexForScan = span.freeindex 1671 } 1672 1673 // Note cache c only valid while m acquired; see #47302 1674 // 1675 // N.B. Use the full size because that matches how the GC 1676 // will update the mem profile on the "free" side. 1677 // 1678 // TODO(mknyszek): We should really count the header as part 1679 // of gc_sys or something. The code below just pretends it is 1680 // internal fragmentation and matches the GC's accounting by 1681 // using the whole allocation slot. 1682 c.nextSample -= int64(size) 1683 if c.nextSample < 0 || MemProfileRate != c.memProfRate { 1684 profilealloc(mp, x, size) 1685 } 1686 mp.mallocing = 0 1687 releasem(mp) 1688 1689 if checkGCTrigger { 1690 if t := (gcTrigger{kind: gcTriggerHeap}); t.test() { 1691 gcStart(t) 1692 } 1693 } 1694 return x, size 1695 } 1696 1697 func mallocgcLarge(size uintptr, typ *_type, needzero bool) (unsafe.Pointer, uintptr) { 1698 // Set mp.mallocing to keep from being preempted by GC. 1699 mp := acquirem() 1700 if doubleCheckMalloc { 1701 if mp.mallocing != 0 { 1702 throw("malloc deadlock") 1703 } 1704 if mp.gsignal == getg() { 1705 throw("malloc during signal") 1706 } 1707 } 1708 mp.mallocing = 1 1709 1710 c := getMCache(mp) 1711 // For large allocations, keep track of zeroed state so that 1712 // bulk zeroing can be happen later in a preemptible context. 1713 span := c.allocLarge(size, typ == nil || !typ.Pointers()) 1714 span.freeindex = 1 1715 span.allocCount = 1 1716 span.largeType = nil // Tell the GC not to look at this yet. 1717 size = span.elemsize 1718 x := unsafe.Pointer(span.base()) 1719 1720 // Ensure that the store above that sets largeType to 1721 // nil happens before the caller can make x observable 1722 // to the garbage collector. 1723 // 1724 // Otherwise, on weakly ordered machines, the garbage 1725 // collector could follow a pointer to x, but see a stale 1726 // largeType value. 1727 publicationBarrier() 1728 1729 if writeBarrier.enabled { 1730 // Allocate black during GC. 1731 // All slots hold nil so no scanning is needed. 1732 // This may be racing with GC so do it atomically if there can be 1733 // a race marking the bit. 1734 gcmarknewobject(span, uintptr(x)) 1735 } else { 1736 // Track the last free index before the mark phase. This field 1737 // is only used by the garbage collector. During the mark phase 1738 // this is used by the conservative scanner to filter out objects 1739 // that are both free and recently-allocated. It's safe to do that 1740 // because we allocate-black if the GC is enabled. The conservative 1741 // scanner produces pointers out of thin air, so without additional 1742 // synchronization it might otherwise observe a partially-initialized 1743 // object, which could crash the program. 1744 span.freeIndexForScan = span.freeindex 1745 } 1746 1747 // Note cache c only valid while m acquired; see #47302 1748 // 1749 // N.B. Use the full size because that matches how the GC 1750 // will update the mem profile on the "free" side. 1751 // 1752 // TODO(mknyszek): We should really count the header as part 1753 // of gc_sys or something. The code below just pretends it is 1754 // internal fragmentation and matches the GC's accounting by 1755 // using the whole allocation slot. 1756 c.nextSample -= int64(size) 1757 if c.nextSample < 0 || MemProfileRate != c.memProfRate { 1758 profilealloc(mp, x, size) 1759 } 1760 mp.mallocing = 0 1761 releasem(mp) 1762 1763 // Check to see if we need to trigger the GC. 1764 if t := (gcTrigger{kind: gcTriggerHeap}); t.test() { 1765 gcStart(t) 1766 } 1767 1768 // Objects can be zeroed late in a context where preemption can occur. 1769 // 1770 // x will keep the memory alive. 1771 if needzero && span.needzero != 0 { 1772 // N.B. size == fullSize always in this case. 1773 memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302 1774 } 1775 1776 // Set the type and run the publication barrier while non-preemptible. We need to make 1777 // sure that between heapSetTypeLarge and publicationBarrier we cannot get preempted, 1778 // otherwise the GC could potentially observe non-zeroed memory but largeType set on weak 1779 // memory architectures. 1780 // 1781 // The GC can also potentially observe non-zeroed memory if conservative scanning spuriously 1782 // observes a partially-allocated object, see the freeIndexForScan update above. This case is 1783 // handled by synchronization inside heapSetTypeLarge. 1784 mp = acquirem() 1785 if typ != nil && typ.Pointers() { 1786 // Finish storing the type information, now that we're certain the memory is zeroed. 1787 getMCache(mp).scanAlloc += heapSetTypeLarge(uintptr(x), size, typ, span) 1788 } 1789 // Publish the object again, now with zeroed memory and initialized type information. 1790 // 1791 // Even if we didn't update any type information, this is necessary to ensure that, for example, 1792 // x written to a global without any synchronization still results in other goroutines observing 1793 // zeroed memory. 1794 publicationBarrier() 1795 releasem(mp) 1796 return x, size 1797 } 1798 1799 func preMallocgcDebug(size uintptr, typ *_type) unsafe.Pointer { 1800 if debug.sbrk != 0 { 1801 align := uintptr(16) 1802 if typ != nil { 1803 // TODO(austin): This should be just 1804 // align = uintptr(typ.align) 1805 // but that's only 4 on 32-bit platforms, 1806 // even if there's a uint64 field in typ (see #599). 1807 // This causes 64-bit atomic accesses to panic. 1808 // Hence, we use stricter alignment that matches 1809 // the normal allocator better. 1810 if size&7 == 0 { 1811 align = 8 1812 } else if size&3 == 0 { 1813 align = 4 1814 } else if size&1 == 0 { 1815 align = 2 1816 } else { 1817 align = 1 1818 } 1819 } 1820 return persistentalloc(size, align, &memstats.other_sys) 1821 } 1822 if inittrace.active && inittrace.id == getg().goid { 1823 // Init functions are executed sequentially in a single goroutine. 1824 inittrace.allocs += 1 1825 } 1826 return nil 1827 } 1828 1829 func postMallocgcDebug(x unsafe.Pointer, elemsize uintptr, typ *_type) { 1830 if inittrace.active && inittrace.id == getg().goid { 1831 // Init functions are executed sequentially in a single goroutine. 1832 inittrace.bytes += uint64(elemsize) 1833 } 1834 1835 if traceAllocFreeEnabled() { 1836 trace := traceAcquire() 1837 if trace.ok() { 1838 trace.HeapObjectAlloc(uintptr(x), typ) 1839 traceRelease(trace) 1840 } 1841 } 1842 1843 // N.B. elemsize == 0 indicates a tiny allocation, since no new slot was 1844 // allocated to fulfill this call to mallocgc. This means checkfinalizer 1845 // will only flag an error if there is actually any risk. If an allocation 1846 // has the tiny block to itself, it will not get flagged, because we won't 1847 // mark the block as a tiny block. 1848 if debug.checkfinalizers != 0 && elemsize == 0 { 1849 setTinyBlockContext(unsafe.Pointer(alignDown(uintptr(x), maxTinySize))) 1850 } 1851 } 1852 1853 // addAssistCredit is like deductAssistCredit, 1854 // but adds credit rather than removes, 1855 // and never calls gcAssistAlloc. 1856 func addAssistCredit(size uintptr) { 1857 // Credit the current user G. 1858 assistG := getg() 1859 if assistG.m.curg != nil { // TODO(thepudds): do we need to do this? 1860 assistG = assistG.m.curg 1861 } 1862 // Credit the size against the G. 1863 assistG.gcAssistBytes += int64(size) 1864 } 1865 1866 const ( 1867 // doubleCheckReusable enables some additional invariant checks for the 1868 // runtime.freegc and reusable objects. Note that some of these checks alter timing, 1869 // and it is good to test changes with and without this enabled. 1870 doubleCheckReusable = false 1871 1872 // debugReusableLog enables some printlns for runtime.freegc and reusable objects. 1873 debugReusableLog = false 1874 ) 1875 1876 // freegc records that a heap object is reusable and available for 1877 // immediate reuse in a subsequent mallocgc allocation, without 1878 // needing to wait for the GC cycle to progress. 1879 // 1880 // The information is recorded in a free list stored in the 1881 // current P's mcache. The caller must pass in the user size 1882 // and whether the object has pointers, which allows a faster free 1883 // operation. 1884 // 1885 // freegc must be called by the effective owner of ptr who knows 1886 // the pointer is logically dead, with no possible aliases that might 1887 // be used past that moment. In other words, ptr must be the 1888 // last and only pointer to its referent. 1889 // 1890 // The intended caller is the compiler. 1891 // 1892 // Note: please do not send changes that attempt to add freegc calls 1893 // to the standard library. 1894 // 1895 // ptr must point to a heap object or into the current g's stack, 1896 // in which case freegc is a no-op. In particular, ptr must not point 1897 // to memory in the data or bss sections, which is partially enforced. 1898 // For objects with a malloc header, ptr should point mallocHeaderSize bytes 1899 // past the base; otherwise, ptr should point to the base of the heap object. 1900 // In other words, ptr should be the same pointer that was returned by mallocgc. 1901 // 1902 // In addition, the caller must know that ptr's object has no specials, such 1903 // as might have been created by a call to SetFinalizer or AddCleanup. 1904 // (Internally, the runtime deals appropriately with internally-created 1905 // specials, such as specials for memory profiling). 1906 // 1907 // If the size of ptr's object is less than 16 bytes or greater than 1908 // 32KiB - gc.MallocHeaderSize bytes, freegc is currently a no-op. It must only 1909 // be called in alloc-safe places. It currently throws if noscan is false 1910 // (support for which is implemented in a later CL in our stack). 1911 // 1912 // Note that freegc accepts an unsafe.Pointer and hence keeps the pointer 1913 // alive. It therefore could be a pessimization in some cases (such 1914 // as a long-lived function) if the caller does not call freegc before 1915 // or roughly when the liveness analysis of the compiler 1916 // would otherwise have determined ptr's object is reclaimable by the GC. 1917 func freegc(ptr unsafe.Pointer, size uintptr, noscan bool) bool { 1918 if !runtimeFreegcEnabled || !reusableSize(size) { 1919 return false 1920 } 1921 if sizeSpecializedMallocEnabled && !noscan { 1922 // TODO(thepudds): temporarily disable freegc with SizeSpecializedMalloc for pointer types 1923 // until we finish integrating. 1924 return false 1925 } 1926 1927 if ptr == nil { 1928 throw("freegc nil") 1929 } 1930 1931 // Set mp.mallocing to keep from being preempted by GC. 1932 // Otherwise, the GC could flush our mcache or otherwise cause problems. 1933 mp := acquirem() 1934 if mp.mallocing != 0 { 1935 throw("freegc deadlock") 1936 } 1937 if mp.gsignal == getg() { 1938 throw("freegc during signal") 1939 } 1940 mp.mallocing = 1 1941 1942 if mp.curg.stack.lo <= uintptr(ptr) && uintptr(ptr) < mp.curg.stack.hi { 1943 // This points into our stack, so free is a no-op. 1944 mp.mallocing = 0 1945 releasem(mp) 1946 return false 1947 } 1948 1949 if doubleCheckReusable { 1950 // TODO(thepudds): we could enforce no free on globals in bss or data. Maybe by 1951 // checking span via spanOf or spanOfHeap, or maybe walk from firstmoduledata 1952 // like isGoPointerWithoutSpan, or activeModules, or something. If so, we might 1953 // be able to delay checking until reuse (e.g., check span just before reusing, 1954 // though currently we don't always need to lookup a span on reuse). If we think 1955 // no usage patterns could result in globals, maybe enforcement for globals could 1956 // be behind -d=checkptr=1 or similar. The compiler can have knowledge of where 1957 // a variable is allocated, but stdlib does not, although there are certain 1958 // usage patterns that cannot result in a global. 1959 // TODO(thepudds): separately, consider a local debugReusableMcacheOnly here 1960 // to ignore freed objects if not in mspan in mcache, maybe when freeing and reading, 1961 // by checking something like s.base() <= uintptr(v) && uintptr(v) < s.limit. Or 1962 // maybe a GODEBUG or compiler debug flag. 1963 span := spanOf(uintptr(ptr)) 1964 if span == nil { 1965 throw("nextReusable: nil span for pointer in free list") 1966 } 1967 if state := span.state.get(); state != mSpanInUse { 1968 throw("nextReusable: span is not in use") 1969 } 1970 } 1971 1972 if debug.clobberfree != 0 { 1973 clobberfree(ptr, size) 1974 } 1975 1976 // We first check if p is still in our per-P cache. 1977 // Get our per-P cache for small objects. 1978 c := getMCache(mp) 1979 if c == nil { 1980 throw("freegc called without a P or outside bootstrapping") 1981 } 1982 1983 v := uintptr(ptr) 1984 if !noscan && !heapBitsInSpan(size) { 1985 // mallocgcSmallScanHeader expects to get the base address of the object back 1986 // from the findReusable funcs (as well as from nextFreeFast and nextFree), and 1987 // not mallocHeaderSize bytes into a object, so adjust that here. 1988 v -= mallocHeaderSize 1989 1990 // The size class lookup wants size to be adjusted by mallocHeaderSize. 1991 size += mallocHeaderSize 1992 } 1993 1994 // TODO(thepudds): should verify (behind doubleCheckReusable constant) that our calculated 1995 // sizeclass here matches what's in span found via spanOf(ptr) or findObject(ptr). 1996 var sizeclass uint8 1997 if size <= gc.SmallSizeMax-8 { 1998 sizeclass = gc.SizeToSizeClass8[divRoundUp(size, gc.SmallSizeDiv)] 1999 } else { 2000 sizeclass = gc.SizeToSizeClass128[divRoundUp(size-gc.SmallSizeMax, gc.LargeSizeDiv)] 2001 } 2002 2003 spc := makeSpanClass(sizeclass, noscan) 2004 s := c.alloc[spc] 2005 2006 if debugReusableLog { 2007 if s.base() <= uintptr(v) && uintptr(v) < s.limit { 2008 println("freegc [in mcache]:", hex(uintptr(v)), "sweepgen:", mheap_.sweepgen, "writeBarrier.enabled:", writeBarrier.enabled) 2009 } else { 2010 println("freegc [NOT in mcache]:", hex(uintptr(v)), "sweepgen:", mheap_.sweepgen, "writeBarrier.enabled:", writeBarrier.enabled) 2011 } 2012 } 2013 2014 if noscan { 2015 c.addReusableNoscan(spc, uintptr(v)) 2016 } else { 2017 // TODO(thepudds): implemented in later CL in our stack. 2018 throw("freegc called for object with pointers, not yet implemented") 2019 } 2020 2021 // For stats, for now we leave allocCount alone, roughly pretending to the rest 2022 // of the system that this potential reuse never happened. 2023 2024 mp.mallocing = 0 2025 releasem(mp) 2026 2027 return true 2028 } 2029 2030 // nextReusableNoScan returns the next reusable object for a noscan span, 2031 // or 0 if no reusable object is found. 2032 func (c *mcache) nextReusableNoScan(s *mspan, spc spanClass) (gclinkptr, *mspan) { 2033 if !runtimeFreegcEnabled { 2034 return 0, s 2035 } 2036 2037 // Pop a reusable pointer from the free list for this span class. 2038 v := c.reusableNoscan[spc] 2039 if v == 0 { 2040 return 0, s 2041 } 2042 c.reusableNoscan[spc] = v.ptr().next 2043 2044 if debugReusableLog { 2045 println("reusing from ptr free list:", hex(v), "sweepgen:", mheap_.sweepgen, "writeBarrier.enabled:", writeBarrier.enabled) 2046 } 2047 if doubleCheckReusable { 2048 doubleCheckNextReusable(v) // debug only sanity check 2049 } 2050 2051 // For noscan spans, we only need the span if the write barrier is enabled (so that our caller 2052 // can call gcmarknewobject to allocate black). If the write barrier is enabled, we can skip 2053 // looking up the span when the pointer is in a span in the mcache. 2054 if !writeBarrier.enabled { 2055 return v, nil 2056 } 2057 if s.base() <= uintptr(v) && uintptr(v) < s.limit { 2058 // Return the original span. 2059 return v, s 2060 } 2061 2062 // We must find and return the span. 2063 span := spanOf(uintptr(v)) 2064 if span == nil { 2065 // TODO(thepudds): construct a test that triggers this throw. 2066 throw("nextReusableNoScan: nil span for pointer in reusable object free list") 2067 } 2068 2069 return v, span 2070 } 2071 2072 // doubleCheckNextReusable checks some invariants. 2073 // TODO(thepudds): will probably delete some of this. Can mostly be ignored for review. 2074 func doubleCheckNextReusable(v gclinkptr) { 2075 // TODO(thepudds): should probably take the spanClass as well to confirm expected 2076 // sizeclass match. 2077 _, span, objIndex := findObject(uintptr(v), 0, 0) 2078 if span == nil { 2079 throw("nextReusable: nil span for pointer in free list") 2080 } 2081 if state := span.state.get(); state != mSpanInUse { 2082 throw("nextReusable: span is not in use") 2083 } 2084 if uintptr(v) < span.base() || uintptr(v) >= span.limit { 2085 throw("nextReusable: span is not in range") 2086 } 2087 if span.objBase(uintptr(v)) != uintptr(v) { 2088 print("nextReusable: v=", hex(v), " base=", hex(span.objBase(uintptr(v))), "\n") 2089 throw("nextReusable: v is non-base-address for object found on pointer free list") 2090 } 2091 if span.isFree(objIndex) { 2092 throw("nextReusable: pointer on free list is free") 2093 } 2094 2095 const debugReusableEnsureSwept = false 2096 if debugReusableEnsureSwept { 2097 // Currently disabled. 2098 // Note: ensureSwept here alters behavior (not just an invariant check). 2099 span.ensureSwept() 2100 if span.isFree(objIndex) { 2101 throw("nextReusable: pointer on free list is free after ensureSwept") 2102 } 2103 } 2104 } 2105 2106 // reusableSize reports if size is a currently supported size for a reusable object. 2107 func reusableSize(size uintptr) bool { 2108 if size < maxTinySize || size > maxSmallSize-mallocHeaderSize { 2109 return false 2110 } 2111 return true 2112 } 2113 2114 // memclrNoHeapPointersChunked repeatedly calls memclrNoHeapPointers 2115 // on chunks of the buffer to be zeroed, with opportunities for preemption 2116 // along the way. memclrNoHeapPointers contains no safepoints and also 2117 // cannot be preemptively scheduled, so this provides a still-efficient 2118 // block copy that can also be preempted on a reasonable granularity. 2119 // 2120 // Use this with care; if the data being cleared is tagged to contain 2121 // pointers, this allows the GC to run before it is all cleared. 2122 func memclrNoHeapPointersChunked(size uintptr, x unsafe.Pointer) { 2123 v := uintptr(x) 2124 // got this from benchmarking. 128k is too small, 512k is too large. 2125 const chunkBytes = 256 * 1024 2126 vsize := v + size 2127 for voff := v; voff < vsize; voff = voff + chunkBytes { 2128 if getg().preempt { 2129 // may hold locks, e.g., profiling 2130 goschedguarded() 2131 } 2132 // clear min(avail, lump) bytes 2133 n := vsize - voff 2134 if n > chunkBytes { 2135 n = chunkBytes 2136 } 2137 memclrNoHeapPointers(unsafe.Pointer(voff), n) 2138 } 2139 } 2140 2141 // implementation of new builtin 2142 // compiler (both frontend and SSA backend) knows the signature 2143 // of this function. 2144 func newobject(typ *_type) unsafe.Pointer { 2145 return mallocgc(typ.Size_, typ, true) 2146 } 2147 2148 //go:linkname maps_newobject internal/runtime/maps.newobject 2149 func maps_newobject(typ *_type) unsafe.Pointer { 2150 return newobject(typ) 2151 } 2152 2153 // reflect_unsafe_New is meant for package reflect, 2154 // but widely used packages access it using linkname. 2155 // Notable members of the hall of shame include: 2156 // - gitee.com/quant1x/gox 2157 // - github.com/goccy/json 2158 // - github.com/modern-go/reflect2 2159 // - github.com/v2pro/plz 2160 // 2161 // Do not remove or change the type signature. 2162 // See go.dev/issue/67401. 2163 // 2164 //go:linkname reflect_unsafe_New reflect.unsafe_New 2165 func reflect_unsafe_New(typ *_type) unsafe.Pointer { 2166 return mallocgc(typ.Size_, typ, true) 2167 } 2168 2169 //go:linkname reflectlite_unsafe_New internal/reflectlite.unsafe_New 2170 func reflectlite_unsafe_New(typ *_type) unsafe.Pointer { 2171 return mallocgc(typ.Size_, typ, true) 2172 } 2173 2174 // newarray allocates an array of n elements of type typ. 2175 // 2176 // newarray should be an internal detail, 2177 // but widely used packages access it using linkname. 2178 // Notable members of the hall of shame include: 2179 // - github.com/RomiChan/protobuf 2180 // - github.com/segmentio/encoding 2181 // - github.com/ugorji/go/codec 2182 // 2183 // Do not remove or change the type signature. 2184 // See go.dev/issue/67401. 2185 // 2186 //go:linkname newarray 2187 func newarray(typ *_type, n int) unsafe.Pointer { 2188 if n == 1 { 2189 return mallocgc(typ.Size_, typ, true) 2190 } 2191 mem, overflow := math.MulUintptr(typ.Size_, uintptr(n)) 2192 if overflow || mem > maxAlloc || n < 0 { 2193 panic(plainError("runtime: allocation size out of range")) 2194 } 2195 return mallocgc(mem, typ, true) 2196 } 2197 2198 // reflect_unsafe_NewArray is meant for package reflect, 2199 // but widely used packages access it using linkname. 2200 // Notable members of the hall of shame include: 2201 // - gitee.com/quant1x/gox 2202 // - github.com/bytedance/sonic 2203 // - github.com/goccy/json 2204 // - github.com/modern-go/reflect2 2205 // - github.com/segmentio/encoding 2206 // - github.com/segmentio/kafka-go 2207 // - github.com/v2pro/plz 2208 // 2209 // Do not remove or change the type signature. 2210 // See go.dev/issue/67401. 2211 // 2212 //go:linkname reflect_unsafe_NewArray reflect.unsafe_NewArray 2213 func reflect_unsafe_NewArray(typ *_type, n int) unsafe.Pointer { 2214 return newarray(typ, n) 2215 } 2216 2217 //go:linkname maps_newarray internal/runtime/maps.newarray 2218 func maps_newarray(typ *_type, n int) unsafe.Pointer { 2219 return newarray(typ, n) 2220 } 2221 2222 // profilealloc resets the current mcache's nextSample counter and 2223 // records a memory profile sample. 2224 // 2225 // The caller must be non-preemptible and have a P. 2226 func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { 2227 c := getMCache(mp) 2228 if c == nil { 2229 throw("profilealloc called without a P or outside bootstrapping") 2230 } 2231 c.memProfRate = MemProfileRate 2232 c.nextSample = nextSample() 2233 mProf_Malloc(mp, x, size) 2234 } 2235 2236 // nextSample returns the next sampling point for heap profiling. The goal is 2237 // to sample allocations on average every MemProfileRate bytes, but with a 2238 // completely random distribution over the allocation timeline; this 2239 // corresponds to a Poisson process with parameter MemProfileRate. In Poisson 2240 // processes, the distance between two samples follows the exponential 2241 // distribution (exp(MemProfileRate)), so the best return value is a random 2242 // number taken from an exponential distribution whose mean is MemProfileRate. 2243 func nextSample() int64 { 2244 if MemProfileRate == 0 { 2245 // Basically never sample. 2246 return math.MaxInt64 2247 } 2248 if MemProfileRate == 1 { 2249 // Sample immediately. 2250 return 0 2251 } 2252 return int64(fastexprand(MemProfileRate)) 2253 } 2254 2255 // fastexprand returns a random number from an exponential distribution with 2256 // the specified mean. 2257 func fastexprand(mean int) int32 { 2258 // Avoid overflow. Maximum possible step is 2259 // -ln(1/(1<<randomBitCount)) * mean, approximately 20 * mean. 2260 switch { 2261 case mean > 0x7000000: 2262 mean = 0x7000000 2263 case mean == 0: 2264 return 0 2265 } 2266 2267 // Take a random sample of the exponential distribution exp(-mean*x). 2268 // The probability distribution function is mean*exp(-mean*x), so the CDF is 2269 // p = 1 - exp(-mean*x), so 2270 // q = 1 - p == exp(-mean*x) 2271 // log_e(q) = -mean*x 2272 // -log_e(q)/mean = x 2273 // x = -log_e(q) * mean 2274 // x = log_2(q) * (-log_e(2)) * mean ; Using log_2 for efficiency 2275 const randomBitCount = 26 2276 q := cheaprandn(1<<randomBitCount) + 1 2277 qlog := fastlog2(float64(q)) - randomBitCount 2278 if qlog > 0 { 2279 qlog = 0 2280 } 2281 const minusLog2 = -0.6931471805599453 // -ln(2) 2282 return int32(qlog*(minusLog2*float64(mean))) + 1 2283 } 2284 2285 type persistentAlloc struct { 2286 base *notInHeap 2287 off uintptr 2288 } 2289 2290 var globalAlloc struct { 2291 mutex 2292 persistentAlloc 2293 } 2294 2295 // persistentChunkSize is the number of bytes we allocate when we grow 2296 // a persistentAlloc. 2297 const persistentChunkSize = 256 << 10 2298 2299 // persistentChunks is a list of all the persistent chunks we have 2300 // allocated. The list is maintained through the first word in the 2301 // persistent chunk. This is updated atomically. 2302 var persistentChunks *notInHeap 2303 2304 // Wrapper around sysAlloc that can allocate small chunks. 2305 // There is no associated free operation. 2306 // Intended for things like function/type/debug-related persistent data. 2307 // If align is 0, uses default align (currently 8). 2308 // The returned memory will be zeroed. 2309 // sysStat must be non-nil. 2310 // 2311 // Consider marking persistentalloc'd types not in heap by embedding 2312 // internal/runtime/sys.NotInHeap. 2313 // 2314 // nosplit because it is used during write barriers and must not be preempted. 2315 // 2316 //go:nosplit 2317 func persistentalloc(size, align uintptr, sysStat *sysMemStat) unsafe.Pointer { 2318 var p *notInHeap 2319 systemstack(func() { 2320 p = persistentalloc1(size, align, sysStat) 2321 }) 2322 return unsafe.Pointer(p) 2323 } 2324 2325 // Must run on system stack because stack growth can (re)invoke it. 2326 // See issue 9174. 2327 // 2328 //go:systemstack 2329 func persistentalloc1(size, align uintptr, sysStat *sysMemStat) *notInHeap { 2330 const ( 2331 maxBlock = 64 << 10 // VM reservation granularity is 64K on windows 2332 ) 2333 2334 if size == 0 { 2335 throw("persistentalloc: size == 0") 2336 } 2337 if align != 0 { 2338 if align&(align-1) != 0 { 2339 throw("persistentalloc: align is not a power of 2") 2340 } 2341 if align > pageSize { 2342 throw("persistentalloc: align is too large") 2343 } 2344 } else { 2345 align = 8 2346 } 2347 2348 if size >= maxBlock { 2349 return (*notInHeap)(sysAlloc(size, sysStat, "immortal metadata")) 2350 } 2351 2352 mp := acquirem() 2353 var persistent *persistentAlloc 2354 if mp != nil && mp.p != 0 { 2355 persistent = &mp.p.ptr().palloc 2356 } else { 2357 lock(&globalAlloc.mutex) 2358 persistent = &globalAlloc.persistentAlloc 2359 } 2360 persistent.off = alignUp(persistent.off, align) 2361 if persistent.off+size > persistentChunkSize || persistent.base == nil { 2362 persistent.base = (*notInHeap)(sysAlloc(persistentChunkSize, &memstats.other_sys, "immortal metadata")) 2363 if persistent.base == nil { 2364 if persistent == &globalAlloc.persistentAlloc { 2365 unlock(&globalAlloc.mutex) 2366 } 2367 throw("runtime: cannot allocate memory") 2368 } 2369 2370 // Add the new chunk to the persistentChunks list. 2371 for { 2372 chunks := uintptr(unsafe.Pointer(persistentChunks)) 2373 *(*uintptr)(unsafe.Pointer(persistent.base)) = chunks 2374 if atomic.Casuintptr((*uintptr)(unsafe.Pointer(&persistentChunks)), chunks, uintptr(unsafe.Pointer(persistent.base))) { 2375 break 2376 } 2377 } 2378 persistent.off = alignUp(goarch.PtrSize, align) 2379 } 2380 p := persistent.base.add(persistent.off) 2381 persistent.off += size 2382 releasem(mp) 2383 if persistent == &globalAlloc.persistentAlloc { 2384 unlock(&globalAlloc.mutex) 2385 } 2386 2387 if sysStat != &memstats.other_sys { 2388 sysStat.add(int64(size)) 2389 memstats.other_sys.add(-int64(size)) 2390 } 2391 return p 2392 } 2393 2394 // inPersistentAlloc reports whether p points to memory allocated by 2395 // persistentalloc. This must be nosplit because it is called by the 2396 // cgo checker code, which is called by the write barrier code. 2397 // 2398 //go:nosplit 2399 func inPersistentAlloc(p uintptr) bool { 2400 chunk := atomic.Loaduintptr((*uintptr)(unsafe.Pointer(&persistentChunks))) 2401 for chunk != 0 { 2402 if p >= chunk && p < chunk+persistentChunkSize { 2403 return true 2404 } 2405 chunk = *(*uintptr)(unsafe.Pointer(chunk)) 2406 } 2407 return false 2408 } 2409 2410 // linearAlloc is a simple linear allocator that pre-reserves a region 2411 // of memory and then optionally maps that region into the Ready state 2412 // as needed. 2413 // 2414 // The caller is responsible for locking. 2415 type linearAlloc struct { 2416 next uintptr // next free byte 2417 mapped uintptr // one byte past end of mapped space 2418 end uintptr // end of reserved space 2419 2420 mapMemory bool // transition memory from Reserved to Ready if true 2421 } 2422 2423 func (l *linearAlloc) init(base, size uintptr, mapMemory bool) { 2424 if base+size < base { 2425 // Chop off the last byte. The runtime isn't prepared 2426 // to deal with situations where the bounds could overflow. 2427 // Leave that memory reserved, though, so we don't map it 2428 // later. 2429 size -= 1 2430 } 2431 l.next, l.mapped = base, base 2432 l.end = base + size 2433 l.mapMemory = mapMemory 2434 } 2435 2436 func (l *linearAlloc) alloc(size, align uintptr, sysStat *sysMemStat, vmaName string) unsafe.Pointer { 2437 p := alignUp(l.next, align) 2438 if p+size > l.end { 2439 return nil 2440 } 2441 l.next = p + size 2442 if pEnd := alignUp(l.next-1, physPageSize); pEnd > l.mapped { 2443 if l.mapMemory { 2444 // Transition from Reserved to Prepared to Ready. 2445 n := pEnd - l.mapped 2446 sysMap(unsafe.Pointer(l.mapped), n, sysStat, vmaName) 2447 sysUsed(unsafe.Pointer(l.mapped), n, n) 2448 } 2449 l.mapped = pEnd 2450 } 2451 return unsafe.Pointer(p) 2452 } 2453 2454 // notInHeap is off-heap memory allocated by a lower-level allocator 2455 // like sysAlloc or persistentAlloc. 2456 // 2457 // In general, it's better to use real types which embed 2458 // internal/runtime/sys.NotInHeap, but this serves as a generic type 2459 // for situations where that isn't possible (like in the allocators). 2460 // 2461 // TODO: Use this as the return type of sysAlloc, persistentAlloc, etc? 2462 type notInHeap struct{ _ sys.NotInHeap } 2463 2464 func (p *notInHeap) add(bytes uintptr) *notInHeap { 2465 return (*notInHeap)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + bytes)) 2466 } 2467 2468 // redZoneSize computes the size of the redzone for a given allocation. 2469 // Refer to the implementation of the compiler-rt. 2470 func redZoneSize(userSize uintptr) uintptr { 2471 switch { 2472 case userSize <= (64 - 16): 2473 return 16 << 0 2474 case userSize <= (128 - 32): 2475 return 16 << 1 2476 case userSize <= (512 - 64): 2477 return 16 << 2 2478 case userSize <= (4096 - 128): 2479 return 16 << 3 2480 case userSize <= (1<<14)-256: 2481 return 16 << 4 2482 case userSize <= (1<<15)-512: 2483 return 16 << 5 2484 case userSize <= (1<<16)-1024: 2485 return 16 << 6 2486 default: 2487 return 16 << 7 2488 } 2489 } 2490