github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/escape/leaks.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package escape 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 9 "math" 10 "strings" 11 ) 12 13 // A leaks represents a set of assignment flows from a parameter to 14 // the heap, mutator, callee, or to any of its function's (first 15 // numEscResults) result parameters. 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 // Heap returns the minimum deref count of any assignment flow from l 28 // to the heap. If no such flows exist, Heap returns -1. 29 func (l leaks) Heap() int { return l.get(leakHeap) } 30 31 // Mutator returns the minimum deref count of any assignment flow from 32 // l to the pointer operand of an indirect assignment statement. If no 33 // such flows exist, Mutator returns -1. 34 func (l leaks) Mutator() int { return l.get(leakMutator) } 35 36 // Callee returns the minimum deref count of any assignment flow from 37 // l to the callee operand of call expression. If no such flows exist, 38 // Callee returns -1. 39 func (l leaks) Callee() int { return l.get(leakCallee) } 40 41 // Result returns the minimum deref count of any assignment flow from 42 // l to its function's i'th result parameter. If no such flows exist, 43 // Result returns -1. 44 func (l leaks) Result(i int) int { return l.get(leakResult0 + i) } 45 46 // AddHeap adds an assignment flow from l to the heap. 47 func (l *leaks) AddHeap(derefs int) { l.add(leakHeap, derefs) } 48 49 // AddMutator adds a flow from l to the mutator (i.e., a pointer 50 // operand of an indirect assignment statement). 51 func (l *leaks) AddMutator(derefs int) { l.add(leakMutator, derefs) } 52 53 // AddCallee adds an assignment flow from l to the callee operand of a 54 // call expression. 55 func (l *leaks) AddCallee(derefs int) { l.add(leakCallee, derefs) } 56 57 // AddResult adds an assignment flow from l to its function's i'th 58 // result parameter. 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 // Optimize removes result flow paths that are equal in length or 82 // longer than the shortest heap flow path. 83 func (l *leaks) Optimize() { 84 // If we have a path to the heap, then there's no use in 85 // keeping equal or longer paths elsewhere. 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 // Encode converts l into a binary string for export data. 98 func (l leaks) Encode() string { 99 if l.Heap() == 0 { 100 // Space optimization: empty string encodes more 101 // efficiently in export data. 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 // parseLeaks parses a binary string representing a leaks. 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 }