1
0
mirror of https://github.com/golang/go synced 2024-11-11 19:51:37 -07: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:
Cherry Mui 2021-06-03 18:25:47 -04:00
parent 8e6dfe1b31
commit 46beeed0ac
4 changed files with 11 additions and 12 deletions

View File

@ -192,6 +192,7 @@ type ClosureExpr struct {
miniExpr
Func *Func `mknode:"-"`
Prealloc *Name
IsGoWrap bool // whether this is wrapper closure of a go statement
}
func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {

View File

@ -301,8 +301,8 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
}
}
if base.Flag.CompilingRuntime && clo.Esc() == EscHeap {
base.ErrorfAt(clo.Pos(), "heap-allocated closure, not allowed in runtime")
if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
}
}

View File

@ -1570,8 +1570,9 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
// only in-register results?
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 {
cloFunc := callX.(*ir.ClosureExpr).Func
cloFunc.SetClosureCalled(false)
clo := callX.(*ir.ClosureExpr)
clo.Func.SetClosureCalled(false)
clo.IsGoWrap = true
c.PreserveClosure = true
}
return
@ -1777,12 +1778,9 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
// Set escape properties for closure.
if n.Op() == ir.OGO {
// For "go", assume that the closure is going to escape
// (with an exception for the runtime, which doesn't
// permit heap-allocated closures).
if base.Ctxt.Pkgpath != "runtime" {
clo.SetEsc(ir.EscHeap)
}
// For "go", assume that the closure is going to escape.
clo.SetEsc(ir.EscHeap)
clo.IsGoWrap = true
} else {
// For defer, just use whatever result escape analysis
// has determined for the defer.

View File

@ -7,11 +7,11 @@
package p
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"
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
return x + y
}