From: Rick Hudson Date: Thu, 4 Feb 2016 16:41:48 +0000 (-0500) Subject: [dev.garbage] runtime: bitmap allocation data structs X-Git-Tag: go1.7beta1~405^2~22 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2ac8bdc52ae1ea0418df465de3f1ef36f49e2274;p=gostls13.git [dev.garbage] runtime: bitmap allocation data structs The bitmap allocation data structure prototypes. Before this is released these underlying data structures need to be more performant but the signatures of helper functions utilizing these structures will remain stable. Change-Id: I5ace12f2fb512a7038a52bbde2bfb7e98783bcbe Reviewed-on: https://go-review.googlesource.com/19221 Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot --- diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 5f1e2f64c0..fe13b8b9a3 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -97,6 +97,9 @@ const ( pageShift = _PageShift pageSize = _PageSize pageMask = _PageMask + // By construction, single page spans of the smallest object class + // have the most objects per span. + maxObjsPerSpan = pageSize / 8 mSpanInUse = _MSpanInUse diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 895af9f07c..8c843be946 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -117,9 +117,41 @@ type mspan struct { 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 diff --git a/src/runtime/msize.go b/src/runtime/msize.go index 21fe2f4c61..18577b309b 100644 --- a/src/runtime/msize.go +++ b/src/runtime/msize.go @@ -55,7 +55,7 @@ var size_to_class128 [(_MaxSmallSize-1024)/128 + 1]int8 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]) @@ -79,7 +79,7 @@ func initSizes() { } } if align&(align-1) != 0 { - throw("InitSizes - bug") + throw("incorrect alignment") } // Make the allocnpages big enough that @@ -106,10 +106,18 @@ func initSizes() { 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++ { @@ -128,12 +136,12 @@ func initSizes() { 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 } @@ -155,18 +163,18 @@ func initSizes() { 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") }