Source file src/internal/runtime/gc/scan/scan_reference.go
1 // Copyright 2025 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package scan 6 7 import ( 8 "internal/goarch" 9 "internal/runtime/gc" 10 "unsafe" 11 ) 12 13 // ScanSpanPackedReference is the reference implementation of ScanScanPacked. It prioritizes clarity over performance. 14 // 15 // Concretely, ScanScanPacked functions read pointers from mem, assumed to be gc.PageSize-aligned and gc.PageSize in size, 16 // and writes them to bufp, which is large enough to guarantee that even if pointer-word of mem is a pointer, it will fit. 17 // Therefore bufp, is always at least gc.PageSize in size. 18 // 19 // ScanSpanPacked is supposed to identify pointers by first filtering words by objMarks, where each bit of the mask 20 // represents gc.SizeClassToSize[sizeClass] bytes of memory, and then filtering again by the bits in ptrMask. 21 func ScanSpanPackedReference(mem unsafe.Pointer, bufp *uintptr, objMarks *gc.ObjMask, sizeClass uintptr, ptrMask *gc.PtrMask) (count int32) { 22 buf := unsafe.Slice(bufp, gc.PageWords) 23 expandBy := uintptr(gc.SizeClassToSize[sizeClass]) / goarch.PtrSize 24 for word := range gc.PageWords { 25 objI := uintptr(word) / expandBy 26 if objMarks[objI/goarch.PtrBits]&(1<<(objI%goarch.PtrBits)) == 0 { 27 continue 28 } 29 if ptrMask[word/goarch.PtrBits]&(1<<(word%goarch.PtrBits)) == 0 { 30 continue 31 } 32 ptr := *(*uintptr)(unsafe.Add(mem, word*goarch.PtrSize)) 33 if ptr == 0 { 34 continue 35 } 36 buf[count] = ptr 37 count++ 38 } 39 return count 40 } 41