...
1 package runtime
2
3 import (
4 "reflect"
5 "unsafe"
6 )
7
8 type SliceHeader struct {
9 Data unsafe.Pointer
10 Len int
11 Cap int
12 }
13
14 const (
15 maxAcceptableTypeAddrRange = 1024 * 1024 * 2
16 )
17
18 type TypeAddr struct {
19 BaseTypeAddr uintptr
20 MaxTypeAddr uintptr
21 AddrRange uintptr
22 AddrShift uintptr
23 }
24
25 var (
26 typeAddr *TypeAddr
27 alreadyAnalyzed bool
28 )
29
30
31 func typelinks() ([]unsafe.Pointer, [][]int32)
32
33
34 func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer
35
36 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
63 }
64 if max < addr {
65 max = addr
66 }
67 if typ.Kind() == reflect.Ptr {
68 addr = uintptr(unsafe.Pointer(typ.Elem()))
69 if min > addr {
70 min = addr
71 }
72 if max < addr {
73 max = addr
74 }
75 }
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 }
99 return typeAddr
100 }
101
View as plain text