1
2
3
4
5 package escape
6
7 import (
8 "cmd/compile/internal/base"
9 "math"
10 "strings"
11 )
12
13
14
15
16 type leaks [8]uint8
17
18 const (
19 leakHeap = iota
20 leakMutator
21 leakCallee
22 leakResult0
23 )
24
25 const numEscResults = len(leaks{}) - leakResult0
26
27
28
29 func (l leaks) Heap() int { return l.get(leakHeap) }
30
31
32
33
34 func (l leaks) Mutator() int { return l.get(leakMutator) }
35
36
37
38
39 func (l leaks) Callee() int { return l.get(leakCallee) }
40
41
42
43
44 func (l leaks) Result(i int) int { return l.get(leakResult0 + i) }
45
46
47 func (l *leaks) AddHeap(derefs int) { l.add(leakHeap, derefs) }
48
49
50
51 func (l *leaks) AddMutator(derefs int) { l.add(leakMutator, derefs) }
52
53
54
55 func (l *leaks) AddCallee(derefs int) { l.add(leakCallee, derefs) }
56
57
58
59 func (l *leaks) AddResult(i, derefs int) { l.add(leakResult0+i, derefs) }
60
61 func (l leaks) get(i int) int { return int(l[i]) - 1 }
62
63 func (l *leaks) add(i, derefs int) {
64 if old := l.get(i); old < 0 || derefs < old {
65 l.set(i, derefs)
66 }
67 }
68
69 func (l *leaks) set(i, derefs int) {
70 v := derefs + 1
71 if v < 0 {
72 base.Fatalf("invalid derefs count: %v", derefs)
73 }
74 if v > math.MaxUint8 {
75 v = math.MaxUint8
76 }
77
78 l[i] = uint8(v)
79 }
80
81
82
83 func (l *leaks) Optimize() {
84
85
86 if x := l.Heap(); x >= 0 {
87 for i := 1; i < len(*l); i++ {
88 if l.get(i) >= x {
89 l.set(i, -1)
90 }
91 }
92 }
93 }
94
95 var leakTagCache = map[leaks]string{}
96
97
98 func (l leaks) Encode() string {
99 if l.Heap() == 0 {
100
101
102 return ""
103 }
104 if s, ok := leakTagCache[l]; ok {
105 return s
106 }
107
108 n := len(l)
109 for n > 0 && l[n-1] == 0 {
110 n--
111 }
112 s := "esc:" + string(l[:n])
113 leakTagCache[l] = s
114 return s
115 }
116
117
118 func parseLeaks(s string) leaks {
119 var l leaks
120 if !strings.HasPrefix(s, "esc:") {
121 l.AddHeap(0)
122 return l
123 }
124 copy(l[:], s[4:])
125 return l
126 }
127
View as plain text