}
func Funcs(all []*ir.Func) {
- ir.VisitFuncsBottomUp(all, Batch)
+ // Make a cache of ir.ReassignOracles. The cache is lazily populated.
+ // TODO(thepudds): consider adding a field on ir.Func instead. We might also be able
+ // to use that field elsewhere, like in walk. See discussion in https://go.dev/cl/688075.
+ reassignOracles := make(map[*ir.Func]*ir.ReassignOracle)
+
+ ir.VisitFuncsBottomUp(all, func(list []*ir.Func, recursive bool) {
+ Batch(list, reassignOracles)
+ })
}
// Batch performs escape analysis on a minimal batch of
// functions.
-func Batch(fns []*ir.Func, recursive bool) {
+func Batch(fns []*ir.Func, reassignOracles map[*ir.Func]*ir.ReassignOracle) {
var b batch
b.heapLoc.attrs = attrEscapes | attrPersists | attrMutates | attrCalls
b.mutatorLoc.attrs = attrMutates
b.calleeLoc.attrs = attrCalls
- b.reassignOracles = make(map[*ir.Func]*ir.ReassignOracle)
+ b.reassignOracles = reassignOracles
// Construct data-flow graph from syntax trees.
for _, fn := range fns {
if n == nil || fn == nil {
return
}
- if n.Op() != ir.OMAKESLICE && n.Op() != ir.OCONVIFACE {
- return
- }
-
- // Look up a cached ReassignOracle for the function, lazily computing one if needed.
- ro := b.reassignOracle(fn)
- if ro == nil {
- base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent)
- }
assignTemp := func(n ir.Node, init *ir.Nodes) {
// Preserve any side effects of n by assigning it to an otherwise unused temp.
}
if (*r).Op() != ir.OLITERAL {
+ // Look up a cached ReassignOracle for the function, lazily computing one if needed.
+ ro := b.reassignOracle(fn)
+ if ro == nil {
+ base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent)
+ }
if s := ro.StaticValue(*r); s.Op() == ir.OLITERAL {
lit, ok := s.(*ir.BasicLit)
if !ok || lit.Val().Kind() != constant.Int {
// a literal to avoid heap allocating the underlying interface value.
conv := n.(*ir.ConvExpr)
if conv.X.Op() != ir.OLITERAL && !conv.X.Type().IsInterface() {
+ // TODO(thepudds): likely could avoid some work by tightening the check of conv.X's type.
+ // Look up a cached ReassignOracle for the function, lazily computing one if needed.
+ ro := b.reassignOracle(fn)
+ if ro == nil {
+ base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent)
+ }
v := ro.StaticValue(conv.X)
if v != nil && v.Op() == ir.OLITERAL && ir.ValidTypeForConst(conv.X.Type(), v.Val()) {
if !base.LiteralAllocHash.MatchPos(n.Pos(), nil) {