prev **mspan // previous span's next field, or list head's first field if none
list *mSpanList // For debugging. TODO: Remove.
- start pageID // starting page number
- npages uintptr // number of pages in span
- freelist gclinkptr // list of free objects
+ start pageID // starting page number
+ npages uintptr // number of pages in span
+ freelist gclinkptr // list of free objects for _MSpanInUse
+ stackfreelist gclinkptr // list of free stacks, avoids overloading freelist for _MSpanStack
+
+ // freeindex is the slot index between 0 and nelems at which to begin scanning
+ // for the next free object in this span.
+ // Each allocation scans allocBits starting at freeindex until it encounters a 0
+ // indicating a free object. freeindex is then adjusted so that subsequent scans begin
+ // just past the the newly discovered free object.
+ //
+ // If freeindex == nelem, this span has no free objects.
+ //
+ // allocBits is a bitmap of objects in this span.
+ // If n >= freeindex and allocBits[n/8] & (1<<(n%8)) is 0
+ // then object n is free;
+ // otherwise, object n is allocated. Bits starting at nelem are
+ // undefined and should never be referenced.
+ //
+ // Object n starts at address n*elemsize + (start << pageShift).
+ freeindex uintptr
+ allocBits *[maxObjsPerSpan / 8]uint8
+ gcmarkBits *[maxObjsPerSpan / 8]uint8
+ nelems uintptr // number of object in the span.
+ // TODO(rlh) consider moving some of these fields into seperate arrays.
+ // Put another way is an array of structs a better idea than a struct of arrays.
+
+ // allocBits and gcmarkBits currently point to either markbits1
+ // or markbits2. At the end of a GC cycle allocBits and
+ // gcmarkBits swap roles simply by swapping pointers.
+ // This level of indirection also facilitates an implementation
+ // where markbits1 and markbits2 are not inlined in mspan.
+ markbits1 [maxObjsPerSpan / 8]uint8 // A bit for each obj.
+ markbits2 [maxObjsPerSpan / 8]uint8 // A bit for each obj.
+
// sweep generation:
// if sweepgen == h->sweepgen - 2, the span needs sweeping
// if sweepgen == h->sweepgen - 1, the span is currently being swept
func sizeToClass(size int32) int32 {
if size > _MaxSmallSize {
- throw("SizeToClass - invalid size")
+ throw("invalid size")
}
if size > 1024-8 {
return int32(size_to_class128[(size-1024+127)>>7])
}
}
if align&(align-1) != 0 {
- throw("InitSizes - bug")
+ throw("incorrect alignment")
}
// Make the allocnpages big enough that
sizeclass++
}
if sizeclass != _NumSizeClasses {
- print("sizeclass=", sizeclass, " NumSizeClasses=", _NumSizeClasses, "\n")
- throw("InitSizes - bad NumSizeClasses")
+ print("runtime: sizeclass=", sizeclass, " NumSizeClasses=", _NumSizeClasses, "\n")
+ throw("bad NumSizeClasses")
+ }
+ // Check maxObjsPerSpan => number of objects invariant.
+ for i, size := range class_to_size {
+ if size != 0 && class_to_allocnpages[i]*pageSize/size > maxObjsPerSpan {
+ throw("span contains too many objects")
+ }
+ if size == 0 && i != 0 {
+ throw("size is 0 but class is not 0")
+ }
}
-
// Initialize the size_to_class tables.
nextsize := 0
for sizeclass = 1; sizeclass < _NumSizeClasses; sizeclass++ {
for n := int32(0); n < _MaxSmallSize; n++ {
sizeclass := sizeToClass(n)
if sizeclass < 1 || sizeclass >= _NumSizeClasses || class_to_size[sizeclass] < n {
- print("size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
+ print("runtime: size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
print("incorrect SizeToClass\n")
goto dump
}
if sizeclass > 1 && class_to_size[sizeclass-1] >= n {
- print("size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
+ print("runtime: size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
print("SizeToClass too big\n")
goto dump
}
dump:
if true {
- print("NumSizeClasses=", _NumSizeClasses, "\n")
+ print("runtime: NumSizeClasses=", _NumSizeClasses, "\n")
print("runtime·class_to_size:")
for sizeclass = 0; sizeclass < _NumSizeClasses; sizeclass++ {
print(" ", class_to_size[sizeclass], "")
}
print("\n\n")
- print("size_to_class8:")
+ print("runtime: size_to_class8:")
for i := 0; i < len(size_to_class8); i++ {
print(" ", i*8, "=>", size_to_class8[i], "(", class_to_size[size_to_class8[i]], ")\n")
}
print("\n")
- print("size_to_class128:")
+ print("runtime: size_to_class128:")
for i := 0; i < len(size_to_class128); i++ {
print(" ", i*128, "=>", size_to_class128[i], "(", class_to_size[size_to_class128[i]], ")\n")
}