Skip to content

Commit

Permalink
cmd/compile: preserve loop depth when evaluating block
Browse files Browse the repository at this point in the history
Add block method to preserve loop depth when evaluating statements in a
block, so escape analysis can handle looping label more precisely.

Updates #22438

Change-Id: I39b306544a6c0ee3fcbebbe0d0ee735cb71773e6
Reviewed-on: https://go-review.googlesource.com/c/go/+/193517
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
  • Loading branch information
cuonglm authored and mdempsky committed Sep 6, 2019
1 parent c99598c commit 1406ece
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
22 changes: 14 additions & 8 deletions src/cmd/compile/internal/gc/escape.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (e *Escape) walkFunc(fn *Node) {

e.curfn = fn
e.loopDepth = 1
e.stmts(fn.Nbody)
e.block(fn.Nbody)
}

// Below we implement the methods for walking the AST and recording
Expand Down Expand Up @@ -284,14 +284,14 @@ func (e *Escape) stmt(n *Node) {

case OIF:
e.discard(n.Left)
e.stmts(n.Nbody)
e.stmts(n.Rlist)
e.block(n.Nbody)
e.block(n.Rlist)

case OFOR, OFORUNTIL:
e.loopDepth++
e.discard(n.Left)
e.stmt(n.Right)
e.stmts(n.Nbody)
e.block(n.Nbody)
e.loopDepth--

case ORANGE:
Expand All @@ -311,7 +311,7 @@ func (e *Escape) stmt(n *Node) {
}
}

e.stmts(n.Nbody)
e.block(n.Nbody)
e.loopDepth--

case OSWITCH:
Expand Down Expand Up @@ -340,13 +340,13 @@ func (e *Escape) stmt(n *Node) {
}

e.discards(cas.List)
e.stmts(cas.Nbody)
e.block(cas.Nbody)
}

case OSELECT:
for _, cas := range n.List.Slice() {
e.stmt(cas.Left)
e.stmts(cas.Nbody)
e.block(cas.Nbody)
}
case OSELRECV:
e.assign(n.Left, n.Right, "selrecv", n)
Expand Down Expand Up @@ -398,12 +398,18 @@ func (e *Escape) stmt(n *Node) {
}

func (e *Escape) stmts(l Nodes) {
// TODO(mdempsky): Preserve and restore e.loopDepth? See also #22438.
for _, n := range l.Slice() {
e.stmt(n)
}
}

// block is like stmts, but preserves loopDepth.
func (e *Escape) block(l Nodes) {
old := e.loopDepth
e.stmts(l)
e.loopDepth = old
}

// expr models evaluating an expression n and flowing the result into
// hole k.
func (e *Escape) expr(k EscHole, n *Node) {
Expand Down
44 changes: 44 additions & 0 deletions test/escape_goto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// errorcheck -0 -m -l

// Copyright 2019 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.

// Test escape analysis for goto statements.

package escape

var x bool

func _() {
var p *int
loop:
if x {
goto loop
}
// BAD: We should be able to recognize that there
// aren't any more "goto loop" after here.
p = new(int) // ERROR "escapes to heap"
_ = p
}

func _() {
var p *int
if x {
loop:
goto loop
} else {
p = new(int) // ERROR "does not escape"
}
_ = p
}

func _() {
var p *int
if x {
loop:
goto loop
}
p = new(int) // ERROR "does not escape"
_ = p
}

0 comments on commit 1406ece

Please sign in to comment.