mirror of
https://github.com/golang/go
synced 2024-09-20 16:32:42 +00:00
cmd/compile: allowing inlining of functions with OCALLPART
OCALLPART is exported in its original form, which is as an OXDOT. The body of the method value wrapper created in makepartialcall() was not being typechecked, and that was causing a problem during escape analysis, so I added code to typecheck the body. The go executable got slightly bigger with this change (13598111 -> 13598905), because of extra exported methods with OCALLPART (I believe), while the text size got slightly smaller (9686964 -> 9686643). This is mainly part of the work to make sure all function bodies can be exported (for purposes of generics), but might as well fix the OCALLPART inlining bug as well. Fixes #18493 Change-Id: If7aa055ff78ed7a6330c6a1e22f836ec567d04fd Reviewed-on: https://go-review.googlesource.com/c/go/+/263620 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
2754d91164
commit
8fe372c7b3
|
@ -434,6 +434,8 @@ func typecheckpartialcall(fn *Node, sym *types.Sym) {
|
||||||
fn.Type = xfunc.Type
|
fn.Type = xfunc.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
|
||||||
|
// for partial calls.
|
||||||
func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
||||||
rcvrtype := fn.Left.Type
|
rcvrtype := fn.Left.Type
|
||||||
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
||||||
|
@ -500,6 +502,10 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
||||||
funcbody()
|
funcbody()
|
||||||
|
|
||||||
xfunc = typecheck(xfunc, ctxStmt)
|
xfunc = typecheck(xfunc, ctxStmt)
|
||||||
|
// Need to typecheck the body of the just-generated wrapper.
|
||||||
|
// typecheckslice() requires that Curfn is set when processing an ORETURN.
|
||||||
|
Curfn = xfunc
|
||||||
|
typecheckslice(xfunc.Nbody.Slice(), ctxStmt)
|
||||||
sym.Def = asTypesNode(xfunc)
|
sym.Def = asTypesNode(xfunc)
|
||||||
xtop = append(xtop, xfunc)
|
xtop = append(xtop, xfunc)
|
||||||
Curfn = savecurfn
|
Curfn = savecurfn
|
||||||
|
|
|
@ -1266,8 +1266,13 @@ func (w *exportWriter) expr(n *Node) {
|
||||||
// case OSTRUCTKEY:
|
// case OSTRUCTKEY:
|
||||||
// unreachable - handled in case OSTRUCTLIT by elemList
|
// unreachable - handled in case OSTRUCTLIT by elemList
|
||||||
|
|
||||||
// case OCALLPART:
|
case OCALLPART:
|
||||||
// unimplemented - handled by default case
|
// An OCALLPART is an OXDOT before type checking.
|
||||||
|
w.op(OXDOT)
|
||||||
|
w.pos(n.Pos)
|
||||||
|
w.expr(n.Left)
|
||||||
|
// Right node should be ONAME
|
||||||
|
w.selector(n.Right.Sym)
|
||||||
|
|
||||||
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
||||||
w.op(OXDOT)
|
w.op(OXDOT)
|
||||||
|
|
|
@ -866,7 +866,7 @@ func (r *importReader) node() *Node {
|
||||||
// unreachable - handled in case OSTRUCTLIT by elemList
|
// unreachable - handled in case OSTRUCTLIT by elemList
|
||||||
|
|
||||||
// case OCALLPART:
|
// case OCALLPART:
|
||||||
// unimplemented
|
// unreachable - mapped to case OXDOT below by exporter
|
||||||
|
|
||||||
// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
||||||
// unreachable - mapped to case OXDOT below by exporter
|
// unreachable - mapped to case OXDOT below by exporter
|
||||||
|
|
|
@ -374,8 +374,10 @@ func (v *hairyVisitor) visit(n *Node) bool {
|
||||||
v.reason = "call to recover"
|
v.reason = "call to recover"
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case OCALLPART:
|
||||||
|
// OCALLPART is inlineable, but no extra cost to the budget
|
||||||
|
|
||||||
case OCLOSURE,
|
case OCLOSURE,
|
||||||
OCALLPART,
|
|
||||||
ORANGE,
|
ORANGE,
|
||||||
OSELECT,
|
OSELECT,
|
||||||
OTYPESW,
|
OTYPESW,
|
||||||
|
@ -454,7 +456,7 @@ func inlcopy(n *Node) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
m := n.copy()
|
m := n.copy()
|
||||||
if m.Func != nil {
|
if n.Op != OCALLPART && m.Func != nil {
|
||||||
Fatalf("unexpected Func: %v", m)
|
Fatalf("unexpected Func: %v", m)
|
||||||
}
|
}
|
||||||
m.Left = inlcopy(n.Left)
|
m.Left = inlcopy(n.Left)
|
||||||
|
|
|
@ -229,3 +229,20 @@ Loop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #18493 - make sure we can do inlining of functions with a method value
|
||||||
|
type T1 struct{}
|
||||||
|
|
||||||
|
func (a T1) meth(val int) int { // ERROR "can inline T1.meth" "inlining call to T1.meth"
|
||||||
|
return val + 5
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth"
|
||||||
|
return t1.meth // ERROR "t1.meth escapes to heap"
|
||||||
|
}
|
||||||
|
|
||||||
|
func ii() { // ERROR "can inline ii"
|
||||||
|
var t1 T1
|
||||||
|
f := getMeth(t1) // ERROR "inlining call to getMeth" "t1.meth does not escape"
|
||||||
|
_ = f(3)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue