-
Notifications
You must be signed in to change notification settings - Fork 42
/
runtime_go1.23.go
128 lines (106 loc) · 2.92 KB
/
runtime_go1.23.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//go:build go1.23
// +build go1.23
//nolint:unused
package log
import (
"runtime"
"strings"
"unsafe"
)
// Fastrandn returns a pseudorandom uint32 in [0,n).
//
//go:nosplit
func Fastrandn(n uint32) uint32 {
// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return uint32((uint64(cheaprand()) * uint64(n)) >> 32)
}
//go:noescape
//go:linkname cheaprand runtime.cheaprand
func cheaprand() uint32
func pcFileLine(pc uintptr) (file string, line int) {
f := findfunc(pc)
if f._func == nil {
return
}
return (*runtime.Func)(unsafe.Pointer(f._func)).FileLine(pc)
}
func pcFileLineName(pc uintptr) (file string, line int, name string) {
f := findfunc(pc)
if f._func == nil {
return
}
file, line = (*runtime.Func)(unsafe.Pointer(f._func)).FileLine(pc)
str := &f.datap.funcnametab[f.nameOff]
ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
name = *(*string)(unsafe.Pointer(&ss))
return
}
type stringStruct struct {
str unsafe.Pointer
len int
}
//go:nosplit
func findnull(s *byte) int {
if s == nil {
return 0
}
// pageSize is the unit we scan at a time looking for NULL.
// It must be the minimum page size for any architecture Go
// runs on. It's okay (just a minor performance loss) if the
// actual system page size is larger than this value.
const pageSize = 4096
offset := 0
ptr := unsafe.Pointer(s)
// IndexByteString uses wide reads, so we need to be careful
// with page boundaries. Call IndexByteString on
// [ptr, endOfPage) interval.
safeLen := int(pageSize - uintptr(ptr)%pageSize)
for {
t := *(*string)(unsafe.Pointer(&stringStruct{ptr, safeLen}))
// Check one page at a time.
if i := strings.IndexByte(t, 0); i != -1 {
return offset + i
}
// Move to next page
ptr = unsafe.Pointer(uintptr(ptr) + uintptr(safeLen))
offset += safeLen
safeLen = pageSize
}
}
type funcInfo struct {
*_func
datap *moduledata
}
type srcFunc struct {
datap *moduledata
nameOff int32
startLine int32
funcID uint8
}
type _func struct {
entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart
nameOff int32 // function name, as index into moduledata.funcnametab.
args int32 // in/out args size
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
pcsp uint32
pcfile uint32
pcln uint32
npcdata uint32
cuOffset uint32 // runtime.cutab offset of this function's CU
startLine int32 // line number of start of function (func keyword/TEXT directive)
funcID uint8 // set for certain special runtime functions
flag uint8
_ [1]byte // pad
nfuncdata uint8 // must be last, must end on a uint32-aligned boundary
}
type moduledata struct {
pcHeader unsafe.Pointer
funcnametab []byte
cutab []uint32
filetab []byte
pctab []byte
pclntable []byte
// omitted
}
//go:linkname findfunc runtime.findfunc
func findfunc(pc uintptr) funcInfo