]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/escape: flip transient to !persists
authorMatthew Dempsky <mdempsky@google.com>
Tue, 15 Aug 2023 21:02:37 +0000 (14:02 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 17 Aug 2023 14:27:55 +0000 (14:27 +0000)
I want to add more location properties (e.g., to track indirect stores
and calls), and it's easier to reason about them if they're all
consistent that "true" means more consequences than less.

Change-Id: I3f8674bb11877ba33082a0f5f7d8e55ad6d7a4cc
Reviewed-on: https://go-review.googlesource.com/c/go/+/520257
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/compile/internal/escape/call.go
src/cmd/compile/internal/escape/escape.go
src/cmd/compile/internal/escape/expr.go
src/cmd/compile/internal/escape/graph.go
src/cmd/compile/internal/escape/solve.go
src/cmd/compile/internal/escape/stmt.go

index bfba651cef25b874901c9d26fd7ae0cb51ec9f4d..2dd3fe8375f0fa8537daf288ae562c9b92a60b6c 100644 (file)
@@ -430,7 +430,7 @@ func (e *escape) copyExpr(pos src.XPos, expr ir.Node, init *ir.Nodes, fn *ir.Fun
        init.Append(stmts...)
 
        if analyze {
-               e.newLoc(tmp, false)
+               e.newLoc(tmp, true)
                e.stmts(stmts)
        }
 
index be02f1b6b0a41e6cf91d86686497e5603af6dc12..ea9287712c027cd779f506b2149948690e434878 100644 (file)
@@ -130,7 +130,7 @@ func Batch(fns []*ir.Func, recursive bool) {
 
        var b batch
        b.heapLoc.escapes = true
-       b.blankLoc.transient = true
+       b.heapLoc.persists = true
 
        // Construct data-flow graph from syntax trees.
        for _, fn := range fns {
@@ -185,14 +185,14 @@ func (b *batch) initFunc(fn *ir.Func) {
 
        // Allocate locations for local variables.
        for _, n := range fn.Dcl {
-               e.newLoc(n, false)
+               e.newLoc(n, true)
        }
 
        // Also for hidden parameters (e.g., the ".this" parameter to a
        // method value wrapper).
        if fn.OClosure == nil {
                for _, n := range fn.ClosureVars {
-                       e.newLoc(n.Canonical(), false)
+                       e.newLoc(n.Canonical(), true)
                }
        }
 
@@ -324,7 +324,7 @@ func (b *batch) finish(fns []*ir.Func) {
                                base.WarnfAt(n.Pos(), "%v does not escape", n)
                        }
                        n.SetEsc(ir.EscNone)
-                       if loc.transient {
+                       if !loc.persists {
                                switch n.Op() {
                                case ir.OCLOSURE:
                                        n := n.(*ir.ClosureExpr)
index d3f963d40a65d41db77c86047b0192521a4642ec..81c0528f1b0b970d8b950e45837a0ffd55c8f161 100644 (file)
@@ -250,7 +250,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
                                // analysis (happens for escape analysis called
                                // from reflectdata.methodWrapper)
                                if n.Op() == ir.ONAME && n.Opt == nil {
-                                       e.with(fn).newLoc(n, false)
+                                       e.with(fn).newLoc(n, true)
                                }
                        }
                        e.walkFunc(fn)
@@ -335,7 +335,7 @@ func (e *escape) discards(l ir.Nodes) {
 // its address to k, and returns a hole that flows values to it. It's
 // intended for use with most expressions that allocate storage.
 func (e *escape) spill(k hole, n ir.Node) hole {
-       loc := e.newLoc(n, true)
+       loc := e.newLoc(n, false)
        e.flow(k.addr(n, "spill"), loc)
        return loc.asHole()
 }
index fc18f7715f75d41a68fbf0f6f0dcecb7813310ab..ad97b7c28c28cec082cc8506843c27479595deea 100644 (file)
@@ -71,10 +71,10 @@ type location struct {
        // allocated.
        escapes bool
 
-       // transient reports whether the represented expression's
-       // address does not outlive the statement; that is, whether
-       // its storage can be immediately reused.
-       transient bool
+       // persists reports whether the represented expression's address
+       // outlives the statement; that is, whether its storage cannot be
+       // immediately reused.
+       persists bool
 
        // paramEsc records the represented parameter's leak set.
        paramEsc leaks
@@ -213,7 +213,7 @@ func (b *batch) oldLoc(n *ir.Name) *location {
        return n.Canonical().Opt.(*location)
 }
 
-func (e *escape) newLoc(n ir.Node, transient bool) *location {
+func (e *escape) newLoc(n ir.Node, persists bool) *location {
        if e.curfn == nil {
                base.Fatalf("e.curfn isn't set")
        }
@@ -230,7 +230,7 @@ func (e *escape) newLoc(n ir.Node, transient bool) *location {
                n:         n,
                curfn:     e.curfn,
                loopDepth: e.loopDepth,
-               transient: transient,
+               persists:  persists,
        }
        e.allLocs = append(e.allLocs, loc)
        if n != nil {
@@ -265,7 +265,7 @@ func (e *escape) teeHole(ks ...hole) hole {
        // Given holes "l1 = _", "l2 = **_", "l3 = *_", ..., create a
        // new temporary location ltmp, wire it into place, and return
        // a hole for "ltmp = _".
-       loc := e.newLoc(nil, true)
+       loc := e.newLoc(nil, false)
        for _, k := range ks {
                // N.B., "p = &q" and "p = &tmp; tmp = q" are not
                // semantically equivalent. To combine holes like "l1
@@ -285,7 +285,7 @@ func (e *escape) teeHole(ks ...hole) hole {
 // Its main effect is to prevent immediate reuse of temporary
 // variables introduced during Order.
 func (e *escape) later(k hole) hole {
-       loc := e.newLoc(nil, false)
+       loc := e.newLoc(nil, true)
        e.flow(k, loc)
        return loc.asHole()
 }
index a2d3b6d2fd9dd56ee6b76b7d2e8e8f44a00a4add..2856c9c13144e2ccbb999db8b71bdfa79917cd74 100644 (file)
@@ -21,7 +21,7 @@ func (b *batch) walkAll() {
        //
        // We walk once from each location (including the heap), and
        // then re-enqueue each location on its transition from
-       // transient->!transient and !escapes->escapes, which can each
+       // !persists->persists and !escapes->escapes, which can each
        // happen at most once. So we take Θ(len(e.allLocs)) walks.
 
        // LIFO queue, has enough room for e.allLocs and e.heapLoc.
@@ -77,11 +77,10 @@ func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location))
                        // derefs at 0.
                        derefs = 0
 
-                       // If l's address flows to a non-transient
-                       // location, then l can't be transiently
-                       // allocated.
-                       if !root.transient && l.transient {
-                               l.transient = false
+                       // If l's address flows to a persistent location, then l needs
+                       // to persist too.
+                       if root.persists && !l.persists {
+                               l.persists = true
                                enqueue(l)
                        }
                }
index 4752e561e257711ce29bb4ad59200981c417a79c..cb2b72fa6b4ee7b83ee3cf28d8f6d32647c5af92 100644 (file)
@@ -92,8 +92,9 @@ func (e *escape) stmt(n ir.Node) {
                n := n.(*ir.RangeStmt)
                base.Assert(!n.DistinctVars) // Should all be rewritten before escape analysis
 
-               // X is evaluated outside the loop.
-               tmp := e.newLoc(nil, false)
+               // X is evaluated outside the loop and persists until the loop
+               // terminates.
+               tmp := e.newLoc(nil, true)
                e.expr(tmp.asHole(), n.X)
 
                e.loopDepth++