// 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
}
// 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
-}
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
}
}
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
+}