1
0
mirror of https://github.com/golang/go synced 2024-11-26 15:46:54 -07:00

[dev.regabi] cmd/compile: use ClosureVars for method value wrappers

Similar to with regular closures, we can change method value wrappers
to use ClosureVars and allow SSA construction to take care of wiring
it up appropriately.

Change-Id: I05c0b1bcec4e24305324755df35b7bc5b8a6ce7a
Reviewed-on: https://go-review.googlesource.com/c/go/+/281353
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Matthew Dempsky 2021-01-04 02:24:48 -08:00
parent 950cf4d46c
commit c9c26d7ffb
3 changed files with 16 additions and 16 deletions

View File

@ -583,6 +583,9 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
if n.Class == ir.PFUNC || n.Class == ir.PEXTERN {
return
}
if n.IsClosureVar() && n.Defn == nil {
return // ".this" from method value wrapper
}
e.flow(k, e.oldLoc(n))
case ir.ONAMEOFFSET:

View File

@ -264,7 +264,7 @@ const (
nameNeedzero // if it contains pointers, needs to be zeroed on function entry
nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap)
nameUsed // for variable declared and not used error
nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn
nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original (if any) at n.Defn
nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy
nameAddrtaken // address taken, even if not moved to heap
nameInlFormal // PAUTO created by inliner, derived from callee formal
@ -332,7 +332,7 @@ func (n *Name) SetVal(v constant.Value) {
// it appears in the function that immediately contains the
// declaration. Otherwise, Canonical simply returns n itself.
func (n *Name) Canonical() *Name {
if n.IsClosureVar() {
if n.IsClosureVar() && n.Defn != nil {
n = n.Defn.(*Name)
}
return n

View File

@ -246,29 +246,26 @@ func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func {
fn.SetWrapper(true)
// Declare and initialize variable holding receiver.
cr := ir.NewClosureRead(rcvrtype, types.Rnd(int64(types.PtrSize), int64(rcvrtype.Align)))
var ptr *ir.Name
var body []ir.Node
if rcvrtype.IsPtr() || rcvrtype.IsInterface() {
ptr = Temp(rcvrtype)
body = append(body, ir.NewAssignStmt(base.Pos, ptr, cr))
} else {
ptr = Temp(types.NewPtr(rcvrtype))
body = append(body, ir.NewAssignStmt(base.Pos, ptr, NodAddr(cr)))
}
ptr := ir.NewNameAt(base.Pos, Lookup(".this"))
ptr.Class = ir.PAUTOHEAP
ptr.SetType(rcvrtype)
ptr.Curfn = fn
ptr.SetIsClosureVar(true)
ptr.SetByval(true)
fn.ClosureVars = append(fn.ClosureVars, ptr)
call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil)
call.Args = ir.ParamNames(tfn.Type())
call.IsDDD = tfn.Type().IsVariadic()
var body ir.Node = call
if t0.NumResults() != 0 {
ret := ir.NewReturnStmt(base.Pos, nil)
ret.Results = []ir.Node{call}
body = append(body, ret)
} else {
body = append(body, call)
body = ret
}
fn.Body = body
fn.Body = []ir.Node{body}
FinishFuncBody()
Func(fn)