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  

View as plain text