-
Notifications
You must be signed in to change notification settings - Fork 61
Expand file tree
/
Copy pathruntime_gccgo.go
More file actions
174 lines (151 loc) · 3.87 KB
/
Copy pathruntime_gccgo.go
File metadata and controls
174 lines (151 loc) · 3.87 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//go:build gccgo
package log
import (
"strings"
"sync"
"time"
"unsafe"
)
const (
secondsPerMinute = 60
secondsPerHour = 60 * secondsPerMinute
secondsPerDay = 24 * secondsPerHour
daysPer400Years = 365*400 + 97
daysPer100Years = 365*100 + 24
daysPer4Years = 365*4 + 1
absoluteZeroYear = -292277022399
)
var gccgoDaysBefore = [...]int32{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}
// gccgoG matches libgo's runtime.g through the goid field.
type gccgoG struct {
_panic unsafe.Pointer
_defer unsafe.Pointer
m unsafe.Pointer
syscallsp uintptr
syscallpc uintptr
param unsafe.Pointer
atomicstatus uint32
goid int64
}
//go:noescape
//go:linkname gccgoGetg runtime.getg
func gccgoGetg() *gccgoG
func goid() int {
return int(gccgoGetg().goid)
}
// Goid returns the current goroutine id.
// It exactly matches goroutine id of the stack trace.
func Goid() int64 {
return int64(goid())
}
// BSD-3-Clause, copied from Go's time.absDate.
func absDate(abs uint64, full bool) (year int, month time.Month, day int, yday int) {
d := abs / secondsPerDay
n := d / daysPer400Years
y := 400 * n
d -= daysPer400Years * n
n = d / daysPer100Years
n -= n >> 2
y += 100 * n
d -= daysPer100Years * n
n = d / daysPer4Years
y += 4 * n
d -= daysPer4Years * n
n = d / 365
n -= n >> 2
y += n
d -= 365 * n
year = int(int64(y) + absoluteZeroYear)
yday = int(d)
if !full {
return
}
day = yday
if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
switch {
case day > 31+29-1:
day--
case day == 31+29-1:
return year, time.February, 29, yday
}
}
month = time.Month(day / 31)
begin := int(gccgoDaysBefore[month])
if end := int(gccgoDaysBefore[month+1]); day >= end {
month++
begin = end
}
month++
day = day - begin + 1
return
}
func absClock(abs uint64) (hour, min, sec int) {
sec = int(abs % secondsPerDay)
hour = sec / secondsPerHour
sec -= hour * secondsPerHour
min = sec / secondsPerMinute
sec -= min * secondsPerMinute
return
}
// gccgoLocation must match runtime.location.
type gccgoLocation struct {
pc uintptr
filename string
function string
lineno int
}
//go:noescape
//extern runtime_callers
func gccgoCallers(skip int32, locbuf *gccgoLocation, max int32, keepThunks bool) int32
//go:noescape
//go:linkname gccgoFuncFileLine runtime.funcfileline
func gccgoFuncFileLine(pc uintptr, index int32, more bool) (name, file string, line, frames int)
//go:noescape
//go:linkname gccgoDecodeIdentifier runtime.decodeIdentifier
func gccgoDecodeIdentifier([]byte) int
//go:noinline
func caller1(skip int, pc *uintptr, length, capacity int) int {
if pc == nil || skip < 0 || length < 1 || capacity < 1 {
return 0
}
var location gccgoLocation
if gccgoCallers(int32(skip+1), &location, 1, false) != 1 {
return 0
}
*pc = location.pc
return 1
}
// Fastrandn returns a pseudorandom uint32 in [0,n).
//
//go:noescape
//go:linkname Fastrandn runtime.fastrandn
func Fastrandn(n uint32) uint32
func pcFileLine(pc uintptr) (file string, line int) {
if pc == 0 {
return "", 0
}
_, file, line, _ = gccgoFuncFileLine(pc-1, -1, false)
return file, line
}
func pcFileLineName(pc uintptr) (file string, line int, name string) {
if pc == 0 {
return "", 0, ""
}
name, file, line, _ = gccgoFuncFileLine(pc-1, -1, false)
return file, line, demangleGCCGoSymbol(name)
}
var gccgoSymbolCache sync.Map
// demangleGCCGoSymbol reverses gccgo's underscore encoding. Libgo's low-level
// symbol lookup returns the encoded name; CallersFrames normally decodes it.
func demangleGCCGoSymbol(name string) string {
if !strings.Contains(name, ".") || !strings.Contains(name, "_") {
return name
}
if decoded, ok := gccgoSymbolCache.Load(name); ok {
return decoded.(string)
}
b := []byte(name)
decoded := string(b[:gccgoDecodeIdentifier(b)])
actual, _ := gccgoSymbolCache.LoadOrStore(name, decoded)
return actual.(string)
}