mirror of
https://github.com/golang/go
synced 2024-11-25 14:57:57 -07:00
cmd/compile: remove trivial closure reference
Trivial closures will be converted to global functions, thus they are not closures anymore. Using fn.IsClosure function is enough, allow removing the trivial/non-trivial closures in the code. Change-Id: Iceb186dd92c1732b101e221ebc13406db35c69ea Reviewed-on: https://go-review.googlesource.com/c/go/+/611995 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Tim King <taking@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
fe69121bc5
commit
d288776d91
@ -36,7 +36,7 @@ func Funcs(fns []*ir.Func) {
|
|||||||
// Kludge for "missing func info" linker panic.
|
// Kludge for "missing func info" linker panic.
|
||||||
// See also closureInitLSym in inline/inl.go.
|
// See also closureInitLSym in inline/inl.go.
|
||||||
if clo, ok := (*as.rhs).(*ir.ClosureExpr); ok && clo.Op() == ir.OCLOSURE {
|
if clo, ok := (*as.rhs).(*ir.ClosureExpr); ok && clo.Op() == ir.OCLOSURE {
|
||||||
if !ir.IsTrivialClosure(clo) {
|
if clo.Func.IsClosure() {
|
||||||
ir.InitLSym(clo.Func, true)
|
ir.InitLSym(clo.Func, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1020,7 @@ func mkinlcall(callerfn *ir.Func, n *ir.CallExpr, fn *ir.Func, bigCaller bool) *
|
|||||||
// typecheck.Target.Decls (ir.UseClosure adds all closures to
|
// typecheck.Target.Decls (ir.UseClosure adds all closures to
|
||||||
// Decls).
|
// Decls).
|
||||||
//
|
//
|
||||||
// However, non-trivial closures in Decls are ignored, and are
|
// However, closures in Decls are ignored, and are
|
||||||
// instead enqueued when walk of the calling function
|
// instead enqueued when walk of the calling function
|
||||||
// discovers them.
|
// discovers them.
|
||||||
//
|
//
|
||||||
@ -1045,8 +1045,8 @@ func mkinlcall(callerfn *ir.Func, n *ir.CallExpr, fn *ir.Func, bigCaller bool) *
|
|||||||
}
|
}
|
||||||
|
|
||||||
clo := n.Fun.(*ir.ClosureExpr)
|
clo := n.Fun.(*ir.ClosureExpr)
|
||||||
if ir.IsTrivialClosure(clo) {
|
if !clo.Func.IsClosure() {
|
||||||
// enqueueFunc will handle trivial closures anyways.
|
// enqueueFunc will handle non closures anyways.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,12 +282,12 @@ func (f *Func) SetWBPos(pos src.XPos) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsClosure reports whether f is a function literal that captures at least one value.
|
||||||
func (f *Func) IsClosure() bool {
|
func (f *Func) IsClosure() bool {
|
||||||
if f.OClosure == nil {
|
if f.OClosure == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Trivial closure will be converted to global.
|
return len(f.ClosureVars) > 0
|
||||||
return !IsTrivialClosure(f.OClosure)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncName returns the name (without the package) of the function f.
|
// FuncName returns the name (without the package) of the function f.
|
||||||
@ -419,12 +419,6 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTrivialClosure reports whether closure clo has an
|
|
||||||
// empty list of captured vars.
|
|
||||||
func IsTrivialClosure(clo *ClosureExpr) bool {
|
|
||||||
return len(clo.Func.ClosureVars) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// globClosgen is like Func.Closgen, but for the global scope.
|
// globClosgen is like Func.Closgen, but for the global scope.
|
||||||
var globClosgen int32
|
var globClosgen int32
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ package ir
|
|||||||
// The algorithm (known as Tarjan's algorithm) for doing that is taken from
|
// The algorithm (known as Tarjan's algorithm) for doing that is taken from
|
||||||
// Sedgewick, Algorithms, Second Edition, p. 482, with two adaptations.
|
// Sedgewick, Algorithms, Second Edition, p. 482, with two adaptations.
|
||||||
//
|
//
|
||||||
// First, a non-trivial closure function (fn.OClosure != nil) cannot be
|
// First, a closure function (fn.IsClosure()) cannot be
|
||||||
// the root of a connected component. Refusing to use it as a root forces
|
// the root of a connected component. Refusing to use it as a root forces
|
||||||
// it into the component of the function in which it appears. This is
|
// it into the component of the function in which it appears. This is
|
||||||
// more convenient for escape analysis.
|
// more convenient for escape analysis.
|
||||||
|
@ -389,7 +389,7 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
|
|||||||
|
|
||||||
case ir.OCLOSURE:
|
case ir.OCLOSURE:
|
||||||
r := r.(*ir.ClosureExpr)
|
r := r.(*ir.ClosureExpr)
|
||||||
if ir.IsTrivialClosure(r) {
|
if !r.Func.IsClosure() {
|
||||||
if base.Debug.Closure > 0 {
|
if base.Debug.Closure > 0 {
|
||||||
base.WarnfAt(r.Pos(), "closure converted to global")
|
base.WarnfAt(r.Pos(), "closure converted to global")
|
||||||
}
|
}
|
||||||
@ -668,7 +668,7 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli
|
|||||||
count[x.(*ir.Name)] = 0
|
count[x.(*ir.Name)] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
hasNonTrivialClosure := false
|
hasClosure := false
|
||||||
ir.Visit(as2body.Rhs[0], func(n ir.Node) {
|
ir.Visit(as2body.Rhs[0], func(n ir.Node) {
|
||||||
if name, ok := n.(*ir.Name); ok {
|
if name, ok := n.(*ir.Name); ok {
|
||||||
if c, ok := count[name]; ok {
|
if c, ok := count[name]; ok {
|
||||||
@ -676,13 +676,13 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if clo, ok := n.(*ir.ClosureExpr); ok {
|
if clo, ok := n.(*ir.ClosureExpr); ok {
|
||||||
hasNonTrivialClosure = hasNonTrivialClosure || !ir.IsTrivialClosure(clo)
|
hasClosure = hasClosure || clo.Func.IsClosure()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// If there's a non-trivial closure, it has captured the param,
|
// If there's a closure, it has captured the param,
|
||||||
// so we can't substitute arg for param.
|
// so we can't substitute arg for param.
|
||||||
if hasNonTrivialClosure {
|
if hasClosure {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func directClosureCall(n *ir.CallExpr) {
|
|||||||
clo := n.Fun.(*ir.ClosureExpr)
|
clo := n.Fun.(*ir.ClosureExpr)
|
||||||
clofn := clo.Func
|
clofn := clo.Func
|
||||||
|
|
||||||
if ir.IsTrivialClosure(clo) {
|
if !clofn.IsClosure() {
|
||||||
return // leave for walkClosure to handle
|
return // leave for walkClosure to handle
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,16 +87,15 @@ func directClosureCall(n *ir.CallExpr) {
|
|||||||
|
|
||||||
// Add to Closures for enqueueFunc. It's no longer a proper
|
// Add to Closures for enqueueFunc. It's no longer a proper
|
||||||
// closure, but we may have already skipped over it in the
|
// closure, but we may have already skipped over it in the
|
||||||
// functions list as a non-trivial closure, so this just
|
// functions list, so this just ensures it's compiled.
|
||||||
// ensures it's compiled.
|
|
||||||
ir.CurFunc.Closures = append(ir.CurFunc.Closures, clofn)
|
ir.CurFunc.Closures = append(ir.CurFunc.Closures, clofn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkClosure(clo *ir.ClosureExpr, init *ir.Nodes) ir.Node {
|
func walkClosure(clo *ir.ClosureExpr, init *ir.Nodes) ir.Node {
|
||||||
clofn := clo.Func
|
clofn := clo.Func
|
||||||
|
|
||||||
// If no closure vars, don't bother wrapping.
|
// If not a closure, don't bother wrapping.
|
||||||
if ir.IsTrivialClosure(clo) {
|
if !clofn.IsClosure() {
|
||||||
if base.Debug.Closure > 0 {
|
if base.Debug.Closure > 0 {
|
||||||
base.WarnfAt(clo.Pos(), "closure converted to global")
|
base.WarnfAt(clo.Pos(), "closure converted to global")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user