// Code generated by mkmalloc.go; DO NOT EDIT. // See overview in malloc_stubs.go. package runtime import ( "internal/goarch" "internal/goexperiment" "internal/runtime/sys" "unsafe" ) func mallocgcSmallScanNoHeaderSC1(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(1<<1) | spanClass(0) const elemsize = uintptr(8) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 1 const elemsize = 8 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(8)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 8 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) const spc = spanClass(2<<1) | spanClass(0) const elemsize = uintptr(16) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 2 const elemsize = 16 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(16)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 16 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) const spc = spanClass(3<<1) | spanClass(0) const elemsize = uintptr(24) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 3 const elemsize = 24 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(24)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 24 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) const spc = spanClass(4<<1) | spanClass(0) const elemsize = uintptr(32) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 4 const elemsize = 32 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(32)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 32 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) const spc = spanClass(5<<1) | spanClass(0) const elemsize = uintptr(48) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 5 const elemsize = 48 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(48)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 48 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) const spc = spanClass(6<<1) | spanClass(0) const elemsize = uintptr(64) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 6 const elemsize = 64 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(64)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 64 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) const spc = spanClass(7<<1) | spanClass(0) const elemsize = uintptr(80) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 7 const elemsize = 80 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(80)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) const elemsize = 80 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0) if forceSlowPath { releasem(mp) return mallocgcTinySlowPath(size, typ, needzero) } lockRankMayQueueFinalizer() const elemsize = 16 if doubleCheckMalloc { doubleCheckTiny(size, typ, mp) } mp.mallocing = 1 c := getMCache(mp) off := c.tinyoffset if size&7 == 0 { off = alignUp(off, 8) } else if goarch.PtrSize == 4 && size == 12 { off = alignUp(off, 8) } else if size&3 == 0 { off = alignUp(off, 4) } else if size&1 == 0 { off = alignUp(off, 2) } if off+size <= maxTinySize && c.tiny != 0 { x := unsafe.Pointer(c.tiny + off) c.tinyoffset = off + size c.tinyAllocs++ mp.mallocing = 0 releasem(mp) const elemsize = 0 return x } checkGCTrigger := false span := c.alloc[tinySpanClass] const nbytes = 8192 const nelems = uint16((nbytes - unsafe.Sizeof(spanInlineMarkBits{})) / 16) var nextFreeFastResult gclinkptr if span.allocCache != 0 { theBit := sys.TrailingZeros64(span.allocCache) result := span.freeindex + uint16(theBit) if result < nelems { freeidx := result + 1 if !(freeidx%64 == 0 && freeidx != nelems) { span.allocCache >>= uint(theBit + 1) span.freeindex = freeidx span.allocCount++ nextFreeFastResult = gclinkptr(uintptr(result)*16 + span.base()) } } } v := nextFreeFastResult if v == 0 { v, span, checkGCTrigger = c.nextFree(tinySpanClass) } x := unsafe.Pointer(v) (*[2]uint64)(x)[0] = 0 (*[2]uint64)(x)[1] = 0 if !raceenabled && (size < c.tinyoffset || c.tiny == 0) { c.tiny = uintptr(x) c.tinyoffset = size } 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 mallocgcSmallNoScanSC2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(2<<1) | spanClass(1) const elemsize = uintptr(16) return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 2 const elemsize = 16 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 mallocgcSmallNoScanSC3(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(3<<1) | spanClass(1) const elemsize = uintptr(24) return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 3 const elemsize = 24 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 mallocgcSmallNoScanSC4(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(4<<1) | spanClass(1) const elemsize = uintptr(32) return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 4 const elemsize = 32 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 mallocgcSmallNoScanSC5(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(5<<1) | spanClass(1) const elemsize = uintptr(48) return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 5 const elemsize = 48 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 mallocgcSmallNoScanSC6(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(6<<1) | spanClass(1) const elemsize = uintptr(64) return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 6 const elemsize = 64 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 mallocgcSmallNoScanSC7(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { releasem(mp) const spc = spanClass(7<<1) | spanClass(1) const elemsize = uintptr(80) return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } lockRankMayQueueFinalizer() const sizeclass = 7 const elemsize = 80 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 { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { return mallocgcSmallNoScanSC2(size, typ, needzero) } lockRankMayQueueFinalizer() if debug.malloc { if x := preMallocgcDebug(size, typ); x != nil { return x } } if gcBlackenEnabled != 0 { assistG := getg() if assistG.m.curg != nil { assistG = assistG.m.curg } assistG.gcAssistBytes -= int64(size) if assistG.gcAssistBytes < 0 { gcAssistAlloc(assistG) } } mp = acquirem() const elemsize = 16 if doubleCheckMalloc { doubleCheckTiny(size, typ, mp) } mp.mallocing = 1 c := getMCache(mp) off := c.tinyoffset if size&7 == 0 { off = alignUp(off, 8) } else if goarch.PtrSize == 4 && size == 12 { off = alignUp(off, 8) } else if size&3 == 0 { off = alignUp(off, 4) } else if size&1 == 0 { off = alignUp(off, 2) } if off+size <= maxTinySize && c.tiny != 0 { x := unsafe.Pointer(c.tiny + off) c.tinyoffset = off + size c.tinyAllocs++ mp.mallocing = 0 releasem(mp) const elemsize = 0 if gcBlackenEnabled != 0 && elemsize != 0 { if assistG := getg().m.curg; assistG != nil { assistG.gcAssistBytes -= int64(elemsize - size) } } if debug.malloc { postMallocgcDebug(x, elemsize, typ) } return x } checkGCTrigger := false span := c.alloc[tinySpanClass] const nbytes = 8192 const nelems = uint16((nbytes - unsafe.Sizeof(spanInlineMarkBits{})) / 16) var nextFreeFastResult gclinkptr if span.allocCache != 0 { theBit := sys.TrailingZeros64(span.allocCache) result := span.freeindex + uint16(theBit) if result < nelems { freeidx := result + 1 if !(freeidx%64 == 0 && freeidx != nelems) { span.allocCache >>= uint(theBit + 1) span.freeindex = freeidx span.allocCount++ nextFreeFastResult = gclinkptr(uintptr(result)*16 + span.base()) } } } v := nextFreeFastResult if v == 0 { v, span, checkGCTrigger = c.nextFree(tinySpanClass) } x := unsafe.Pointer(v) (*[2]uint64)(x)[0] = 0 (*[2]uint64)(x)[1] = 0 if !raceenabled && (size < c.tinyoffset || c.tiny == 0) { c.tiny = uintptr(x) c.tinyoffset = size } publicationBarrier() if writeBarrier.enabled { gcmarknewobject(span, uintptr(x)) } else { 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) } } if gcBlackenEnabled != 0 && elemsize != 0 { if assistG := getg().m.curg; assistG != nil { assistG.gcAssistBytes -= int64(elemsize - size) } } if debug.malloc { postMallocgcDebug(x, elemsize, typ) } return x } func mallocgcSmallScanSlowPath(size uintptr, typ *_type, needzero bool, spc spanClass, elemsize uintptr) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m lockRankMayQueueFinalizer() if debug.malloc { if x := preMallocgcDebug(size, typ); x != nil { return x } } if gcBlackenEnabled != 0 { assistG := getg() if assistG.m.curg != nil { assistG = assistG.m.curg } assistG.gcAssistBytes -= int64(size) if assistG.gcAssistBytes < 0 { gcAssistAlloc(assistG) } } mp = acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) } mp.mallocing = 1 checkGCTrigger := false c := getMCache(mp) 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(elemsize_)) { throw("tried to write heap bits, but no heap bits in span") } src0 := readUintptr(getGCMask(typ)) 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<> bits0) } else { dst := (*uintptr)(add(dst, i*goarch.PtrSize)) *dst = (*dst)&^(((1<<(min(bits, ptrBits)))-1)< 0 { addSecret(x, size) } if gcBlackenEnabled != 0 && elemsize != 0 { if assistG := getg().m.curg; assistG != nil { assistG.gcAssistBytes -= int64(elemsize - size) } } if debug.malloc { postMallocgcDebug(x, elemsize, typ) } return x } func mallocgcSmallNoScanSlowPath(size uintptr, typ *_type, needzero bool, spc spanClass, elemsize uintptr) unsafe.Pointer { if doubleCheckMalloc { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } var mp *m lockRankMayQueueFinalizer() if debug.malloc { if x := preMallocgcDebug(size, typ); x != nil { return x } } if gcBlackenEnabled != 0 { assistG := getg() if assistG.m.curg != nil { assistG = assistG.m.curg } assistG.gcAssistBytes -= int64(size) if assistG.gcAssistBytes < 0 { gcAssistAlloc(assistG) } } mp = acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) } mp.mallocing = 1 checkGCTrigger := false c := getMCache(mp) 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) goto post } { 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() if writeBarrier.enabled { gcmarknewobject(span, uintptr(x)) } else { 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) } } post: gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { addSecret(x, size) } if gcBlackenEnabled != 0 && elemsize != 0 { if assistG := getg().m.curg; assistG != nil { assistG.gcAssistBytes -= int64(elemsize - size) } } if debug.malloc { postMallocgcDebug(x, elemsize, typ) } return x }