diff options
author | Colin Cross <ccross@android.com> | 2024-03-20 12:54:39 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2024-03-20 14:11:54 -0700 |
commit | fbe2133b4d3417adc93daa3819fccf52d2bb66ea (patch) | |
tree | 489499c233d3e979128afcc077ea1c6c01725ddf /src/runtime/trace2region.go | |
parent | 68a2d6d0813d288a1149f79a7223284fa2f5559f (diff) | |
parent | db6097f8cbaceaed02051850d2411c88b763a0c3 (diff) | |
download | go-fbe2133b4d3417adc93daa3819fccf52d2bb66ea.tar.gz |
Bug: 330574836
Test: builds
Change-Id: Icaf805d49ad96dd3f2960c5f92b4eeb7c131291c
Diffstat (limited to 'src/runtime/trace2region.go')
-rw-r--r-- | src/runtime/trace2region.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/runtime/trace2region.go b/src/runtime/trace2region.go new file mode 100644 index 0000000000..b514d127b5 --- /dev/null +++ b/src/runtime/trace2region.go @@ -0,0 +1,62 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.exectracer2 + +// Simple not-in-heap bump-pointer traceRegion allocator. + +package runtime + +import ( + "internal/goarch" + "runtime/internal/sys" + "unsafe" +) + +// traceRegionAlloc is a non-thread-safe region allocator. +// It holds a linked list of traceRegionAllocBlock. +type traceRegionAlloc struct { + head *traceRegionAllocBlock + off uintptr +} + +// traceRegionAllocBlock is a block in traceRegionAlloc. +// +// traceRegionAllocBlock is allocated from non-GC'd memory, so it must not +// contain heap pointers. Writes to pointers to traceRegionAllocBlocks do +// not need write barriers. +type traceRegionAllocBlock struct { + _ sys.NotInHeap + next *traceRegionAllocBlock + data [64<<10 - goarch.PtrSize]byte +} + +// alloc allocates n-byte block. +func (a *traceRegionAlloc) alloc(n uintptr) *notInHeap { + n = alignUp(n, goarch.PtrSize) + if a.head == nil || a.off+n > uintptr(len(a.head.data)) { + if n > uintptr(len(a.head.data)) { + throw("traceRegion: alloc too large") + } + block := (*traceRegionAllocBlock)(sysAlloc(unsafe.Sizeof(traceRegionAllocBlock{}), &memstats.other_sys)) + if block == nil { + throw("traceRegion: out of memory") + } + block.next = a.head + a.head = block + a.off = 0 + } + p := &a.head.data[a.off] + a.off += n + return (*notInHeap)(unsafe.Pointer(p)) +} + +// drop frees all previously allocated memory and resets the allocator. +func (a *traceRegionAlloc) drop() { + for a.head != nil { + block := a.head + a.head = block.next + sysFree(unsafe.Pointer(block), unsafe.Sizeof(traceRegionAllocBlock{}), &memstats.other_sys) + } +} |