Commit eb3c44b2 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: cleanup closure.go

The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).

This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)

Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".

In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.

More opportunity for cleanups still, but this makes some substantial
progress, IMO.

Passes toolstash-check.

Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 644d14ea
This diff is collapsed.
...@@ -948,7 +948,7 @@ func (e *EscState) esc(n *Node, parent *Node) { ...@@ -948,7 +948,7 @@ func (e *EscState) esc(n *Node, parent *Node) {
case OCLOSURE: case OCLOSURE:
// Link addresses of captured variables to closure. // Link addresses of captured variables to closure.
for _, v := range n.Func.Cvars.Slice() { for _, v := range n.Func.Closure.Func.Cvars.Slice() {
if v.Op == OXXX { // unnamed out argument; see dcl.go:/^funcargs if v.Op == OXXX { // unnamed out argument; see dcl.go:/^funcargs
continue continue
} }
......
...@@ -816,7 +816,7 @@ func mkinlcall1(n, fn *Node) *Node { ...@@ -816,7 +816,7 @@ func mkinlcall1(n, fn *Node) *Node {
// handle captured variables when inlining closures // handle captured variables when inlining closures
if c := fn.Name.Defn.Func.Closure; c != nil { if c := fn.Name.Defn.Func.Closure; c != nil {
for _, v := range c.Func.Cvars.Slice() { for _, v := range c.Func.Closure.Func.Cvars.Slice() {
if v.Op == OXXX { if v.Op == OXXX {
continue continue
} }
......
...@@ -1124,7 +1124,7 @@ func (o *Order) expr(n, lhs *Node) *Node { ...@@ -1124,7 +1124,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
} }
case OCLOSURE: case OCLOSURE:
if n.Noescape() && n.Func.Cvars.Len() > 0 { if n.Noescape() && n.Func.Closure.Func.Cvars.Len() > 0 {
prealloc[n] = o.newTemp(types.Types[TUINT8], false) // walk will fill in correct type prealloc[n] = o.newTemp(types.Types[TUINT8], false) // walk will fill in correct type
} }
......
...@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) { ...@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
_32bit uintptr // size on 32bit platforms _32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms _64bit uintptr // size on 64bit platforms
}{ }{
{Func{}, 128, 232}, {Func{}, 124, 224},
{Name{}, 32, 56}, {Name{}, 32, 56},
{Param{}, 24, 48}, {Param{}, 24, 48},
{Node{}, 76, 128}, {Node{}, 76, 128},
......
...@@ -471,8 +471,11 @@ type Func struct { ...@@ -471,8 +471,11 @@ type Func struct {
// Marks records scope boundary changes. // Marks records scope boundary changes.
Marks []Mark Marks []Mark
Closgen int // Closgen tracks how many closures have been generated within
Outerfunc *Node // outer function (for closure) // this function. Used by closurename for creating unique
// function names.
Closgen int
FieldTrack map[*types.Sym]struct{} FieldTrack map[*types.Sym]struct{}
DebugInfo *ssa.FuncDebug DebugInfo *ssa.FuncDebug
Ntype *Node // signature Ntype *Node // signature
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment