mirror of
https://github.com/golang/go.git
synced 2026-06-27 19:30:52 +00:00
runtime: further reduce number of size classes
We now will only generate size specialized functions for size clases less than or equal to 7. This brings down the size of the generated functions from around 21k to around 16k. For #79286 Change-Id: I1adafd3674004069ed6461ef63228bfc6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/780300 Reviewed-by: Michael Matloob <matloob@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
3652f299a8
commit
694604e524
6 changed files with 9 additions and 835 deletions
|
|
@ -39,8 +39,8 @@ type symsStruct struct {
|
|||
InterfaceSwitch *obj.LSym
|
||||
MallocGC *obj.LSym
|
||||
MallocGCTiny *obj.LSym
|
||||
MallocGCSmallNoScan [11]*obj.LSym
|
||||
MallocGCSmallScanNoHeader [11]*obj.LSym
|
||||
MallocGCSmallNoScan [8]*obj.LSym
|
||||
MallocGCSmallScanNoHeader [8]*obj.LSym
|
||||
Memmove *obj.LSym
|
||||
Memequal *obj.LSym
|
||||
Msanread *obj.LSym
|
||||
|
|
|
|||
|
|
@ -806,7 +806,7 @@ func (s *state) specializedMallocSym(size int64, hasPointers bool) *obj.LSym {
|
|||
if !s.sizeSpecializedMallocEnabled() {
|
||||
return nil
|
||||
}
|
||||
const specializedMallocMax = 128 // This must match the constant in mkmalloc.
|
||||
const specializedMallocMax = 80 // This must match the constant in mkmalloc.
|
||||
if size > specializedMallocMax {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,5 +27,5 @@ const (
|
|||
// size classes, and with the wrapper they are sometimes slower
|
||||
// than the non-specialized functions.
|
||||
// This must match the constant in the compiler.
|
||||
specializedMallocMax = 128
|
||||
specializedMallocMax = 80
|
||||
)
|
||||
|
|
|
|||
|
|
@ -888,16 +888,16 @@ package runtime
|
|||
|
||||
import "unsafe"
|
||||
|
||||
var mallocScanTable = [129]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{`)
|
||||
var mallocScanTable = [%d]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{`, specializedMallocMax+1)
|
||||
|
||||
for i := range uintptr(specializedMallocMax + 1) {
|
||||
fmt.Fprintf(&b, "%s,\n", smallScanNoHeaderSCFuncName(sizeToSizeClass[i], scMax))
|
||||
}
|
||||
|
||||
fmt.Fprintln(&b, `
|
||||
fmt.Fprintf(&b, `
|
||||
}
|
||||
|
||||
var mallocNoScanTable = [129]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{`)
|
||||
var mallocNoScanTable = [%d]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{`, specializedMallocMax+1)
|
||||
for i := range uintptr(specializedMallocMax + 1) {
|
||||
if i < 16 {
|
||||
fmt.Fprintf(&b, "%s,\n", "mallocPanic")
|
||||
|
|
|
|||
|
|
@ -1053,453 +1053,6 @@ func mallocgcSmallScanNoHeaderSC7(size uintptr, typ *_type, needzero bool) unsaf
|
|||
return x
|
||||
}
|
||||
|
||||
func mallocgcSmallScanNoHeaderSC8(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
||||
if forceSlowPath {
|
||||
|
||||
const spc = spanClass(8<<1) | spanClass(0)
|
||||
const elemsize = uintptr(96)
|
||||
return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize)
|
||||
}
|
||||
|
||||
if doubleCheckMalloc {
|
||||
if gcphase == _GCmarktermination {
|
||||
throw("mallocgc called with gcphase == _GCmarktermination")
|
||||
}
|
||||
}
|
||||
|
||||
lockRankMayQueueFinalizer()
|
||||
|
||||
const sizeclass = 8
|
||||
const elemsize = 96
|
||||
|
||||
mp := acquirem()
|
||||
if doubleCheckMalloc {
|
||||
|
||||
doubleCheckSmallScanNoHeader(size, typ, mp)
|
||||
|
||||
}
|
||||
mp.mallocing = 1
|
||||
|
||||
checkGCTrigger := false
|
||||
c := getMCache(mp)
|
||||
const spc = spanClass(sizeclass<<1) | spanClass(0)
|
||||
span := c.alloc[spc]
|
||||
|
||||
var v gclinkptr
|
||||
var x unsafe.Pointer
|
||||
|
||||
{
|
||||
|
||||
var nextFreeFastResult gclinkptr
|
||||
if span.allocCache != 0 {
|
||||
theBit := sys.TrailingZeros64(span.allocCache)
|
||||
result := span.freeindex + uint16(theBit)
|
||||
if result < span.nelems {
|
||||
freeidx := result + 1
|
||||
if !(freeidx%64 == 0 && freeidx != span.nelems) {
|
||||
span.allocCache >>= uint(theBit + 1)
|
||||
span.freeindex = freeidx
|
||||
span.allocCount++
|
||||
nextFreeFastResult = gclinkptr(uintptr(result)*elemsize + span.base())
|
||||
}
|
||||
}
|
||||
}
|
||||
v = nextFreeFastResult
|
||||
if v == 0 {
|
||||
v, span, checkGCTrigger = c.nextFree(spc)
|
||||
}
|
||||
x = unsafe.Pointer(v)
|
||||
}
|
||||
|
||||
if span.needzero != 0 {
|
||||
memclrNoHeapPointers(x, elemsize)
|
||||
}
|
||||
if goarch.PtrSize == 8 && elemsize == 8 {
|
||||
|
||||
c.scanAlloc += 8
|
||||
} else {
|
||||
dataSize := size
|
||||
x := uintptr(x)
|
||||
|
||||
if doubleCheckHeapSetType && (!heapBitsInSpan(dataSize) || !heapBitsInSpan(96)) {
|
||||
throw("tried to write heap bits, but no heap bits in span")
|
||||
}
|
||||
|
||||
src0 := readUintptr(getGCMask(typ))
|
||||
|
||||
const elemsize = 96
|
||||
|
||||
var scanSize uintptr
|
||||
src := src0
|
||||
if typ.Size_ == goarch.PtrSize {
|
||||
src = (1 << (dataSize / goarch.PtrSize)) - 1
|
||||
|
||||
scanSize = dataSize
|
||||
} else {
|
||||
|
||||
if doubleCheckHeapSetType && !asanenabled && dataSize%typ.Size_ != 0 {
|
||||
throw("runtime: (*mspan).writeHeapBitsSmall: dataSize is not a multiple of typ.Size_")
|
||||
}
|
||||
scanSize = typ.PtrBytes
|
||||
for i := typ.Size_; i < dataSize; i += typ.Size_ {
|
||||
src |= src0 << (i / goarch.PtrSize)
|
||||
scanSize += typ.Size_
|
||||
}
|
||||
}
|
||||
|
||||
dstBase, _ := spanHeapBitsRange(span.base(), pageSize, elemsize)
|
||||
dst := unsafe.Pointer(dstBase)
|
||||
o := (x - span.base()) / goarch.PtrSize
|
||||
i := o / ptrBits
|
||||
j := o % ptrBits
|
||||
var bits uintptr = elemsize / goarch.PtrSize
|
||||
|
||||
var bitsIsPowerOfTwo = bits&(bits-1) == 0
|
||||
if bits > ptrBits || (!bitsIsPowerOfTwo && j+bits > ptrBits) {
|
||||
|
||||
bits0 := ptrBits - j
|
||||
bits1 := bits - bits0
|
||||
dst0 := (*uintptr)(add(dst, (i+0)*goarch.PtrSize))
|
||||
dst1 := (*uintptr)(add(dst, (i+1)*goarch.PtrSize))
|
||||
*dst0 = (*dst0)&(^uintptr(0)>>bits0) | (src << j)
|
||||
*dst1 = (*dst1)&^((1<<bits1)-1) | (src >> bits0)
|
||||
} else {
|
||||
|
||||
dst := (*uintptr)(add(dst, i*goarch.PtrSize))
|
||||
*dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)<<j) | (src << j)
|
||||
}
|
||||
|
||||
const doubleCheck = false
|
||||
if doubleCheck {
|
||||
writeHeapBitsDoubleCheck(span, x, dataSize, src, src0, i, j, bits, typ)
|
||||
}
|
||||
if doubleCheckHeapSetType {
|
||||
doubleCheckHeapType(x, dataSize, typ, nil, span)
|
||||
}
|
||||
c.scanAlloc += scanSize
|
||||
}
|
||||
|
||||
publicationBarrier()
|
||||
|
||||
span.freeIndexForScan = span.freeindex
|
||||
|
||||
c.nextSample -= int64(elemsize)
|
||||
if c.nextSample < 0 || MemProfileRate != c.memProfRate {
|
||||
profilealloc(mp, x, elemsize)
|
||||
}
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
if checkGCTrigger {
|
||||
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
|
||||
gcStart(t)
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func mallocgcSmallScanNoHeaderSC9(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
||||
if forceSlowPath {
|
||||
|
||||
const spc = spanClass(9<<1) | spanClass(0)
|
||||
const elemsize = uintptr(112)
|
||||
return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize)
|
||||
}
|
||||
|
||||
if doubleCheckMalloc {
|
||||
if gcphase == _GCmarktermination {
|
||||
throw("mallocgc called with gcphase == _GCmarktermination")
|
||||
}
|
||||
}
|
||||
|
||||
lockRankMayQueueFinalizer()
|
||||
|
||||
const sizeclass = 9
|
||||
const elemsize = 112
|
||||
|
||||
mp := acquirem()
|
||||
if doubleCheckMalloc {
|
||||
|
||||
doubleCheckSmallScanNoHeader(size, typ, mp)
|
||||
|
||||
}
|
||||
mp.mallocing = 1
|
||||
|
||||
checkGCTrigger := false
|
||||
c := getMCache(mp)
|
||||
const spc = spanClass(sizeclass<<1) | spanClass(0)
|
||||
span := c.alloc[spc]
|
||||
|
||||
var v gclinkptr
|
||||
var x unsafe.Pointer
|
||||
|
||||
{
|
||||
|
||||
var nextFreeFastResult gclinkptr
|
||||
if span.allocCache != 0 {
|
||||
theBit := sys.TrailingZeros64(span.allocCache)
|
||||
result := span.freeindex + uint16(theBit)
|
||||
if result < span.nelems {
|
||||
freeidx := result + 1
|
||||
if !(freeidx%64 == 0 && freeidx != span.nelems) {
|
||||
span.allocCache >>= uint(theBit + 1)
|
||||
span.freeindex = freeidx
|
||||
span.allocCount++
|
||||
nextFreeFastResult = gclinkptr(uintptr(result)*elemsize + span.base())
|
||||
}
|
||||
}
|
||||
}
|
||||
v = nextFreeFastResult
|
||||
if v == 0 {
|
||||
v, span, checkGCTrigger = c.nextFree(spc)
|
||||
}
|
||||
x = unsafe.Pointer(v)
|
||||
}
|
||||
|
||||
if span.needzero != 0 {
|
||||
memclrNoHeapPointers(x, elemsize)
|
||||
}
|
||||
if goarch.PtrSize == 8 && elemsize == 8 {
|
||||
|
||||
c.scanAlloc += 8
|
||||
} else {
|
||||
dataSize := size
|
||||
x := uintptr(x)
|
||||
|
||||
if doubleCheckHeapSetType && (!heapBitsInSpan(dataSize) || !heapBitsInSpan(112)) {
|
||||
throw("tried to write heap bits, but no heap bits in span")
|
||||
}
|
||||
|
||||
src0 := readUintptr(getGCMask(typ))
|
||||
|
||||
const elemsize = 112
|
||||
|
||||
var scanSize uintptr
|
||||
src := src0
|
||||
if typ.Size_ == goarch.PtrSize {
|
||||
src = (1 << (dataSize / goarch.PtrSize)) - 1
|
||||
|
||||
scanSize = dataSize
|
||||
} else {
|
||||
|
||||
if doubleCheckHeapSetType && !asanenabled && dataSize%typ.Size_ != 0 {
|
||||
throw("runtime: (*mspan).writeHeapBitsSmall: dataSize is not a multiple of typ.Size_")
|
||||
}
|
||||
scanSize = typ.PtrBytes
|
||||
for i := typ.Size_; i < dataSize; i += typ.Size_ {
|
||||
src |= src0 << (i / goarch.PtrSize)
|
||||
scanSize += typ.Size_
|
||||
}
|
||||
}
|
||||
|
||||
dstBase, _ := spanHeapBitsRange(span.base(), pageSize, elemsize)
|
||||
dst := unsafe.Pointer(dstBase)
|
||||
o := (x - span.base()) / goarch.PtrSize
|
||||
i := o / ptrBits
|
||||
j := o % ptrBits
|
||||
var bits uintptr = elemsize / goarch.PtrSize
|
||||
|
||||
var bitsIsPowerOfTwo = bits&(bits-1) == 0
|
||||
if bits > ptrBits || (!bitsIsPowerOfTwo && j+bits > ptrBits) {
|
||||
|
||||
bits0 := ptrBits - j
|
||||
bits1 := bits - bits0
|
||||
dst0 := (*uintptr)(add(dst, (i+0)*goarch.PtrSize))
|
||||
dst1 := (*uintptr)(add(dst, (i+1)*goarch.PtrSize))
|
||||
*dst0 = (*dst0)&(^uintptr(0)>>bits0) | (src << j)
|
||||
*dst1 = (*dst1)&^((1<<bits1)-1) | (src >> bits0)
|
||||
} else {
|
||||
|
||||
dst := (*uintptr)(add(dst, i*goarch.PtrSize))
|
||||
*dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)<<j) | (src << j)
|
||||
}
|
||||
|
||||
const doubleCheck = false
|
||||
if doubleCheck {
|
||||
writeHeapBitsDoubleCheck(span, x, dataSize, src, src0, i, j, bits, typ)
|
||||
}
|
||||
if doubleCheckHeapSetType {
|
||||
doubleCheckHeapType(x, dataSize, typ, nil, span)
|
||||
}
|
||||
c.scanAlloc += scanSize
|
||||
}
|
||||
|
||||
publicationBarrier()
|
||||
|
||||
span.freeIndexForScan = span.freeindex
|
||||
|
||||
c.nextSample -= int64(elemsize)
|
||||
if c.nextSample < 0 || MemProfileRate != c.memProfRate {
|
||||
profilealloc(mp, x, elemsize)
|
||||
}
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
if checkGCTrigger {
|
||||
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
|
||||
gcStart(t)
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func mallocgcSmallScanNoHeaderSC10(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
||||
if forceSlowPath {
|
||||
|
||||
const spc = spanClass(10<<1) | spanClass(0)
|
||||
const elemsize = uintptr(128)
|
||||
return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize)
|
||||
}
|
||||
|
||||
if doubleCheckMalloc {
|
||||
if gcphase == _GCmarktermination {
|
||||
throw("mallocgc called with gcphase == _GCmarktermination")
|
||||
}
|
||||
}
|
||||
|
||||
lockRankMayQueueFinalizer()
|
||||
|
||||
const sizeclass = 10
|
||||
const elemsize = 128
|
||||
|
||||
mp := acquirem()
|
||||
if doubleCheckMalloc {
|
||||
|
||||
doubleCheckSmallScanNoHeader(size, typ, mp)
|
||||
|
||||
}
|
||||
mp.mallocing = 1
|
||||
|
||||
checkGCTrigger := false
|
||||
c := getMCache(mp)
|
||||
const spc = spanClass(sizeclass<<1) | spanClass(0)
|
||||
span := c.alloc[spc]
|
||||
|
||||
var v gclinkptr
|
||||
var x unsafe.Pointer
|
||||
|
||||
{
|
||||
|
||||
var nextFreeFastResult gclinkptr
|
||||
if span.allocCache != 0 {
|
||||
theBit := sys.TrailingZeros64(span.allocCache)
|
||||
result := span.freeindex + uint16(theBit)
|
||||
if result < span.nelems {
|
||||
freeidx := result + 1
|
||||
if !(freeidx%64 == 0 && freeidx != span.nelems) {
|
||||
span.allocCache >>= uint(theBit + 1)
|
||||
span.freeindex = freeidx
|
||||
span.allocCount++
|
||||
nextFreeFastResult = gclinkptr(uintptr(result)*elemsize + span.base())
|
||||
}
|
||||
}
|
||||
}
|
||||
v = nextFreeFastResult
|
||||
if v == 0 {
|
||||
v, span, checkGCTrigger = c.nextFree(spc)
|
||||
}
|
||||
x = unsafe.Pointer(v)
|
||||
}
|
||||
|
||||
if span.needzero != 0 {
|
||||
memclrNoHeapPointers(x, elemsize)
|
||||
}
|
||||
if goarch.PtrSize == 8 && elemsize == 8 {
|
||||
|
||||
c.scanAlloc += 8
|
||||
} else {
|
||||
dataSize := size
|
||||
x := uintptr(x)
|
||||
|
||||
if doubleCheckHeapSetType && (!heapBitsInSpan(dataSize) || !heapBitsInSpan(128)) {
|
||||
throw("tried to write heap bits, but no heap bits in span")
|
||||
}
|
||||
|
||||
src0 := readUintptr(getGCMask(typ))
|
||||
|
||||
const elemsize = 128
|
||||
|
||||
var scanSize uintptr
|
||||
src := src0
|
||||
if typ.Size_ == goarch.PtrSize {
|
||||
src = (1 << (dataSize / goarch.PtrSize)) - 1
|
||||
|
||||
scanSize = dataSize
|
||||
} else {
|
||||
|
||||
if doubleCheckHeapSetType && !asanenabled && dataSize%typ.Size_ != 0 {
|
||||
throw("runtime: (*mspan).writeHeapBitsSmall: dataSize is not a multiple of typ.Size_")
|
||||
}
|
||||
scanSize = typ.PtrBytes
|
||||
for i := typ.Size_; i < dataSize; i += typ.Size_ {
|
||||
src |= src0 << (i / goarch.PtrSize)
|
||||
scanSize += typ.Size_
|
||||
}
|
||||
}
|
||||
|
||||
dstBase, _ := spanHeapBitsRange(span.base(), pageSize, elemsize)
|
||||
dst := unsafe.Pointer(dstBase)
|
||||
o := (x - span.base()) / goarch.PtrSize
|
||||
i := o / ptrBits
|
||||
j := o % ptrBits
|
||||
var bits uintptr = elemsize / goarch.PtrSize
|
||||
|
||||
var bitsIsPowerOfTwo = bits&(bits-1) == 0
|
||||
if bits > ptrBits || (!bitsIsPowerOfTwo && j+bits > ptrBits) {
|
||||
|
||||
bits0 := ptrBits - j
|
||||
bits1 := bits - bits0
|
||||
dst0 := (*uintptr)(add(dst, (i+0)*goarch.PtrSize))
|
||||
dst1 := (*uintptr)(add(dst, (i+1)*goarch.PtrSize))
|
||||
*dst0 = (*dst0)&(^uintptr(0)>>bits0) | (src << j)
|
||||
*dst1 = (*dst1)&^((1<<bits1)-1) | (src >> bits0)
|
||||
} else {
|
||||
|
||||
dst := (*uintptr)(add(dst, i*goarch.PtrSize))
|
||||
*dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)<<j) | (src << j)
|
||||
}
|
||||
|
||||
const doubleCheck = false
|
||||
if doubleCheck {
|
||||
writeHeapBitsDoubleCheck(span, x, dataSize, src, src0, i, j, bits, typ)
|
||||
}
|
||||
if doubleCheckHeapSetType {
|
||||
doubleCheckHeapType(x, dataSize, typ, nil, span)
|
||||
}
|
||||
c.scanAlloc += scanSize
|
||||
}
|
||||
|
||||
publicationBarrier()
|
||||
|
||||
span.freeIndexForScan = span.freeindex
|
||||
|
||||
c.nextSample -= int64(elemsize)
|
||||
if c.nextSample < 0 || MemProfileRate != c.memProfRate {
|
||||
profilealloc(mp, x, elemsize)
|
||||
}
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
if checkGCTrigger {
|
||||
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
|
||||
gcStart(t)
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func mallocgcTinySC2(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
|
@ -2171,288 +1724,6 @@ func mallocgcSmallNoScanSC7(size uintptr, typ *_type, needzero bool) unsafe.Poin
|
|||
return x
|
||||
}
|
||||
|
||||
func mallocgcSmallNoScanSC8(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
||||
if forceSlowPath {
|
||||
|
||||
const spc = spanClass(8<<1) | spanClass(1)
|
||||
const elemsize = uintptr(96)
|
||||
return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize)
|
||||
}
|
||||
|
||||
if doubleCheckMalloc {
|
||||
if gcphase == _GCmarktermination {
|
||||
throw("mallocgc called with gcphase == _GCmarktermination")
|
||||
}
|
||||
}
|
||||
|
||||
lockRankMayQueueFinalizer()
|
||||
|
||||
const sizeclass = 8
|
||||
const elemsize = 96
|
||||
|
||||
mp := acquirem()
|
||||
if doubleCheckMalloc {
|
||||
|
||||
doubleCheckSmallNoScan(typ, mp)
|
||||
|
||||
}
|
||||
mp.mallocing = 1
|
||||
|
||||
checkGCTrigger := false
|
||||
c := getMCache(mp)
|
||||
const spc = spanClass(sizeclass<<1) | spanClass(1)
|
||||
span := c.alloc[spc]
|
||||
|
||||
var v gclinkptr
|
||||
var x unsafe.Pointer
|
||||
|
||||
if runtimeFreegcEnabled && c.hasReusableNoscan(spc) {
|
||||
|
||||
x = mallocgcSmallNoscanReuse(c, span, spc, elemsize, needzero)
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
var nextFreeFastResult gclinkptr
|
||||
if span.allocCache != 0 {
|
||||
theBit := sys.TrailingZeros64(span.allocCache)
|
||||
result := span.freeindex + uint16(theBit)
|
||||
if result < span.nelems {
|
||||
freeidx := result + 1
|
||||
if !(freeidx%64 == 0 && freeidx != span.nelems) {
|
||||
span.allocCache >>= uint(theBit + 1)
|
||||
span.freeindex = freeidx
|
||||
span.allocCount++
|
||||
nextFreeFastResult = gclinkptr(uintptr(result)*elemsize + span.base())
|
||||
}
|
||||
}
|
||||
}
|
||||
v = nextFreeFastResult
|
||||
if v == 0 {
|
||||
v, span, checkGCTrigger = c.nextFree(spc)
|
||||
}
|
||||
x = unsafe.Pointer(v)
|
||||
}
|
||||
|
||||
if needzero && span.needzero != 0 {
|
||||
memclrNoHeapPointers(x, elemsize)
|
||||
}
|
||||
|
||||
publicationBarrier()
|
||||
|
||||
span.freeIndexForScan = span.freeindex
|
||||
|
||||
c.nextSample -= int64(elemsize)
|
||||
if c.nextSample < 0 || MemProfileRate != c.memProfRate {
|
||||
profilealloc(mp, x, elemsize)
|
||||
}
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
if checkGCTrigger {
|
||||
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
|
||||
gcStart(t)
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func mallocgcSmallNoScanSC9(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
||||
if forceSlowPath {
|
||||
|
||||
const spc = spanClass(9<<1) | spanClass(1)
|
||||
const elemsize = uintptr(112)
|
||||
return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize)
|
||||
}
|
||||
|
||||
if doubleCheckMalloc {
|
||||
if gcphase == _GCmarktermination {
|
||||
throw("mallocgc called with gcphase == _GCmarktermination")
|
||||
}
|
||||
}
|
||||
|
||||
lockRankMayQueueFinalizer()
|
||||
|
||||
const sizeclass = 9
|
||||
const elemsize = 112
|
||||
|
||||
mp := acquirem()
|
||||
if doubleCheckMalloc {
|
||||
|
||||
doubleCheckSmallNoScan(typ, mp)
|
||||
|
||||
}
|
||||
mp.mallocing = 1
|
||||
|
||||
checkGCTrigger := false
|
||||
c := getMCache(mp)
|
||||
const spc = spanClass(sizeclass<<1) | spanClass(1)
|
||||
span := c.alloc[spc]
|
||||
|
||||
var v gclinkptr
|
||||
var x unsafe.Pointer
|
||||
|
||||
if runtimeFreegcEnabled && c.hasReusableNoscan(spc) {
|
||||
|
||||
x = mallocgcSmallNoscanReuse(c, span, spc, elemsize, needzero)
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
var nextFreeFastResult gclinkptr
|
||||
if span.allocCache != 0 {
|
||||
theBit := sys.TrailingZeros64(span.allocCache)
|
||||
result := span.freeindex + uint16(theBit)
|
||||
if result < span.nelems {
|
||||
freeidx := result + 1
|
||||
if !(freeidx%64 == 0 && freeidx != span.nelems) {
|
||||
span.allocCache >>= uint(theBit + 1)
|
||||
span.freeindex = freeidx
|
||||
span.allocCount++
|
||||
nextFreeFastResult = gclinkptr(uintptr(result)*elemsize + span.base())
|
||||
}
|
||||
}
|
||||
}
|
||||
v = nextFreeFastResult
|
||||
if v == 0 {
|
||||
v, span, checkGCTrigger = c.nextFree(spc)
|
||||
}
|
||||
x = unsafe.Pointer(v)
|
||||
}
|
||||
|
||||
if needzero && span.needzero != 0 {
|
||||
memclrNoHeapPointers(x, elemsize)
|
||||
}
|
||||
|
||||
publicationBarrier()
|
||||
|
||||
span.freeIndexForScan = span.freeindex
|
||||
|
||||
c.nextSample -= int64(elemsize)
|
||||
if c.nextSample < 0 || MemProfileRate != c.memProfRate {
|
||||
profilealloc(mp, x, elemsize)
|
||||
}
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
if checkGCTrigger {
|
||||
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
|
||||
gcStart(t)
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func mallocgcSmallNoScanSC10(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0)
|
||||
|
||||
if forceSlowPath {
|
||||
|
||||
const spc = spanClass(10<<1) | spanClass(1)
|
||||
const elemsize = uintptr(128)
|
||||
return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize)
|
||||
}
|
||||
|
||||
if doubleCheckMalloc {
|
||||
if gcphase == _GCmarktermination {
|
||||
throw("mallocgc called with gcphase == _GCmarktermination")
|
||||
}
|
||||
}
|
||||
|
||||
lockRankMayQueueFinalizer()
|
||||
|
||||
const sizeclass = 10
|
||||
const elemsize = 128
|
||||
|
||||
mp := acquirem()
|
||||
if doubleCheckMalloc {
|
||||
|
||||
doubleCheckSmallNoScan(typ, mp)
|
||||
|
||||
}
|
||||
mp.mallocing = 1
|
||||
|
||||
checkGCTrigger := false
|
||||
c := getMCache(mp)
|
||||
const spc = spanClass(sizeclass<<1) | spanClass(1)
|
||||
span := c.alloc[spc]
|
||||
|
||||
var v gclinkptr
|
||||
var x unsafe.Pointer
|
||||
|
||||
if runtimeFreegcEnabled && c.hasReusableNoscan(spc) {
|
||||
|
||||
x = mallocgcSmallNoscanReuse(c, span, spc, elemsize, needzero)
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
var nextFreeFastResult gclinkptr
|
||||
if span.allocCache != 0 {
|
||||
theBit := sys.TrailingZeros64(span.allocCache)
|
||||
result := span.freeindex + uint16(theBit)
|
||||
if result < span.nelems {
|
||||
freeidx := result + 1
|
||||
if !(freeidx%64 == 0 && freeidx != span.nelems) {
|
||||
span.allocCache >>= uint(theBit + 1)
|
||||
span.freeindex = freeidx
|
||||
span.allocCount++
|
||||
nextFreeFastResult = gclinkptr(uintptr(result)*elemsize + span.base())
|
||||
}
|
||||
}
|
||||
}
|
||||
v = nextFreeFastResult
|
||||
if v == 0 {
|
||||
v, span, checkGCTrigger = c.nextFree(spc)
|
||||
}
|
||||
x = unsafe.Pointer(v)
|
||||
}
|
||||
|
||||
if needzero && span.needzero != 0 {
|
||||
memclrNoHeapPointers(x, elemsize)
|
||||
}
|
||||
|
||||
publicationBarrier()
|
||||
|
||||
span.freeIndexForScan = span.freeindex
|
||||
|
||||
c.nextSample -= int64(elemsize)
|
||||
if c.nextSample < 0 || MemProfileRate != c.memProfRate {
|
||||
profilealloc(mp, x, elemsize)
|
||||
}
|
||||
mp.mallocing = 0
|
||||
releasem(mp)
|
||||
|
||||
if checkGCTrigger {
|
||||
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
|
||||
gcStart(t)
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func mallocgcTinySlowPath(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||
|
||||
gp := getg()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ package runtime
|
|||
|
||||
import "unsafe"
|
||||
|
||||
var mallocScanTable = [129]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{mallocPanic,
|
||||
var mallocScanTable = [81]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{mallocPanic,
|
||||
mallocgcSmallScanNoHeaderSC1,
|
||||
mallocgcSmallScanNoHeaderSC1,
|
||||
mallocgcSmallScanNoHeaderSC1,
|
||||
|
|
@ -86,58 +86,9 @@ var mallocScanTable = [129]func(size uintptr, typ *_type, needzero bool) unsafe.
|
|||
mallocgcSmallScanNoHeaderSC7,
|
||||
mallocgcSmallScanNoHeaderSC7,
|
||||
mallocgcSmallScanNoHeaderSC7,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC8,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC9,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
mallocgcSmallScanNoHeaderSC10,
|
||||
}
|
||||
|
||||
var mallocNoScanTable = [129]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{
|
||||
mallocPanic,
|
||||
var mallocNoScanTable = [81]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{mallocPanic,
|
||||
mallocPanic,
|
||||
mallocPanic,
|
||||
mallocPanic,
|
||||
|
|
@ -218,52 +169,4 @@ var mallocNoScanTable = [129]func(size uintptr, typ *_type, needzero bool) unsaf
|
|||
mallocgcSmallNoScanSC7,
|
||||
mallocgcSmallNoScanSC7,
|
||||
mallocgcSmallNoScanSC7,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC8,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC9,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
mallocgcSmallNoScanSC10,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue