Skip to content

Commit 9872089

Browse files
authored
fix: AnalyzeTypeAddr using sync.Once (#531)
1 parent 279389a commit 9872089

File tree

1 file changed

+53
-55
lines changed

1 file changed

+53
-55
lines changed

internal/runtime/type.go

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package runtime
22

33
import (
44
"reflect"
5+
"sync"
56
"unsafe"
67
)
78

@@ -23,8 +24,8 @@ type TypeAddr struct {
2324
}
2425

2526
var (
26-
typeAddr *TypeAddr
27-
alreadyAnalyzed bool
27+
typeAddr *TypeAddr
28+
once sync.Once
2829
)
2930

3031
//go:linkname typelinks reflect.typelinks
@@ -34,67 +35,64 @@ func typelinks() ([]unsafe.Pointer, [][]int32)
3435
func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer
3536

3637
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
6342
}
64-
if max < addr {
65-
max = addr
43+
if len(offsets) != 1 {
44+
return
6645
}
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))
6957
if min > addr {
7058
min = addr
7159
}
7260
if max < addr {
7361
max = addr
7462
}
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
7584
}
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+
9997
return typeAddr
10098
}

0 commit comments

Comments
 (0)