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