Source file src/runtime/trace2region.go

     1  // Copyright 2023 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  //go:build goexperiment.exectracer2
     6  
     7  // Simple not-in-heap bump-pointer traceRegion allocator.
     8  
     9  package runtime
    10  
    11  import (
    12  	"internal/goarch"
    13  	"runtime/internal/sys"
    14  	"unsafe"
    15  )
    16  
    17  // traceRegionAlloc is a non-thread-safe region allocator.
    18  // It holds a linked list of traceRegionAllocBlock.
    19  type traceRegionAlloc struct {
    20  	head *traceRegionAllocBlock
    21  	off  uintptr
    22  }
    23  
    24  // traceRegionAllocBlock is a block in traceRegionAlloc.
    25  //
    26  // traceRegionAllocBlock is allocated from non-GC'd memory, so it must not
    27  // contain heap pointers. Writes to pointers to traceRegionAllocBlocks do
    28  // not need write barriers.
    29  type traceRegionAllocBlock struct {
    30  	_    sys.NotInHeap
    31  	next *traceRegionAllocBlock
    32  	data [64<<10 - goarch.PtrSize]byte
    33  }
    34  
    35  // alloc allocates n-byte block.
    36  func (a *traceRegionAlloc) alloc(n uintptr) *notInHeap {
    37  	n = alignUp(n, goarch.PtrSize)
    38  	if a.head == nil || a.off+n > uintptr(len(a.head.data)) {
    39  		if n > uintptr(len(a.head.data)) {
    40  			throw("traceRegion: alloc too large")
    41  		}
    42  		block := (*traceRegionAllocBlock)(sysAlloc(unsafe.Sizeof(traceRegionAllocBlock{}), &memstats.other_sys))
    43  		if block == nil {
    44  			throw("traceRegion: out of memory")
    45  		}
    46  		block.next = a.head
    47  		a.head = block
    48  		a.off = 0
    49  	}
    50  	p := &a.head.data[a.off]
    51  	a.off += n
    52  	return (*notInHeap)(unsafe.Pointer(p))
    53  }
    54  
    55  // drop frees all previously allocated memory and resets the allocator.
    56  func (a *traceRegionAlloc) drop() {
    57  	for a.head != nil {
    58  		block := a.head
    59  		a.head = block.next
    60  		sysFree(unsafe.Pointer(block), unsafe.Sizeof(traceRegionAllocBlock{}), &memstats.other_sys)
    61  	}
    62  }
    63  

View as plain text