27
27
package inline
28
28
29
29
import (
30
- "errors"
31
30
"fmt"
32
31
"go/constant"
33
32
"strings"
@@ -256,17 +255,12 @@ type hairyVisitor struct {
256
255
reason string
257
256
extraCallCost int32
258
257
usedLocals map [* ir.Name ]bool
259
- do func (ir.Node ) error
258
+ do func (ir.Node ) bool
260
259
}
261
260
262
- var errBudget = errors .New ("too expensive" )
263
-
264
261
func (v * hairyVisitor ) tooHairy (fn * ir.Func ) bool {
265
262
v .do = v .doNode // cache closure
266
-
267
- err := errChildren (fn , v .do )
268
- if err != nil {
269
- v .reason = err .Error ()
263
+ if ir .DoChildren (fn , v .do ) {
270
264
return true
271
265
}
272
266
if v .budget < 0 {
@@ -276,11 +270,10 @@ func (v *hairyVisitor) tooHairy(fn *ir.Func) bool {
276
270
return false
277
271
}
278
272
279
- func (v * hairyVisitor ) doNode (n ir.Node ) error {
273
+ func (v * hairyVisitor ) doNode (n ir.Node ) bool {
280
274
if n == nil {
281
- return nil
275
+ return false
282
276
}
283
-
284
277
switch n .Op () {
285
278
// Call is okay if inlinable and we have the budget for the body.
286
279
case ir .OCALLFUNC :
@@ -294,7 +287,8 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
294
287
if name .Class == ir .PFUNC && types .IsRuntimePkg (name .Sym ().Pkg ) {
295
288
fn := name .Sym ().Name
296
289
if fn == "getcallerpc" || fn == "getcallersp" {
297
- return errors .New ("call to " + fn )
290
+ v .reason = "call to " + fn
291
+ return true
298
292
}
299
293
if fn == "throw" {
300
294
v .budget -= inlineExtraThrowCost
@@ -357,7 +351,8 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
357
351
case ir .ORECOVER :
358
352
// recover matches the argument frame pointer to find
359
353
// the right panic value, so it needs an argument frame.
360
- return errors .New ("call to recover" )
354
+ v .reason = "call to recover"
355
+ return true
361
356
362
357
case ir .OCLOSURE :
363
358
// TODO(danscales) - fix some bugs when budget is lowered below 30
@@ -371,24 +366,27 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
371
366
ir .ODEFER ,
372
367
ir .ODCLTYPE , // can't print yet
373
368
ir .OTAILCALL :
374
- return errors .New ("unhandled op " + n .Op ().String ())
369
+ v .reason = "unhandled op " + n .Op ().String ()
370
+ return true
375
371
376
372
case ir .OAPPEND :
377
373
v .budget -= inlineExtraAppendCost
378
374
379
375
case ir .ODCLCONST , ir .OFALL :
380
376
// These nodes don't produce code; omit from inlining budget.
381
- return nil
377
+ return false
382
378
383
379
case ir .OFOR , ir .OFORUNTIL :
384
380
n := n .(* ir.ForStmt )
385
381
if n .Label != nil {
386
- return errors .New ("labeled control" )
382
+ v .reason = "labeled control"
383
+ return true
387
384
}
388
385
case ir .OSWITCH :
389
386
n := n .(* ir.SwitchStmt )
390
387
if n .Label != nil {
391
- return errors .New ("labeled control" )
388
+ v .reason = "labeled control"
389
+ return true
392
390
}
393
391
// case ir.ORANGE, ir.OSELECT in "unhandled" above
394
392
@@ -404,16 +402,9 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
404
402
if ir .IsConst (n .Cond , constant .Bool ) {
405
403
// This if and the condition cost nothing.
406
404
// TODO(rsc): It seems strange that we visit the dead branch.
407
- if err := errList (n .Init (), v .do ); err != nil {
408
- return err
409
- }
410
- if err := errList (n .Body , v .do ); err != nil {
411
- return err
412
- }
413
- if err := errList (n .Else , v .do ); err != nil {
414
- return err
415
- }
416
- return nil
405
+ return doList (n .Init (), v .do ) ||
406
+ doList (n .Body , v .do ) ||
407
+ doList (n .Else , v .do )
417
408
}
418
409
419
410
case ir .ONAME :
@@ -439,10 +430,11 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
439
430
440
431
// When debugging, don't stop early, to get full cost of inlining this function
441
432
if v .budget < 0 && base .Flag .LowerM < 2 && ! logopt .Enabled () {
442
- return errBudget
433
+ v .reason = "too expensive"
434
+ return true
443
435
}
444
436
445
- return errChildren (n , v .do )
437
+ return ir . DoChildren (n , v .do )
446
438
}
447
439
448
440
func isBigFunc (fn * ir.Func ) bool {
@@ -1411,21 +1403,13 @@ func numNonClosures(list []*ir.Func) int {
1411
1403
return count
1412
1404
}
1413
1405
1414
- // TODO(mdempsky): Update inl.go to use ir.DoChildren directly.
1415
- func errChildren (n ir.Node , do func (ir.Node ) error ) (err error ) {
1416
- ir .DoChildren (n , func (x ir.Node ) bool {
1417
- err = do (x )
1418
- return err != nil
1419
- })
1420
- return
1421
- }
1422
- func errList (list []ir.Node , do func (ir.Node ) error ) error {
1406
+ func doList (list []ir.Node , do func (ir.Node ) bool ) bool {
1423
1407
for _ , x := range list {
1424
1408
if x != nil {
1425
- if err := do (x ); err != nil {
1426
- return err
1409
+ if do (x ) {
1410
+ return true
1427
1411
}
1428
1412
}
1429
1413
}
1430
- return nil
1414
+ return false
1431
1415
}
0 commit comments