summaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/gc/escape.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/gc/escape.go')
-rw-r--r--src/cmd/compile/internal/gc/escape.go80
1 files changed, 35 insertions, 45 deletions
diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go
index 351643ef5d..4bddb7f0f4 100644
--- a/src/cmd/compile/internal/gc/escape.go
+++ b/src/cmd/compile/internal/gc/escape.go
@@ -87,7 +87,7 @@ type Escape struct {
allLocs []*EscLocation
labels map[*types.Sym]labelState // known labels
- curfn ir.Node
+ curfn *ir.Func
// loopDepth counts the current loop nesting depth within
// curfn. It increments within each "for" loop and at each
@@ -103,7 +103,7 @@ type Escape struct {
// variable.
type EscLocation struct {
n ir.Node // represented variable or expression, if any
- curfn ir.Node // enclosing function
+ curfn *ir.Func // enclosing function
edges []EscEdge // incoming edges
loopDepth int // loopDepth at declaration
@@ -180,7 +180,7 @@ func escFmt(n ir.Node, short bool) string {
// escapeFuncs performs escape analysis on a minimal batch of
// functions.
-func escapeFuncs(fns []ir.Node, recursive bool) {
+func escapeFuncs(fns []*ir.Func, recursive bool) {
for _, fn := range fns {
if fn.Op() != ir.ODCLFUNC {
base.Fatalf("unexpected node: %v", fn)
@@ -203,8 +203,8 @@ func escapeFuncs(fns []ir.Node, recursive bool) {
e.finish(fns)
}
-func (e *Escape) initFunc(fn ir.Node) {
- if fn.Op() != ir.ODCLFUNC || fn.Esc() != EscFuncUnknown {
+func (e *Escape) initFunc(fn *ir.Func) {
+ if fn.Esc() != EscFuncUnknown {
base.Fatalf("unexpected node: %v", fn)
}
fn.SetEsc(EscFuncPlanned)
@@ -216,14 +216,14 @@ func (e *Escape) initFunc(fn ir.Node) {
e.loopDepth = 1
// Allocate locations for local variables.
- for _, dcl := range fn.Func().Dcl {
+ for _, dcl := range fn.Dcl {
if dcl.Op() == ir.ONAME {
e.newLoc(dcl, false)
}
}
}
-func (e *Escape) walkFunc(fn ir.Node) {
+func (e *Escape) walkFunc(fn *ir.Func) {
fn.SetEsc(EscFuncStarted)
// Identify labels that mark the head of an unstructured loop.
@@ -589,7 +589,8 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
for i := m.Type.NumResults(); i > 0; i-- {
ks = append(ks, e.heapHole())
}
- paramK := e.tagHole(ks, ir.AsNode(m.Nname), m.Type.Recv())
+ name, _ := m.Nname.(*ir.Name)
+ paramK := e.tagHole(ks, name, m.Type.Recv())
e.expr(e.teeHole(paramK, closureK), n.Left())
@@ -633,17 +634,13 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
k = e.spill(k, n)
// Link addresses of captured variables to closure.
- for _, v := range n.Func().ClosureVars.Slice() {
- if v.Op() == ir.OXXX { // unnamed out argument; see dcl.go:/^funcargs
- continue
- }
-
+ for _, v := range n.Func().ClosureVars {
k := k
- if !v.Name().Byval() {
+ if !v.Byval() {
k = k.addr(v, "reference")
}
- e.expr(k.note(n, "captured by a closure"), v.Name().Defn)
+ e.expr(k.note(n, "captured by a closure"), v.Defn)
}
case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR:
@@ -813,12 +810,12 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) {
fixVariadicCall(call)
// Pick out the function callee, if statically known.
- var fn ir.Node
+ var fn *ir.Name
switch call.Op() {
case ir.OCALLFUNC:
switch v := staticValue(call.Left()); {
case v.Op() == ir.ONAME && v.Class() == ir.PFUNC:
- fn = v
+ fn = v.(*ir.Name)
case v.Op() == ir.OCLOSURE:
fn = v.Func().Nname
}
@@ -902,7 +899,7 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) {
// ks should contain the holes representing where the function
// callee's results flows. fn is the statically-known callee function,
// if any.
-func (e *Escape) tagHole(ks []EscHole, fn ir.Node, param *types.Field) EscHole {
+func (e *Escape) tagHole(ks []EscHole, fn *ir.Name, param *types.Field) EscHole {
// If this is a dynamic call, we can't rely on param.Note.
if fn == nil {
return e.heapHole()
@@ -943,9 +940,9 @@ func (e *Escape) tagHole(ks []EscHole, fn ir.Node, param *types.Field) EscHole {
// fn has not yet been analyzed, so its parameters and results
// should be incorporated directly into the flow graph instead of
// relying on its escape analysis tagging.
-func (e *Escape) inMutualBatch(fn ir.Node) bool {
- if fn.Name().Defn != nil && fn.Name().Defn.Esc() < EscFuncTagged {
- if fn.Name().Defn.Esc() == EscFuncUnknown {
+func (e *Escape) inMutualBatch(fn *ir.Name) bool {
+ if fn.Defn != nil && fn.Defn.Esc() < EscFuncTagged {
+ if fn.Defn.Esc() == EscFuncUnknown {
base.Fatalf("graph inconsistency")
}
return true
@@ -1368,7 +1365,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool {
//
// var u int // okay to stack allocate
// *(func() *int { return &u }()) = 42
- if containsClosure(other.curfn, l.curfn) && l.curfn.Func().ClosureCalled {
+ if containsClosure(other.curfn, l.curfn) && l.curfn.ClosureCalled() {
return false
}
@@ -1402,11 +1399,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool {
}
// containsClosure reports whether c is a closure contained within f.
-func containsClosure(f, c ir.Node) bool {
- if f.Op() != ir.ODCLFUNC || c.Op() != ir.ODCLFUNC {
- base.Fatalf("bad containsClosure: %v, %v", f, c)
- }
-
+func containsClosure(f, c *ir.Func) bool {
// Common case.
if f == c {
return false
@@ -1414,8 +1407,8 @@ func containsClosure(f, c ir.Node) bool {
// Closures within function Foo are named like "Foo.funcN..."
// TODO(mdempsky): Better way to recognize this.
- fn := f.Func().Nname.Sym().Name
- cn := c.Func().Nname.Sym().Name
+ fn := f.Sym().Name
+ cn := c.Sym().Name
return len(cn) > len(fn) && cn[:len(fn)] == fn && cn[len(fn)] == '.'
}
@@ -1437,7 +1430,7 @@ func (l *EscLocation) leakTo(sink *EscLocation, derefs int) {
l.paramEsc.AddHeap(derefs)
}
-func (e *Escape) finish(fns []ir.Node) {
+func (e *Escape) finish(fns []*ir.Func) {
// Record parameter tags for package export data.
for _, fn := range fns {
fn.SetEsc(EscFuncTagged)
@@ -1614,12 +1607,12 @@ const (
EscNever // By construction will not escape.
)
-// funcSym returns fn.Func.Nname.Sym if no nils are encountered along the way.
-func funcSym(fn ir.Node) *types.Sym {
- if fn == nil || fn.Func().Nname == nil {
+// funcSym returns fn.Nname.Sym if no nils are encountered along the way.
+func funcSym(fn *ir.Func) *types.Sym {
+ if fn == nil || fn.Nname == nil {
return nil
}
- return fn.Func().Nname.Sym()
+ return fn.Sym()
}
// Mark labels that have no backjumps to them as not increasing e.loopdepth.
@@ -1798,6 +1791,7 @@ func addrescapes(n ir.Node) {
// Nothing to do.
case ir.ONAME:
+ n := n.(*ir.Name)
if n == nodfp {
break
}
@@ -1832,10 +1826,6 @@ func addrescapes(n ir.Node) {
// heap in f, not in the inner closure. Flip over to f before calling moveToHeap.
oldfn := Curfn
Curfn = n.Name().Curfn
- if Curfn.Op() == ir.OCLOSURE {
- Curfn = Curfn.Func().Decl
- panic("can't happen")
- }
ln := base.Pos
base.Pos = Curfn.Pos()
moveToHeap(n)
@@ -1855,7 +1845,7 @@ func addrescapes(n ir.Node) {
}
// moveToHeap records the parameter or local variable n as moved to the heap.
-func moveToHeap(n ir.Node) {
+func moveToHeap(n *ir.Name) {
if base.Flag.LowerR != 0 {
ir.Dump("MOVE", n)
}
@@ -1877,7 +1867,7 @@ func moveToHeap(n ir.Node) {
// Unset AutoTemp to persist the &foo variable name through SSA to
// liveness analysis.
// TODO(mdempsky/drchase): Cleaner solution?
- heapaddr.Name().SetAutoTemp(false)
+ heapaddr.SetAutoTemp(false)
// Parameters have a local stack copy used at function start/end
// in addition to the copy in the heap that may live longer than
@@ -1895,14 +1885,14 @@ func moveToHeap(n ir.Node) {
stackcopy.SetType(n.Type())
stackcopy.SetOffset(n.Offset())
stackcopy.SetClass(n.Class())
- stackcopy.Name().Heapaddr = heapaddr
+ stackcopy.Heapaddr = heapaddr
if n.Class() == ir.PPARAMOUT {
// Make sure the pointer to the heap copy is kept live throughout the function.
// The function could panic at any point, and then a defer could recover.
// Thus, we need the pointer to the heap copy always available so the
// post-deferreturn code can copy the return value back to the stack.
// See issue 16095.
- heapaddr.Name().SetIsOutputParamHeapAddr(true)
+ heapaddr.SetIsOutputParamHeapAddr(true)
}
n.Name().Stackcopy = stackcopy
@@ -1910,9 +1900,9 @@ func moveToHeap(n ir.Node) {
// liveness and other analyses use the underlying stack slot
// and not the now-pseudo-variable n.
found := false
- for i, d := range Curfn.Func().Dcl {
+ for i, d := range Curfn.Dcl {
if d == n {
- Curfn.Func().Dcl[i] = stackcopy
+ Curfn.Dcl[i] = stackcopy
found = true
break
}
@@ -1925,7 +1915,7 @@ func moveToHeap(n ir.Node) {
if !found {
base.Fatalf("cannot find %v in local variable list", n)
}
- Curfn.Func().Dcl = append(Curfn.Func().Dcl, n)
+ Curfn.Dcl = append(Curfn.Dcl, n)
}
// Modify n in place so that uses of n now mean indirection of the heapaddr.