1
0
mirror of https://github.com/golang/go synced 2024-09-29 14:24:32 -06:00

[dev.regabi] cmd/compile: use names for keep alive variables in function call

Back to pre Russquake, Node.Nbody of OCALL* node is used to attach
variables which must be kept alive during that call.

Now after Russquake, we have CallExpr to represent a function call,
so use a dedicated field for those variables instead.

Passes toolstash -cmp.

Change-Id: I4f40ebefcc7c41cdcc4e29c7a6d8496a083b68f4
Reviewed-on: https://go-review.googlesource.com/c/go/+/280733
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Cuong Manh Le 2020-12-30 14:08:44 +07:00
parent 8fe1197654
commit 77fd81a3e6
5 changed files with 39 additions and 13 deletions

View File

@ -159,13 +159,13 @@ const (
type CallExpr struct { type CallExpr struct {
miniExpr miniExpr
origNode origNode
X Node X Node
Args Nodes Args Nodes
Rargs Nodes // TODO(rsc): Delete. Rargs Nodes // TODO(rsc): Delete.
Body Nodes // TODO(rsc): Delete. KeepAlive []*Name // vars to be kept alive until call returns
IsDDD bool IsDDD bool
Use CallUse Use CallUse
NoInline bool NoInline bool
} }
func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {

View File

@ -251,7 +251,7 @@ func (n *CallExpr) copy() Node {
c.init = copyNodes(c.init) c.init = copyNodes(c.init)
c.Args = copyNodes(c.Args) c.Args = copyNodes(c.Args)
c.Rargs = copyNodes(c.Rargs) c.Rargs = copyNodes(c.Rargs)
c.Body = copyNodes(c.Body) c.KeepAlive = copyNames(c.KeepAlive)
return &c return &c
} }
func (n *CallExpr) doChildren(do func(Node) bool) bool { func (n *CallExpr) doChildren(do func(Node) bool) bool {
@ -267,7 +267,7 @@ func (n *CallExpr) doChildren(do func(Node) bool) bool {
if doNodes(n.Rargs, do) { if doNodes(n.Rargs, do) {
return true return true
} }
if doNodes(n.Body, do) { if doNames(n.KeepAlive, do) {
return true return true
} }
return false return false
@ -279,7 +279,7 @@ func (n *CallExpr) editChildren(edit func(Node) Node) {
} }
editNodes(n.Args, edit) editNodes(n.Args, edit)
editNodes(n.Rargs, edit) editNodes(n.Rargs, edit)
editNodes(n.Body, edit) editNames(n.KeepAlive, edit)
} }
func (n *CaseClause) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } func (n *CaseClause) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
@ -1381,6 +1381,30 @@ func editCommClauses(list []*CommClause, edit func(Node) Node) {
} }
} }
func copyNames(list []*Name) []*Name {
if list == nil {
return nil
}
c := make([]*Name, len(list))
copy(c, list)
return c
}
func doNames(list []*Name, do func(Node) bool) bool {
for _, x := range list {
if x != nil && do(x) {
return true
}
}
return false
}
func editNames(list []*Name, edit func(Node) Node) {
for i, x := range list {
if x != nil {
list[i] = edit(x).(*Name)
}
}
}
func copyNodes(list []Node) []Node { func copyNodes(list []Node) []Node {
if list == nil { if list == nil {
return nil return nil

View File

@ -4867,7 +4867,9 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
s.vars[memVar] = call s.vars[memVar] = call
} }
// Insert OVARLIVE nodes // Insert OVARLIVE nodes
s.stmtList(n.Body) for _, name := range n.KeepAlive {
s.stmt(ir.NewUnaryExpr(n.Pos(), ir.OVARLIVE, name))
}
// Finish block for defers // Finish block for defers
if k == callDefer || k == callDeferStack { if k == callDefer || k == callDeferStack {

View File

@ -518,7 +518,7 @@ func (o *orderState) call(nn ir.Node) {
x := o.copyExpr(arg.X) x := o.copyExpr(arg.X)
arg.X = x arg.X = x
x.Name().SetAddrtaken(true) // ensure SSA keeps the x variable x.Name().SetAddrtaken(true) // ensure SSA keeps the x variable
n.Body.Append(typecheck.Stmt(ir.NewUnaryExpr(base.Pos, ir.OVARLIVE, x))) n.KeepAlive = append(n.KeepAlive, x.(*ir.Name))
} }
} }
} }

View File

@ -228,7 +228,7 @@ func walkGoDefer(n *ir.GoDeferStmt) ir.Node {
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
call := call.(*ir.CallExpr) call := call.(*ir.CallExpr)
if len(call.Body) > 0 { if len(call.KeepAlive) > 0 {
n.Call = wrapCall(call, &init) n.Call = wrapCall(call, &init)
} else { } else {
n.Call = walkExpr(call, &init) n.Call = walkExpr(call, &init)