@@ -291,53 +291,45 @@ func (e *Escape) stmt(n *Node) {
291
291
292
292
case ORANGE :
293
293
// for List = range Right { Nbody }
294
-
295
- // Right is evaluated outside the loop.
296
- tv := e .newLoc (n , false )
297
- e .expr (tv .asHole (), n .Right )
298
-
299
294
e .loopDepth ++
300
295
ks := e .addrs (n .List )
296
+ e .block (n .Nbody )
297
+ e .loopDepth --
298
+
299
+ // Right is evaluated outside the loop.
300
+ k := e .discardHole ()
301
301
if len (ks ) >= 2 {
302
302
if n .Right .Type .IsArray () {
303
- e . flow ( ks [1 ].note (n , "range" ), tv )
303
+ k = ks [1 ].note (n , "range" )
304
304
} else {
305
- e . flow ( ks [1 ].deref (n , "range-deref" ), tv )
305
+ k = ks [1 ].deref (n , "range-deref" )
306
306
}
307
307
}
308
-
309
- e .block (n .Nbody )
310
- e .loopDepth --
308
+ e .expr (e .later (k ), n .Right )
311
309
312
310
case OSWITCH :
313
- var tv * EscLocation
314
- if n .Left != nil {
315
- if n .Left .Op == OTYPESW {
316
- k := e .discardHole ()
317
- if n .Left .Left != nil {
318
- tv = e .newLoc (n .Left , false )
319
- k = tv .asHole ()
320
- }
321
- e .expr (k , n .Left .Right )
322
- } else {
323
- e .discard (n .Left )
324
- }
325
- }
311
+ typesw := n .Left != nil && n .Left .Op == OTYPESW
326
312
313
+ var ks []EscHole
327
314
for _ , cas := range n .List .Slice () { // cases
328
- if tv != nil {
329
- // type switch variables have no ODCL.
315
+ if typesw && n .Left .Left != nil {
330
316
cv := cas .Rlist .First ()
331
- k := e .dcl (cv )
317
+ k := e .dcl (cv ) // type switch variables have no ODCL.
332
318
if types .Haspointers (cv .Type ) {
333
- e . flow ( k .dotType (cv .Type , n , "switch case" ), tv )
319
+ ks = append ( ks , k .dotType (cv .Type , n , "switch case" ))
334
320
}
335
321
}
336
322
337
323
e .discards (cas .List )
338
324
e .block (cas .Nbody )
339
325
}
340
326
327
+ if typesw {
328
+ e .expr (e .teeHole (ks ... ), n .Left .Right )
329
+ } else {
330
+ e .discard (n .Left )
331
+ }
332
+
341
333
case OSELECT :
342
334
for _ , cas := range n .List .Slice () {
343
335
e .stmt (cas .Left )
@@ -882,8 +874,7 @@ func (e *Escape) augmentParamHole(k EscHole, where *Node) EscHole {
882
874
// transiently allocated.
883
875
if where .Op == ODEFER && e .loopDepth == 1 {
884
876
where .Esc = EscNever // force stack allocation of defer record (see ssa.go)
885
- // TODO(mdempsky): Eliminate redundant EscLocation allocs.
886
- return e .teeHole (k , e .newLoc (nil , false ).asHole ())
877
+ return e .later (k )
887
878
}
888
879
889
880
return e .heapHole ()
@@ -988,6 +979,9 @@ func (e *Escape) dcl(n *Node) EscHole {
988
979
return loc .asHole ()
989
980
}
990
981
982
+ // spill allocates a new location associated with expression n, flows
983
+ // its address to k, and returns a hole that flows values to it. It's
984
+ // intended for use with most expressions that allocate storage.
991
985
func (e * Escape ) spill (k EscHole , n * Node ) EscHole {
992
986
// TODO(mdempsky): Optimize. E.g., if k is the heap or blank,
993
987
// then we already know whether n leaks, and we can return a
@@ -997,6 +991,15 @@ func (e *Escape) spill(k EscHole, n *Node) EscHole {
997
991
return loc .asHole ()
998
992
}
999
993
994
+ // later returns a new hole that flows into k, but some time later.
995
+ // Its main effect is to prevent immediate reuse of temporary
996
+ // variables introduced during Order.
997
+ func (e * Escape ) later (k EscHole ) EscHole {
998
+ loc := e .newLoc (nil , false )
999
+ e .flow (k , loc )
1000
+ return loc .asHole ()
1001
+ }
1002
+
1000
1003
// canonicalNode returns the canonical *Node that n logically
1001
1004
// represents.
1002
1005
func canonicalNode (n * Node ) * Node {
@@ -1276,9 +1279,6 @@ func (e *Escape) finish(fns []*Node) {
1276
1279
1277
1280
// Update n.Esc based on escape analysis results.
1278
1281
//
1279
- // TODO(mdempsky): Simplify once compatibility with
1280
- // esc.go is no longer necessary.
1281
- //
1282
1282
// TODO(mdempsky): Describe path when Debug['m'] >= 2.
1283
1283
1284
1284
if loc .escapes {
@@ -1288,15 +1288,12 @@ func (e *Escape) finish(fns []*Node) {
1288
1288
n .Esc = EscHeap
1289
1289
addrescapes (n )
1290
1290
} else {
1291
- if Debug ['m' ] != 0 && n .Op != ONAME && n . Op != OTYPESW && n . Op != ORANGE && n . Op != ODEFER {
1291
+ if Debug ['m' ] != 0 && n .Op != ONAME {
1292
1292
Warnl (n .Pos , "%S does not escape" , n )
1293
1293
}
1294
1294
n .Esc = EscNone
1295
1295
if loc .transient {
1296
- switch n .Op {
1297
- case OCALLPART , OCLOSURE , ODDDARG , OARRAYLIT , OSLICELIT , OPTRLIT , OSTRUCTLIT :
1298
- n .SetNoescape (true )
1299
- }
1296
+ n .SetNoescape (true )
1300
1297
}
1301
1298
}
1302
1299
}
0 commit comments