internal/gclayout: make gclayout values constants

The previous versions calculated at init() prevented `interp` from running
in many cases, increasing compile times due to the increased need to revert
the partially interpreted results and also increasing binary runtime because
fewer optimizations had happened during interp.
This commit is contained in:
Damian Gryski
2025-07-08 15:20:49 -07:00
committed by Ron Evans
parent 3bb092d4d4
commit 8c5886060f
5 changed files with 25 additions and 34 deletions
+15 -24
View File
@@ -5,29 +5,20 @@ import "unsafe"
// Internal constants for gc layout // Internal constants for gc layout
// See runtime/gc_precise.go // See runtime/gc_precise.go
var ( type Layout uintptr
NoPtrs unsafe.Pointer
Pointer unsafe.Pointer const (
String unsafe.Pointer // 16-bit int => bits = 4
Slice unsafe.Pointer // 32-bit int => bits = 5
// 64-bit int => bits = 6
sizeBits = 4 + unsafe.Sizeof(uintptr(0))/4
sizeShift = sizeBits + 1
NoPtrs = Layout(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
Pointer = Layout(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
String = Layout(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
Slice = Layout(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
) )
func init() { func (l Layout) AsPtr() unsafe.Pointer { return unsafe.Pointer(l) }
var sizeBits uintptr
switch unsafe.Sizeof(uintptr(0)) {
case 8:
sizeBits = 6
case 4:
sizeBits = 5
case 2:
sizeBits = 4
}
var sizeShift = sizeBits + 1
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
}
+4 -4
View File
@@ -708,16 +708,16 @@ func (r *RawType) gcLayout() unsafe.Pointer {
kind := r.Kind() kind := r.Kind()
if kind < String { if kind < String {
return gclayout.NoPtrs return gclayout.NoPtrs.AsPtr()
} }
switch kind { switch kind {
case Pointer, UnsafePointer, Chan, Map: case Pointer, UnsafePointer, Chan, Map:
return gclayout.Pointer return gclayout.Pointer.AsPtr()
case String: case String:
return gclayout.String return gclayout.String.AsPtr()
case Slice: case Slice:
return gclayout.Slice return gclayout.Slice.AsPtr()
} }
// Unknown (for now); let the conservative pointer scanning handle it // Unknown (for now); let the conservative pointer scanning handle it
+1 -1
View File
@@ -89,7 +89,7 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
gcLock.Lock() gcLock.Lock()
needsResumeWorld = false needsResumeWorld = false
var ptr unsafe.Pointer var ptr unsafe.Pointer
if layout == gclayout.NoPtrs { if layout == gclayout.NoPtrs.AsPtr() {
// This object is entirely pointer free, for example make([]int, ...). // This object is entirely pointer free, for example make([]int, ...).
// Make sure the GC knows this so it doesn't scan the object // Make sure the GC knows this so it doesn't scan the object
// unnecessarily to improve performance. // unnecessarily to improve performance.
+1 -1
View File
@@ -51,7 +51,7 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr)
var layout unsafe.Pointer var layout unsafe.Pointer
// less type info here; can only go off element size // less type info here; can only go off element size
if elemSize < unsafe.Sizeof(uintptr(0)) { if elemSize < unsafe.Sizeof(uintptr(0)) {
layout = gclayout.NoPtrs layout = gclayout.NoPtrs.AsPtr()
} }
buf := alloc(newCap*elemSize, layout) buf := alloc(newCap*elemSize, layout)
+4 -4
View File
@@ -60,7 +60,7 @@ func stringConcat(x, y _string) _string {
return x return x
} else { } else {
length := x.length + y.length length := x.length + y.length
buf := alloc(length, gclayout.NoPtrs) buf := alloc(length, gclayout.NoPtrs.AsPtr())
memcpy(buf, unsafe.Pointer(x.ptr), x.length) memcpy(buf, unsafe.Pointer(x.ptr), x.length)
memcpy(unsafe.Add(buf, x.length), unsafe.Pointer(y.ptr), y.length) memcpy(unsafe.Add(buf, x.length), unsafe.Pointer(y.ptr), y.length)
return _string{ptr: (*byte)(buf), length: length} return _string{ptr: (*byte)(buf), length: length}
@@ -73,7 +73,7 @@ func stringFromBytes(x struct {
len uintptr len uintptr
cap uintptr cap uintptr
}) _string { }) _string {
buf := alloc(x.len, gclayout.NoPtrs) buf := alloc(x.len, gclayout.NoPtrs.AsPtr())
memcpy(buf, unsafe.Pointer(x.ptr), x.len) memcpy(buf, unsafe.Pointer(x.ptr), x.len)
return _string{ptr: (*byte)(buf), length: x.len} return _string{ptr: (*byte)(buf), length: x.len}
} }
@@ -84,7 +84,7 @@ func stringToBytes(x _string) (slice struct {
len uintptr len uintptr
cap uintptr cap uintptr
}) { }) {
buf := alloc(x.length, gclayout.NoPtrs) buf := alloc(x.length, gclayout.NoPtrs.AsPtr())
memcpy(buf, unsafe.Pointer(x.ptr), x.length) memcpy(buf, unsafe.Pointer(x.ptr), x.length)
slice.ptr = (*byte)(buf) slice.ptr = (*byte)(buf)
slice.len = x.length slice.len = x.length
@@ -101,7 +101,7 @@ func stringFromRunes(runeSlice []rune) (s _string) {
} }
// Allocate memory for the string. // Allocate memory for the string.
s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs)) s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs.AsPtr()))
// Encode runes to UTF-8 and store the resulting bytes in the string. // Encode runes to UTF-8 and store the resulting bytes in the string.
index := uintptr(0) index := uintptr(0)