runtime: add gc layout info for some basic types

This commit is contained in:
Damian Gryski
2024-10-03 12:03:32 -07:00
committed by Ayke
parent b8fe75a9dd
commit 6e6507bf77
6 changed files with 73 additions and 7 deletions
+1
View File
@@ -245,6 +245,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"internal/cm/": false, "internal/cm/": false,
"internal/fuzz/": false, "internal/fuzz/": false,
"internal/reflectlite/": false, "internal/reflectlite/": false,
"internal/gclayout": false,
"internal/task/": false, "internal/task/": false,
"internal/wasi/": false, "internal/wasi/": false,
"machine/": false, "machine/": false,
+33
View File
@@ -0,0 +1,33 @@
package gclayout
import "unsafe"
// Internal constants for gc layout
// See runtime/gc_precise.go
var (
NoPtrs unsafe.Pointer
Pointer unsafe.Pointer
String unsafe.Pointer
Slice unsafe.Pointer
)
func init() {
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))
}
+21
View File
@@ -64,6 +64,7 @@
package reflect package reflect
import ( import (
"internal/gclayout"
"internal/itoa" "internal/itoa"
"unsafe" "unsafe"
) )
@@ -961,6 +962,26 @@ func (t *rawType) Align() int {
} }
} }
func (r *rawType) gcLayout() unsafe.Pointer {
kind := r.Kind()
if kind < String {
return gclayout.NoPtrs
}
switch kind {
case Pointer, UnsafePointer, Chan, Map:
return gclayout.Pointer
case String:
return gclayout.String
case Slice:
return gclayout.Slice
}
// Unknown (for now); let the conservative pointer scanning handle it
return nil
}
// FieldAlign returns the alignment if this type is used in a struct field. It // FieldAlign returns the alignment if this type is used in a struct field. It
// is currently an alias for Align() but this might change in the future. // is currently an alias for Align() but this might change in the future.
func (t *rawType) FieldAlign() int { func (t *rawType) FieldAlign() int {
+5 -2
View File
@@ -1479,7 +1479,8 @@ func MakeSlice(typ Type, len, cap int) Value {
ulen := uint(len) ulen := uint(len)
ucap := uint(cap) ucap := uint(cap)
maxSize := (^uintptr(0)) / 2 maxSize := (^uintptr(0)) / 2
elementSize := rtype.elem().Size() elem := rtype.elem()
elementSize := elem.Size()
if elementSize > 1 { if elementSize > 1 {
maxSize /= uintptr(elementSize) maxSize /= uintptr(elementSize)
} }
@@ -1493,7 +1494,9 @@ func MakeSlice(typ Type, len, cap int) Value {
var slice sliceHeader var slice sliceHeader
slice.cap = uintptr(ucap) slice.cap = uintptr(ucap)
slice.len = uintptr(ulen) slice.len = uintptr(ulen)
slice.data = alloc(size, nil) layout := elem.gcLayout()
slice.data = alloc(size, layout)
return Value{ return Value{
typecode: rtype, typecode: rtype,
+8 -1
View File
@@ -3,6 +3,7 @@ package runtime
// This file implements compiler builtins for slices: append() and copy(). // This file implements compiler builtins for slices: append() and copy().
import ( import (
"internal/gclayout"
"math/bits" "math/bits"
"unsafe" "unsafe"
) )
@@ -47,7 +48,13 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr)
// memory allocators, this causes some difficult to debug issues. // memory allocators, this causes some difficult to debug issues.
newCap = 1 << bits.Len(uint(newCap)) newCap = 1 << bits.Len(uint(newCap))
buf := alloc(newCap*elemSize, nil) var layout unsafe.Pointer
// less type info here; can only go off element size
if elemSize < unsafe.Sizeof(uintptr(0)) {
layout = gclayout.NoPtrs
}
buf := alloc(newCap*elemSize, layout)
if oldLen > 0 { if oldLen > 0 {
// copy any data to new slice // copy any data to new slice
memmove(buf, oldBuf, oldLen*elemSize) memmove(buf, oldBuf, oldLen*elemSize)
+5 -4
View File
@@ -3,6 +3,7 @@ package runtime
// This file implements functions related to Go strings. // This file implements functions related to Go strings.
import ( import (
"internal/gclayout"
"unsafe" "unsafe"
) )
@@ -59,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, nil) buf := alloc(length, gclayout.NoPtrs)
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}
@@ -72,7 +73,7 @@ func stringFromBytes(x struct {
len uintptr len uintptr
cap uintptr cap uintptr
}) _string { }) _string {
buf := alloc(x.len, nil) buf := alloc(x.len, gclayout.NoPtrs)
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}
} }
@@ -83,7 +84,7 @@ func stringToBytes(x _string) (slice struct {
len uintptr len uintptr
cap uintptr cap uintptr
}) { }) {
buf := alloc(x.length, nil) buf := alloc(x.length, gclayout.NoPtrs)
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
@@ -100,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, nil)) s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs))
// 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)