return false
}
+// doNode visits n and its children, updates the state in v, and returns true if
+// n makes the current function too hairy for inlining.
func (v *hairyVisitor) doNode(n ir.Node) bool {
if n == nil {
return false
// TODO(danscales): Maybe make budget proportional to number of closure
// variables, e.g.:
//v.budget -= int32(len(n.(*ir.ClosureExpr).Func.ClosureVars) * 3)
+ // TODO(austin): However, if we're able to inline this closure into
+ // v.curFunc, then we actually pay nothing for the closure captures. We
+ // should try to account for that if we're going to account for captures.
v.budget -= 15
- // Scan body of closure (which DoChildren doesn't automatically
- // do) to check for disallowed ops in the body and include the
- // body in the budget.
- if doList(n.(*ir.ClosureExpr).Func.Body, v.do) {
- return true
- }
case ir.OGO,
ir.ODEFER,
"net": {
"(*UDPConn).ReadFromUDP",
},
- // These testpoints commented out for now, since CL 479095
- // had to be reverted. We can re-enable this once we roll
- // forward with a new version of 479095.
- /*
- "sync": {
- // Both OnceFunc and its returned closure need to be inlinable so
- // that the returned closure can be inlined into the caller of OnceFunc.
- "OnceFunc",
- "OnceFunc.func2", // The returned closure.
- // TODO(austin): It would be good to check OnceValue and OnceValues,
- // too, but currently they aren't reported because they have type
- // parameters and aren't instantiated in sync.
- }, */
+ "sync": {
+ // Both OnceFunc and its returned closure need to be inlinable so
+ // that the returned closure can be inlined into the caller of OnceFunc.
+ "OnceFunc",
+ "OnceFunc.func2", // The returned closure.
+ // TODO(austin): It would be good to check OnceValue and OnceValues,
+ // too, but currently they aren't reported because they have type
+ // parameters and aren't instantiated in sync.
+ },
"sync/atomic": {
// (*Bool).CompareAndSwap handled below.
"(*Bool).Load",
{
c := 3
- func() { // ERROR "func literal does not escape"
+ func() { // ERROR "can inline main.func26"
c = 4
- func() { // ERROR "func literal does not escape"
+ func() {
if c != 4 {
ppanic("c != 4")
}
recover() // prevent inlining
}()
- }()
+ }() // ERROR "inlining call to main.func26" "func literal does not escape"
if c != 4 {
ppanic("c != 4")
}
{
a := 2
- if r := func(x int) int { // ERROR "func literal does not escape"
+ // This has an unfortunate exponential growth, where as we visit each
+ // function, we inline the inner closure, and that constructs a new
+ // function for any closures inside the inner function, and then we
+ // revisit those. E.g., func34 and func36 are constructed by the inliner.
+ if r := func(x int) int { // ERROR "can inline main.func27"
b := 3
- return func(y int) int { // ERROR "can inline main.func27.1"
+ return func(y int) int { // ERROR "can inline main.func27.1" "can inline main.func34"
c := 5
- return func(z int) int { // ERROR "can inline main.func27.1.1" "can inline main.func27.(func)?2"
+ return func(z int) int { // ERROR "can inline main.func27.1.1" "can inline main.func27.(func)?2" "can inline main.func34.1" "can inline main.func36"
return a*x + b*y + c*z
}(10) // ERROR "inlining call to main.func27.1.1"
}(100) // ERROR "inlining call to main.func27.1" "inlining call to main.func27.(func)?2"
- }(1000); r != 2350 {
+ }(1000); r != 2350 { // ERROR "inlining call to main.func27" "inlining call to main.func34" "inlining call to main.func36"
ppanic("r != 2350")
}
}
{
a := 2
- if r := func(x int) int { // ERROR "func literal does not escape"
+ if r := func(x int) int { // ERROR "can inline main.func28"
b := 3
- return func(y int) int { // ERROR "can inline main.func28.1"
+ return func(y int) int { // ERROR "can inline main.func28.1" "can inline main.func35"
c := 5
- func(z int) { // ERROR "can inline main.func28.1.1" "can inline main.func28.(func)?2"
+ func(z int) { // ERROR "can inline main.func28.1.1" "can inline main.func28.(func)?2" "can inline main.func35.1" "can inline main.func37"
a = a * x
b = b * y
c = c * z
}(10) // ERROR "inlining call to main.func28.1.1"
return a + c
}(100) + b // ERROR "inlining call to main.func28.1" "inlining call to main.func28.(func)?2"
- }(1000); r != 2350 {
+ }(1000); r != 2350 { // ERROR "inlining call to main.func28" "inlining call to main.func35" "inlining call to main.func37"
ppanic("r != 2350")
}
if a != 2000 {