aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/escape
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-22 20:53:14 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-23 05:31:38 +0000
commit99732b9070ea23c13f7ed9ff8518304e34942ad4 (patch)
tree05620b04cfff797193ee0f37d5c361488dbd85a8 /src/cmd/compile/internal/escape
parent1a445dab6676b2a5c0b15b313eabec5a79ea99a3 (diff)
downloadgo-99732b9070ea23c13f7ed9ff8518304e34942ad4.tar.gz
go-99732b9070ea23c13f7ed9ff8518304e34942ad4.zip
[dev.typeparams] cmd/compile: refactor escape analysis of calls
This CL is a prep refactoring for an upcoming CL to move go/defer wrapping into escape analysis. That CL is unfortunately unavoidably complex and subtle, so this CL takes care of some more mundane refactoring details. Change-Id: Ifbefe1d522a8d57066646be09536437f42e7082c Reviewed-on: https://go-review.googlesource.com/c/go/+/330251 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/escape')
-rw-r--r--src/cmd/compile/internal/escape/call.go78
-rw-r--r--src/cmd/compile/internal/escape/expr.go2
-rw-r--r--src/cmd/compile/internal/escape/stmt.go7
3 files changed, 48 insertions, 39 deletions
diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go
index 28a3b679a5..8511259d47 100644
--- a/src/cmd/compile/internal/escape/call.go
+++ b/src/cmd/compile/internal/escape/call.go
@@ -13,26 +13,24 @@ import (
// call evaluates a call expressions, including builtin calls. ks
// should contain the holes representing where the function callee's
-// results flows; where is the OGO/ODEFER context of the call, if any.
-func (e *escape) call(ks []hole, call, where ir.Node) {
- topLevelDefer := where != nil && where.Op() == ir.ODEFER && e.loopDepth == 1
- if topLevelDefer {
- // force stack allocation of defer record, unless
- // open-coded defers are used (see ssa.go)
- where.SetEsc(ir.EscNever)
- }
+// results flows.
+func (e *escape) call(ks []hole, call ir.Node) {
+ e.callCommon(ks, call, nil)
+}
- argument := func(k hole, arg ir.Node) {
- if topLevelDefer {
- // Top level defers arguments don't escape to
- // heap, but they do need to last until end of
- // function.
- k = e.later(k)
- } else if where != nil {
- k = e.heapHole()
+func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) {
+ argument := func(k hole, argp *ir.Node) {
+ if where != nil {
+ if where.Esc() == ir.EscNever {
+ // Top-level defers arguments don't escape to heap,
+ // but they do need to last until end of function.
+ k = e.later(k)
+ } else {
+ k = e.heapHole()
+ }
}
- e.expr(k.note(call, "call parameter"), arg)
+ e.expr(k.note(call, "call parameter"), *argp)
}
switch call.Op() {
@@ -70,15 +68,15 @@ func (e *escape) call(ks []hole, call, where ir.Node) {
}
if r := fntype.Recv(); r != nil {
- argument(e.tagHole(ks, fn, r), call.X.(*ir.SelectorExpr).X)
+ argument(e.tagHole(ks, fn, r), &call.X.(*ir.SelectorExpr).X)
} else {
// Evaluate callee function expression.
- argument(e.discardHole(), call.X)
+ argument(e.discardHole(), &call.X)
}
args := call.Args
for i, param := range fntype.Params().FieldSlice() {
- argument(e.tagHole(ks, fn, param), args[i])
+ argument(e.tagHole(ks, fn, param), &args[i])
}
case ir.OAPPEND:
@@ -93,54 +91,66 @@ func (e *escape) call(ks []hole, call, where ir.Node) {
if args[0].Type().Elem().HasPointers() {
appendeeK = e.teeHole(appendeeK, e.heapHole().deref(call, "appendee slice"))
}
- argument(appendeeK, args[0])
+ argument(appendeeK, &args[0])
if call.IsDDD {
appendedK := e.discardHole()
if args[1].Type().IsSlice() && args[1].Type().Elem().HasPointers() {
appendedK = e.heapHole().deref(call, "appended slice...")
}
- argument(appendedK, args[1])
+ argument(appendedK, &args[1])
} else {
- for _, arg := range args[1:] {
- argument(e.heapHole(), arg)
+ for i := 1; i < len(args); i++ {
+ argument(e.heapHole(), &args[i])
}
}
case ir.OCOPY:
call := call.(*ir.BinaryExpr)
- argument(e.discardHole(), call.X)
+ argument(e.discardHole(), &call.X)
copiedK := e.discardHole()
if call.Y.Type().IsSlice() && call.Y.Type().Elem().HasPointers() {
copiedK = e.heapHole().deref(call, "copied slice")
}
- argument(copiedK, call.Y)
+ argument(copiedK, &call.Y)
case ir.OPANIC:
call := call.(*ir.UnaryExpr)
- argument(e.heapHole(), call.X)
+ argument(e.heapHole(), &call.X)
case ir.OCOMPLEX:
call := call.(*ir.BinaryExpr)
- argument(e.discardHole(), call.X)
- argument(e.discardHole(), call.Y)
+ argument(e.discardHole(), &call.X)
+ argument(e.discardHole(), &call.Y)
case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
call := call.(*ir.CallExpr)
- for _, arg := range call.Args {
- argument(e.discardHole(), arg)
+ for i := range call.Args {
+ argument(e.discardHole(), &call.Args[i])
}
case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE:
call := call.(*ir.UnaryExpr)
- argument(e.discardHole(), call.X)
+ argument(e.discardHole(), &call.X)
case ir.OUNSAFEADD, ir.OUNSAFESLICE:
call := call.(*ir.BinaryExpr)
- argument(ks[0], call.X)
- argument(e.discardHole(), call.Y)
+ argument(ks[0], &call.X)
+ argument(e.discardHole(), &call.Y)
}
}
+func (e *escape) goDeferStmt(n *ir.GoDeferStmt) {
+ topLevelDefer := n.Op() == ir.ODEFER && e.loopDepth == 1
+ if topLevelDefer {
+ // force stack allocation of defer record, unless
+ // open-coded defers are used (see ssa.go)
+ n.SetEsc(ir.EscNever)
+ }
+
+ e.stmts(n.Call.Init())
+ e.callCommon(nil, n.Call, n)
+}
+
// tagHole returns a hole for evaluating an argument passed to param.
// ks should contain the holes representing where the function
// callee's results flows. fn is the statically-known callee function,
diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go
index 5b280c76f1..cb95221dd5 100644
--- a/src/cmd/compile/internal/escape/expr.go
+++ b/src/cmd/compile/internal/escape/expr.go
@@ -139,7 +139,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
e.discard(n.X)
case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE:
- e.call([]hole{k}, n, nil)
+ e.call([]hole{k}, n)
case ir.ONEW:
n := n.(*ir.UnaryExpr)
diff --git a/src/cmd/compile/internal/escape/stmt.go b/src/cmd/compile/internal/escape/stmt.go
index d3e47290d3..0bdb07b278 100644
--- a/src/cmd/compile/internal/escape/stmt.go
+++ b/src/cmd/compile/internal/escape/stmt.go
@@ -163,7 +163,7 @@ func (e *escape) stmt(n ir.Node) {
n := n.(*ir.AssignListStmt)
e.stmts(n.Rhs[0].Init())
ks := e.addrs(n.Lhs)
- e.call(ks, n.Rhs[0], nil)
+ e.call(ks, n.Rhs[0])
e.reassigned(ks, n)
case ir.ORETURN:
n := n.(*ir.ReturnStmt)
@@ -174,11 +174,10 @@ func (e *escape) stmt(n ir.Node) {
}
e.assignList(dsts, n.Results, "return", n)
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
- e.call(nil, n, nil)
+ e.call(nil, n)
case ir.OGO, ir.ODEFER:
n := n.(*ir.GoDeferStmt)
- e.stmts(n.Call.Init())
- e.call(nil, n.Call, n)
+ e.goDeferStmt(n)
case ir.OTAILCALL:
// TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it.