mirror of
https://github.com/golang/go
synced 2024-09-04 15:34:21 +00:00
[dev.typeparams] cmd/compile: allow go'd closure to escape when compiling runtime
When compiling runtime, we don't allow closures to escape, because we don't want (implicit) allocations to occur when it is not okay to allocate (e.g. in the allocator itself). However, for go statement, it already allocates a new goroutine anyway. It is okay to allocate the closure. Allow it. Also include the closure's name when reporting error. Updates #40724. Change-Id: Id7574ed17cc27709609a059c4eaa67ba1c4436dc Reviewed-on: https://go-review.googlesource.com/c/go/+/325109 Trust: Cherry Mui <cherryyz@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
8e6dfe1b31
commit
46beeed0ac
|
@ -192,6 +192,7 @@ type ClosureExpr struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
Func *Func `mknode:"-"`
|
Func *Func `mknode:"-"`
|
||||||
Prealloc *Name
|
Prealloc *Name
|
||||||
|
IsGoWrap bool // whether this is wrapper closure of a go statement
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
|
func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
|
||||||
|
|
|
@ -301,8 +301,8 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
|
||||||
base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
|
base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if base.Flag.CompilingRuntime && clo.Esc() == EscHeap {
|
if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
|
||||||
base.ErrorfAt(clo.Pos(), "heap-allocated closure, not allowed in runtime")
|
base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1570,8 +1570,9 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
|
||||||
// only in-register results?
|
// only in-register results?
|
||||||
if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 {
|
if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 {
|
||||||
if c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE {
|
if c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE {
|
||||||
cloFunc := callX.(*ir.ClosureExpr).Func
|
clo := callX.(*ir.ClosureExpr)
|
||||||
cloFunc.SetClosureCalled(false)
|
clo.Func.SetClosureCalled(false)
|
||||||
|
clo.IsGoWrap = true
|
||||||
c.PreserveClosure = true
|
c.PreserveClosure = true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -1777,12 +1778,9 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
|
||||||
|
|
||||||
// Set escape properties for closure.
|
// Set escape properties for closure.
|
||||||
if n.Op() == ir.OGO {
|
if n.Op() == ir.OGO {
|
||||||
// For "go", assume that the closure is going to escape
|
// For "go", assume that the closure is going to escape.
|
||||||
// (with an exception for the runtime, which doesn't
|
clo.SetEsc(ir.EscHeap)
|
||||||
// permit heap-allocated closures).
|
clo.IsGoWrap = true
|
||||||
if base.Ctxt.Pkgpath != "runtime" {
|
|
||||||
clo.SetEsc(ir.EscHeap)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// For defer, just use whatever result escape analysis
|
// For defer, just use whatever result escape analysis
|
||||||
// has determined for the defer.
|
// has determined for the defer.
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
package p
|
package p
|
||||||
|
|
||||||
func f(x int) func(int) int {
|
func f(x int) func(int) int {
|
||||||
return func(y int) int { return x + y } // ERROR "heap-allocated closure, not allowed in runtime"
|
return func(y int) int { return x + y } // ERROR "heap-allocated closure f\.func1, not allowed in runtime"
|
||||||
}
|
}
|
||||||
|
|
||||||
func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime"
|
func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime"
|
||||||
return func(y int) int { // ERROR "heap-allocated closure, not allowed in runtime"
|
return func(y int) int { // ERROR "heap-allocated closure g\.func1, not allowed in runtime"
|
||||||
x += y
|
x += y
|
||||||
return x + y
|
return x + y
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue