// weight allocation. If it is a heavy weight allocation the caller must
// determine whether a new GC cycle needs to be started or if the GC is active
// whether this goroutine needs to assist the GC.
-func (c *mcache) nextFree(sizeclass int8) (v gclinkptr, s *mspan, shouldhelpgc bool) {
+func (c *mcache) nextFree(sizeclass uint8) (v gclinkptr, s *mspan, shouldhelpgc bool) {
s = c.alloc[sizeclass]
shouldhelpgc = false
freeIndex := s.nextFreeIndex()
}
size = maxTinySize
} else {
- var sizeclass int8
- if size <= 1024-8 {
- sizeclass = size_to_class8[(size+7)>>3]
+ var sizeclass uint8
+ if size <= smallSizeMax-8 {
+ sizeclass = size_to_class8[(size+smallSizeDiv-1)/smallSizeDiv]
} else {
- sizeclass = size_to_class128[(size-1024+127)>>7]
+ sizeclass = size_to_class128[(size-smallSizeMax+largeSizeDiv-1)/largeSizeDiv]
}
size = uintptr(class_to_size[sizeclass])
span := c.alloc[sizeclass]
// size divided by 128 (rounded up). The arrays are filled in
// by InitSizes.
-var class_to_size [_NumSizeClasses]int32
-var class_to_allocnpages [_NumSizeClasses]int32
+const (
+ smallSizeDiv = 8
+ smallSizeMax = 1024
+ largeSizeDiv = 128
+)
+
+var class_to_size [_NumSizeClasses]uint32
+var class_to_allocnpages [_NumSizeClasses]uint32
var class_to_divmagic [_NumSizeClasses]divMagic
-var size_to_class8 [1024/8 + 1]int8
-var size_to_class128 [(_MaxSmallSize-1024)/128 + 1]int8
+var size_to_class8 [smallSizeMax/smallSizeDiv + 1]uint8
+var size_to_class128 [(_MaxSmallSize-smallSizeMax)/largeSizeDiv + 1]uint8
-func sizeToClass(size int32) int32 {
+func sizeToClass(size uint32) uint32 {
if size > _MaxSmallSize {
throw("invalid size")
}
- if size > 1024-8 {
- return int32(size_to_class128[(size-1024+127)>>7])
+ if size > smallSizeMax-8 {
+ return uint32(size_to_class128[(size-smallSizeMax+largeSizeDiv-1)/largeSizeDiv])
}
- return int32(size_to_class8[(size+7)>>3])
+ return uint32(size_to_class8[(size+smallSizeDiv-1)/smallSizeDiv])
}
func initSizes() {
// use just this size instead of having two
// different sizes.
if sizeclass > 1 && npages == int(class_to_allocnpages[sizeclass-1]) && allocsize/size == allocsize/int(class_to_size[sizeclass-1]) {
- class_to_size[sizeclass-1] = int32(size)
+ class_to_size[sizeclass-1] = uint32(size)
continue
}
- class_to_allocnpages[sizeclass] = int32(npages)
- class_to_size[sizeclass] = int32(size)
+ class_to_allocnpages[sizeclass] = uint32(npages)
+ class_to_size[sizeclass] = uint32(size)
sizeclass++
}
if sizeclass != _NumSizeClasses {
print("runtime: sizeclass=", sizeclass, " NumSizeClasses=", _NumSizeClasses, "\n")
throw("bad NumSizeClasses")
}
+
+ // Increase object sizes if we can fit the same number of larger objects
+ // into the same number of pages. For example, we choose size 8448 above
+ // with 6 objects in 7 pages. But we can well use object size 9472,
+ // which is also 6 objects in 7 pages but +1024 bytes (+12.12%).
+ // We need to preserve at least largeSizeDiv alignment otherwise
+ // sizeToClass won't work.
+ for i := 1; i < _NumSizeClasses; i++ {
+ npages := class_to_allocnpages[i]
+ psize := npages * _PageSize
+ size := class_to_size[i]
+ new_size := (psize / (psize / size)) &^ (largeSizeDiv - 1)
+ if new_size > size {
+ class_to_size[i] = new_size
+ }
+ }
+
// Check maxObjsPerSpan => number of objects invariant.
for i, size := range class_to_size {
+ if i != 0 && class_to_size[i-1] >= size {
+ throw("non-monotonic size classes")
+ }
+
if size != 0 && class_to_allocnpages[i]*pageSize/size > maxObjsPerSpan {
throw("span contains too many objects")
}
nextsize := 0
for sizeclass = 1; sizeclass < _NumSizeClasses; sizeclass++ {
for ; nextsize < 1024 && nextsize <= int(class_to_size[sizeclass]); nextsize += 8 {
- size_to_class8[nextsize/8] = int8(sizeclass)
+ size_to_class8[nextsize/8] = uint8(sizeclass)
}
if nextsize >= 1024 {
for ; nextsize <= int(class_to_size[sizeclass]); nextsize += 128 {
- size_to_class128[(nextsize-1024)/128] = int8(sizeclass)
+ size_to_class128[(nextsize-1024)/128] = uint8(sizeclass)
}
}
}
// Double-check SizeToClass.
if false {
- for n := int32(0); n < _MaxSmallSize; n++ {
+ for n := uint32(0); n < _MaxSmallSize; n++ {
sizeclass := sizeToClass(n)
if sizeclass < 1 || sizeclass >= _NumSizeClasses || class_to_size[sizeclass] < n {
print("runtime: size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
// Returns size of the memory block that mallocgc will allocate if you ask for the size.
func roundupsize(size uintptr) uintptr {
if size < _MaxSmallSize {
- if size <= 1024-8 {
- return uintptr(class_to_size[size_to_class8[(size+7)>>3]])
+ if size <= smallSizeMax-8 {
+ return uintptr(class_to_size[size_to_class8[(size+smallSizeDiv-1)/smallSizeDiv]])
} else {
- return uintptr(class_to_size[size_to_class128[(size-1024+127)>>7]])
+ return uintptr(class_to_size[size_to_class128[(size-smallSizeMax+largeSizeDiv-1)/largeSizeDiv]])
}
}
if size+_PageSize < size {