Skip to content

Commit c186004

Browse files
committed
runtime: record in-use spans in a page-indexed bitmap
This adds a bitmap indexed by page number that marks the starts of in-use spans. This will be used to quickly find in-use spans with no marked objects for sweeping. For #18155. Change-Id: Icee56f029cde502447193e136fa54a74c74326dd Reviewed-on: https://go-review.googlesource.com/c/138957 Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rick Hudson <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent cd3b878 commit c186004

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/runtime/mheap.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ type heapArena struct {
193193
// must not be a safe-point between establishing that an
194194
// address is live and looking it up in the spans array.
195195
spans [pagesPerArena]*mspan
196+
197+
// pageInUse is a bitmap that indicates which spans are in
198+
// state mSpanInUse. This bitmap is indexed by page number,
199+
// but only the bit corresponding to the first page in each
200+
// span is used.
201+
//
202+
// Writes are protected by mheap_.lock.
203+
pageInUse [pagesPerArena / 8]uint8
196204
}
197205

198206
// arenaHint is a hint for where to grow the heap arenas. See
@@ -600,6 +608,16 @@ func spanOfHeap(p uintptr) *mspan {
600608
return s
601609
}
602610

611+
// pageIndexOf returns the arena, page index, and page mask for pointer p.
612+
// The caller must ensure p is in the heap.
613+
func pageIndexOf(p uintptr) (arena *heapArena, pageIdx uintptr, pageMask uint8) {
614+
ai := arenaIndex(p)
615+
arena = mheap_.arenas[ai.l1()][ai.l2()]
616+
pageIdx = ((p / pageSize) / 8) % uintptr(len(arena.pageInUse))
617+
pageMask = byte(1 << ((p / pageSize) % 8))
618+
return
619+
}
620+
603621
// Initialize the heap.
604622
func (h *mheap) init() {
605623
h.treapalloc.init(unsafe.Sizeof(treapNode{}), nil, nil, &memstats.other_sys)
@@ -741,6 +759,10 @@ func (h *mheap) alloc_m(npage uintptr, spanclass spanClass, large bool) *mspan {
741759
s.baseMask = m.baseMask
742760
}
743761

762+
// Mark in-use span in arena page bitmap.
763+
arena, pageIdx, pageMask := pageIndexOf(s.base())
764+
arena.pageInUse[pageIdx] |= pageMask
765+
744766
// update stats, sweep lists
745767
h.pagesInUse += uint64(npage)
746768
if large {
@@ -1039,6 +1061,10 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
10391061
throw("mheap.freeSpanLocked - invalid free")
10401062
}
10411063
h.pagesInUse -= uint64(s.npages)
1064+
1065+
// Clear in-use bit in arena page bitmap.
1066+
arena, pageIdx, pageMask := pageIndexOf(s.base())
1067+
arena.pageInUse[pageIdx] &^= pageMask
10421068
default:
10431069
throw("mheap.freeSpanLocked - invalid span state")
10441070
}

0 commit comments

Comments
 (0)