// words to pointer/scan.
// Otherwise, it initializes all words to scalar/dead.
func (h heapBits) initSpan(s *mspan) {
- size, n, total := s.layout()
-
- // Init the markbit structures
- s.freeindex = 0
- s.allocCache = ^uint64(0) // all 1s indicating all free.
- s.nelems = n
- s.allocBits = nil
- s.gcmarkBits = nil
- s.gcmarkBits = newMarkBits(s.nelems)
- s.allocBits = newAllocBits(s.nelems)
-
// Clear bits corresponding to objects.
- nw := total / sys.PtrSize
+ nw := (s.npages << _PageShift) / sys.PtrSize
if nw%wordsPerBitmapByte != 0 {
throw("initSpan: unaligned length")
}
if h.shift != 0 {
throw("initSpan: unaligned base")
}
+ isPtrs := sys.PtrSize == 8 && s.elemsize == sys.PtrSize
for nw > 0 {
hNext, anw := h.forwardOrBoundary(nw)
nbyte := anw / wordsPerBitmapByte
- if sys.PtrSize == 8 && size == sys.PtrSize {
+ if isPtrs {
bitp := h.bitp
for i := uintptr(0); i < nbyte; i++ {
*bitp = bitPointerAll | bitScanAll
h.reclaim(npage)
}
+ // Compute size information.
+ nbytes := npage << _PageShift
+ var elemSize, nelems uintptr
+ if sizeclass := spanclass.sizeclass(); sizeclass == 0 {
+ elemSize = nbytes
+ nelems = 1
+ } else {
+ elemSize = uintptr(class_to_size[sizeclass])
+ nelems = nbytes / elemSize
+ }
+
+ // Allocate mark and allocation bits before we take the heap
+ // lock. We'll drop these on the floor if we fail to allocate
+ // the span, but in that case we'll panic soon.
+ gcmarkBits := newMarkBits(nelems)
+ allocBits := newAllocBits(nelems)
+
lock(&h.lock)
// transfer stats from cache to global
memstats.heap_scan += uint64(_g_.m.mcache.local_scan)
s.state = mSpanInUse
s.allocCount = 0
s.spanclass = spanclass
+ s.elemsize = elemSize
if sizeclass := spanclass.sizeclass(); sizeclass == 0 {
- s.elemsize = s.npages << _PageShift
s.divShift = 0
s.divMul = 0
s.divShift2 = 0
s.baseMask = 0
} else {
- s.elemsize = uintptr(class_to_size[sizeclass])
m := &class_to_divmagic[sizeclass]
s.divShift = m.shift
s.divMul = m.mul
s.baseMask = m.baseMask
}
+ // Initialize mark and allocation structures.
+ s.freeindex = 0
+ s.allocCache = ^uint64(0) // all 1s indicating all free.
+ s.nelems = nelems
+ s.gcmarkBits = gcmarkBits
+ s.allocBits = allocBits
+
// Mark in-use span in arena page bitmap.
arena, pageIdx, pageMask := pageIndexOf(s.base())
arena.pageInUse[pageIdx] |= pageMask