@@ -2,6 +2,7 @@ package runtime
2
2
3
3
import (
4
4
"reflect"
5
+ "sync"
5
6
"unsafe"
6
7
)
7
8
@@ -23,8 +24,8 @@ type TypeAddr struct {
23
24
}
24
25
25
26
var (
26
- typeAddr * TypeAddr
27
- alreadyAnalyzed bool
27
+ typeAddr * TypeAddr
28
+ once sync. Once
28
29
)
29
30
30
31
//go:linkname typelinks reflect.typelinks
@@ -34,67 +35,64 @@ func typelinks() ([]unsafe.Pointer, [][]int32)
34
35
func rtypeOff (unsafe.Pointer , int32 ) unsafe.Pointer
35
36
36
37
func AnalyzeTypeAddr () * TypeAddr {
37
- defer func () {
38
- alreadyAnalyzed = true
39
- }()
40
- if alreadyAnalyzed {
41
- return typeAddr
42
- }
43
- sections , offsets := typelinks ()
44
- if len (sections ) != 1 {
45
- return nil
46
- }
47
- if len (offsets ) != 1 {
48
- return nil
49
- }
50
- section := sections [0 ]
51
- offset := offsets [0 ]
52
- var (
53
- min uintptr = uintptr (^ uint (0 ))
54
- max uintptr = 0
55
- isAligned64 = true
56
- isAligned32 = true
57
- )
58
- for i := 0 ; i < len (offset ); i ++ {
59
- typ := (* Type )(rtypeOff (section , offset [i ]))
60
- addr := uintptr (unsafe .Pointer (typ ))
61
- if min > addr {
62
- min = addr
38
+ once .Do (func () {
39
+ sections , offsets := typelinks ()
40
+ if len (sections ) != 1 {
41
+ return
63
42
}
64
- if max < addr {
65
- max = addr
43
+ if len ( offsets ) != 1 {
44
+ return
66
45
}
67
- if typ .Kind () == reflect .Ptr {
68
- addr = uintptr (unsafe .Pointer (typ .Elem ()))
46
+ section := sections [0 ]
47
+ offset := offsets [0 ]
48
+ var (
49
+ min uintptr = uintptr (^ uint (0 ))
50
+ max uintptr = 0
51
+ isAligned64 = true
52
+ isAligned32 = true
53
+ )
54
+ for i := 0 ; i < len (offset ); i ++ {
55
+ typ := (* Type )(rtypeOff (section , offset [i ]))
56
+ addr := uintptr (unsafe .Pointer (typ ))
69
57
if min > addr {
70
58
min = addr
71
59
}
72
60
if max < addr {
73
61
max = addr
74
62
}
63
+ if typ .Kind () == reflect .Ptr {
64
+ addr = uintptr (unsafe .Pointer (typ .Elem ()))
65
+ if min > addr {
66
+ min = addr
67
+ }
68
+ if max < addr {
69
+ max = addr
70
+ }
71
+ }
72
+ isAligned64 = isAligned64 && (addr - min )& 63 == 0
73
+ isAligned32 = isAligned32 && (addr - min )& 31 == 0
74
+ }
75
+ addrRange := max - min
76
+ if addrRange == 0 {
77
+ return
78
+ }
79
+ var addrShift uintptr
80
+ if isAligned64 {
81
+ addrShift = 6
82
+ } else if isAligned32 {
83
+ addrShift = 5
75
84
}
76
- isAligned64 = isAligned64 && (addr - min )& 63 == 0
77
- isAligned32 = isAligned32 && (addr - min )& 31 == 0
78
- }
79
- addrRange := max - min
80
- if addrRange == 0 {
81
- return nil
82
- }
83
- var addrShift uintptr
84
- if isAligned64 {
85
- addrShift = 6
86
- } else if isAligned32 {
87
- addrShift = 5
88
- }
89
- cacheSize := addrRange >> addrShift
90
- if cacheSize > maxAcceptableTypeAddrRange {
91
- return nil
92
- }
93
- typeAddr = & TypeAddr {
94
- BaseTypeAddr : min ,
95
- MaxTypeAddr : max ,
96
- AddrRange : addrRange ,
97
- AddrShift : addrShift ,
98
- }
85
+ cacheSize := addrRange >> addrShift
86
+ if cacheSize > maxAcceptableTypeAddrRange {
87
+ return
88
+ }
89
+ typeAddr = & TypeAddr {
90
+ BaseTypeAddr : min ,
91
+ MaxTypeAddr : max ,
92
+ AddrRange : addrRange ,
93
+ AddrShift : addrShift ,
94
+ }
95
+ })
96
+
99
97
return typeAddr
100
98
}
0 commit comments