mirror of https://github.com/golang/go.git
cmd/compile: add ir.ContainsClosure
And use it to unify all codes that need parent/closure checking. Change-Id: I0b0aa1b007598668dff2c4bee31e21f0fb3830ce Reviewed-on: https://go-review.googlesource.com/c/go/+/650315 Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
34073a736a
commit
a08984bc8f
|
|
@ -278,7 +278,7 @@ func (b *batch) outlives(l, other *location) bool {
|
|||
// var u int // okay to stack allocate
|
||||
// fn := func() *int { return &u }()
|
||||
// *fn() = 42
|
||||
if containsClosure(other.curfn, l.curfn) && !l.curfn.ClosureResultsLost() {
|
||||
if ir.ContainsClosure(other.curfn, l.curfn) && !l.curfn.ClosureResultsLost() {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -304,24 +304,9 @@ func (b *batch) outlives(l, other *location) bool {
|
|||
// func() {
|
||||
// l = new(int) // must heap allocate: outlives call frame (if not inlined)
|
||||
// }()
|
||||
if containsClosure(l.curfn, other.curfn) {
|
||||
if ir.ContainsClosure(l.curfn, other.curfn) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// containsClosure reports whether c is a closure contained within f.
|
||||
func containsClosure(f, c *ir.Func) bool {
|
||||
// Common cases.
|
||||
if f == c || c.OClosure == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for p := c.ClosureParent; p != nil; p = p.ClosureParent {
|
||||
if p == f {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1009,26 +1009,19 @@ func canInlineCallExpr(callerfn *ir.Func, n *ir.CallExpr, callee *ir.Func, bigCa
|
|||
return false, 0, false
|
||||
}
|
||||
|
||||
isClosureParent := func(closure, parent *ir.Func) bool {
|
||||
for p := closure.ClosureParent; p != nil; p = p.ClosureParent {
|
||||
if p == parent {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if isClosureParent(callerfn, callee) {
|
||||
if ir.ContainsClosure(callee, callerfn) {
|
||||
// Can't recursively inline a parent of the closure into itself.
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to closure parent: %s, %s", ir.FuncName(callerfn), ir.FuncName(callee)))
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
if isClosureParent(callee, callerfn) {
|
||||
|
||||
if ir.ContainsClosure(callerfn, callee) {
|
||||
// Can't recursively inline a closure if there's a call to the parent in closure body.
|
||||
if ir.Any(callee, func(node ir.Node) bool {
|
||||
if call, ok := node.(*ir.CallExpr); ok {
|
||||
if name, ok := call.Fun.(*ir.Name); ok && isClosureParent(callerfn, name.Func) {
|
||||
if name, ok := call.Fun.(*ir.Name); ok && ir.ContainsClosure(name.Func, callerfn) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -627,3 +627,18 @@ func (fn *Func) DeclareParams(setNname bool) {
|
|||
declareParams(params, PPARAM, "~p", 0)
|
||||
declareParams(results, PPARAMOUT, "~r", len(params))
|
||||
}
|
||||
|
||||
// ContainsClosure reports whether c is a closure contained within f.
|
||||
func ContainsClosure(f, c *Func) bool {
|
||||
// Common cases.
|
||||
if f == c || c.OClosure == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for p := c.ClosureParent; p != nil; p = p.ClosureParent {
|
||||
if p == f {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue