summaryrefslogtreecommitdiffstats
path: root/src/runtime/trace2region.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/runtime/trace2region.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/runtime/trace2region.go b/src/runtime/trace2region.go
new file mode 100644
index 0000000..b514d12
--- /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)
+ }
+}