Skip to content

Commit 6e6507b

Browse files
dgryskiaykevl
authored andcommitted
runtime: add gc layout info for some basic types
1 parent b8fe75a commit 6e6507b

File tree

6 files changed

+73
-7
lines changed

6 files changed

+73
-7
lines changed

loader/goroot.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
245245
"internal/cm/": false,
246246
"internal/fuzz/": false,
247247
"internal/reflectlite/": false,
248+
"internal/gclayout": false,
248249
"internal/task/": false,
249250
"internal/wasi/": false,
250251
"machine/": false,

src/internal/gclayout/gclayout.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package gclayout
2+
3+
import "unsafe"
4+
5+
// Internal constants for gc layout
6+
// See runtime/gc_precise.go
7+
8+
var (
9+
NoPtrs unsafe.Pointer
10+
Pointer unsafe.Pointer
11+
String unsafe.Pointer
12+
Slice unsafe.Pointer
13+
)
14+
15+
func init() {
16+
var sizeBits uintptr
17+
18+
switch unsafe.Sizeof(uintptr(0)) {
19+
case 8:
20+
sizeBits = 6
21+
case 4:
22+
sizeBits = 5
23+
case 2:
24+
sizeBits = 4
25+
}
26+
27+
var sizeShift = sizeBits + 1
28+
29+
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
30+
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
31+
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
32+
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
33+
}

src/reflect/type.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
package reflect
6565

6666
import (
67+
"internal/gclayout"
6768
"internal/itoa"
6869
"unsafe"
6970
)
@@ -961,6 +962,26 @@ func (t *rawType) Align() int {
961962
}
962963
}
963964

965+
func (r *rawType) gcLayout() unsafe.Pointer {
966+
kind := r.Kind()
967+
968+
if kind < String {
969+
return gclayout.NoPtrs
970+
}
971+
972+
switch kind {
973+
case Pointer, UnsafePointer, Chan, Map:
974+
return gclayout.Pointer
975+
case String:
976+
return gclayout.String
977+
case Slice:
978+
return gclayout.Slice
979+
}
980+
981+
// Unknown (for now); let the conservative pointer scanning handle it
982+
return nil
983+
}
984+
964985
// FieldAlign returns the alignment if this type is used in a struct field. It
965986
// is currently an alias for Align() but this might change in the future.
966987
func (t *rawType) FieldAlign() int {

src/reflect/value.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,7 +1479,8 @@ func MakeSlice(typ Type, len, cap int) Value {
14791479
ulen := uint(len)
14801480
ucap := uint(cap)
14811481
maxSize := (^uintptr(0)) / 2
1482-
elementSize := rtype.elem().Size()
1482+
elem := rtype.elem()
1483+
elementSize := elem.Size()
14831484
if elementSize > 1 {
14841485
maxSize /= uintptr(elementSize)
14851486
}
@@ -1493,7 +1494,9 @@ func MakeSlice(typ Type, len, cap int) Value {
14931494
var slice sliceHeader
14941495
slice.cap = uintptr(ucap)
14951496
slice.len = uintptr(ulen)
1496-
slice.data = alloc(size, nil)
1497+
layout := elem.gcLayout()
1498+
1499+
slice.data = alloc(size, layout)
14971500

14981501
return Value{
14991502
typecode: rtype,

src/runtime/slice.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package runtime
33
// This file implements compiler builtins for slices: append() and copy().
44

55
import (
6+
"internal/gclayout"
67
"math/bits"
78
"unsafe"
89
)
@@ -47,7 +48,13 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr)
4748
// memory allocators, this causes some difficult to debug issues.
4849
newCap = 1 << bits.Len(uint(newCap))
4950

50-
buf := alloc(newCap*elemSize, nil)
51+
var layout unsafe.Pointer
52+
// less type info here; can only go off element size
53+
if elemSize < unsafe.Sizeof(uintptr(0)) {
54+
layout = gclayout.NoPtrs
55+
}
56+
57+
buf := alloc(newCap*elemSize, layout)
5158
if oldLen > 0 {
5259
// copy any data to new slice
5360
memmove(buf, oldBuf, oldLen*elemSize)

src/runtime/string.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package runtime
33
// This file implements functions related to Go strings.
44

55
import (
6+
"internal/gclayout"
67
"unsafe"
78
)
89

@@ -59,7 +60,7 @@ func stringConcat(x, y _string) _string {
5960
return x
6061
} else {
6162
length := x.length + y.length
62-
buf := alloc(length, nil)
63+
buf := alloc(length, gclayout.NoPtrs)
6364
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
6465
memcpy(unsafe.Add(buf, x.length), unsafe.Pointer(y.ptr), y.length)
6566
return _string{ptr: (*byte)(buf), length: length}
@@ -72,7 +73,7 @@ func stringFromBytes(x struct {
7273
len uintptr
7374
cap uintptr
7475
}) _string {
75-
buf := alloc(x.len, nil)
76+
buf := alloc(x.len, gclayout.NoPtrs)
7677
memcpy(buf, unsafe.Pointer(x.ptr), x.len)
7778
return _string{ptr: (*byte)(buf), length: x.len}
7879
}
@@ -83,7 +84,7 @@ func stringToBytes(x _string) (slice struct {
8384
len uintptr
8485
cap uintptr
8586
}) {
86-
buf := alloc(x.length, nil)
87+
buf := alloc(x.length, gclayout.NoPtrs)
8788
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
8889
slice.ptr = (*byte)(buf)
8990
slice.len = x.length
@@ -100,7 +101,7 @@ func stringFromRunes(runeSlice []rune) (s _string) {
100101
}
101102

102103
// Allocate memory for the string.
103-
s.ptr = (*byte)(alloc(s.length, nil))
104+
s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs))
104105

105106
// Encode runes to UTF-8 and store the resulting bytes in the string.
106107
index := uintptr(0)

0 commit comments

Comments
 (0)