mirror of
https://github.com/golang/go
synced 2024-11-18 17:04:41 -07:00
go/ssa: remove optimization of 'rundefers'.
The SSA builder shouldn't be in the business of interprocedural optimization, especially in the presence of concurrency. This causes the instruction count to increase by 0.03%. LGTM=gri R=gri, pcc CC=golang-codereviews https://golang.org/cl/105020045
This commit is contained in:
parent
cd36f52558
commit
30166088e4
@ -1918,24 +1918,7 @@ start:
|
||||
// locals (which may be mutated by the deferred call)
|
||||
// and return them.
|
||||
if fn.namedResults != nil {
|
||||
// Optimization: if we can prove the deferred call
|
||||
// won't cause recovery from panic, we can avoid a
|
||||
// Recover block.
|
||||
// We scan the callee for calls to recover() iff:
|
||||
// - it's a static call
|
||||
// - to a function in the same package
|
||||
// (other packages' SSA building happens concurrently)
|
||||
// - whose SSA building has started (Blocks != nil)
|
||||
// - and finished (i.e. not this function)
|
||||
// NB, this is always true for: defer func() { ... } ()
|
||||
//
|
||||
// TODO(adonovan): optimize interpackage cases, e.g.
|
||||
// (sync.Mutex).Unlock(), (io.Closer).Close
|
||||
if callee, ok := v.Call.Value.(*Function); ok && callee.Pkg == fn.Pkg && callee != fn && callee.Blocks != nil && !callsRecover(callee) {
|
||||
// Deferred call cannot cause recovery from panic.
|
||||
} else {
|
||||
createRecoverBlock(fn)
|
||||
}
|
||||
createRecoverBlock(fn)
|
||||
}
|
||||
|
||||
case *ast.ReturnStmt:
|
||||
|
@ -103,22 +103,6 @@ func logStack(format string, args ...interface{}) func() {
|
||||
}
|
||||
}
|
||||
|
||||
// callsRecover reports whether f contains a direct call to recover().
|
||||
func callsRecover(f *Function) bool {
|
||||
for _, b := range f.Blocks {
|
||||
for _, instr := range b.Instrs {
|
||||
if call, ok := instr.(*Call); ok {
|
||||
if blt, ok := call.Call.Value.(*Builtin); ok {
|
||||
if blt.Name() == "recover" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// newVar creates a 'var' for use in a types.Tuple.
|
||||
func newVar(name string, typ types.Type) *types.Var {
|
||||
return types.NewParam(token.NoPos, nil, name, typ)
|
||||
|
Loading…
Reference in New Issue
Block a user