diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:25:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:25:22 +0000 |
commit | f6ad4dcef54c5ce997a4bad5a6d86de229015700 (patch) | |
tree | 7cfa4e31ace5c2bd95c72b154d15af494b2bcbef /src/cmd/compile/internal/escape/leaks.go | |
parent | Initial commit. (diff) | |
download | golang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.tar.xz golang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.zip |
Adding upstream version 1.22.1.upstream/1.22.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/compile/internal/escape/leaks.go')
-rw-r--r-- | src/cmd/compile/internal/escape/leaks.go | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/escape/leaks.go b/src/cmd/compile/internal/escape/leaks.go new file mode 100644 index 0000000..942f87d --- /dev/null +++ b/src/cmd/compile/internal/escape/leaks.go @@ -0,0 +1,126 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "math" + "strings" +) + +// A leaks represents a set of assignment flows from a parameter to +// the heap, mutator, callee, or to any of its function's (first +// numEscResults) result parameters. +type leaks [8]uint8 + +const ( + leakHeap = iota + leakMutator + leakCallee + leakResult0 +) + +const numEscResults = len(leaks{}) - leakResult0 + +// Heap returns the minimum deref count of any assignment flow from l +// to the heap. If no such flows exist, Heap returns -1. +func (l leaks) Heap() int { return l.get(leakHeap) } + +// Mutator returns the minimum deref count of any assignment flow from +// l to the pointer operand of an indirect assignment statement. If no +// such flows exist, Mutator returns -1. +func (l leaks) Mutator() int { return l.get(leakMutator) } + +// Callee returns the minimum deref count of any assignment flow from +// l to the callee operand of call expression. If no such flows exist, +// Callee returns -1. +func (l leaks) Callee() int { return l.get(leakCallee) } + +// Result returns the minimum deref count of any assignment flow from +// l to its function's i'th result parameter. If no such flows exist, +// Result returns -1. +func (l leaks) Result(i int) int { return l.get(leakResult0 + i) } + +// AddHeap adds an assignment flow from l to the heap. +func (l *leaks) AddHeap(derefs int) { l.add(leakHeap, derefs) } + +// AddMutator adds a flow from l to the mutator (i.e., a pointer +// operand of an indirect assignment statement). +func (l *leaks) AddMutator(derefs int) { l.add(leakMutator, derefs) } + +// AddCallee adds an assignment flow from l to the callee operand of a +// call expression. +func (l *leaks) AddCallee(derefs int) { l.add(leakCallee, derefs) } + +// AddResult adds an assignment flow from l to its function's i'th +// result parameter. +func (l *leaks) AddResult(i, derefs int) { l.add(leakResult0+i, derefs) } + +func (l leaks) get(i int) int { return int(l[i]) - 1 } + +func (l *leaks) add(i, derefs int) { + if old := l.get(i); old < 0 || derefs < old { + l.set(i, derefs) + } +} + +func (l *leaks) set(i, derefs int) { + v := derefs + 1 + if v < 0 { + base.Fatalf("invalid derefs count: %v", derefs) + } + if v > math.MaxUint8 { + v = math.MaxUint8 + } + + l[i] = uint8(v) +} + +// Optimize removes result flow paths that are equal in length or +// longer than the shortest heap flow path. +func (l *leaks) Optimize() { + // If we have a path to the heap, then there's no use in + // keeping equal or longer paths elsewhere. + if x := l.Heap(); x >= 0 { + for i := 1; i < len(*l); i++ { + if l.get(i) >= x { + l.set(i, -1) + } + } + } +} + +var leakTagCache = map[leaks]string{} + +// Encode converts l into a binary string for export data. +func (l leaks) Encode() string { + if l.Heap() == 0 { + // Space optimization: empty string encodes more + // efficiently in export data. + return "" + } + if s, ok := leakTagCache[l]; ok { + return s + } + + n := len(l) + for n > 0 && l[n-1] == 0 { + n-- + } + s := "esc:" + string(l[:n]) + leakTagCache[l] = s + return s +} + +// parseLeaks parses a binary string representing a leaks. +func parseLeaks(s string) leaks { + var l leaks + if !strings.HasPrefix(s, "esc:") { + l.AddHeap(0) + return l + } + copy(l[:], s[4:]) + return l +} |