]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: allowing inlining of functions with OCALLPART
authorDan Scales <danscales@google.com>
Mon, 19 Oct 2020 20:09:55 +0000 (13:09 -0700)
committerDan Scales <danscales@google.com>
Tue, 20 Oct 2020 00:07:42 +0000 (00:07 +0000)
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>
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/inl.go
test/inline.go

index 250be38e5bf9f470fcf698a840d297fdb939ce31..5d1012111fc78ae5c9d983d9ba093902ab9dbebd 100644 (file)
@@ -434,6 +434,8 @@ func typecheckpartialcall(fn *Node, sym *types.Sym) {
        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 {
        rcvrtype := fn.Left.Type
        sym := methodSymSuffix(rcvrtype, meth, "-fm")
@@ -500,6 +502,10 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
        funcbody()
 
        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)
        xtop = append(xtop, xfunc)
        Curfn = savecurfn
index df08a4a6c20185817bd216c895698336ae82ddda..9bc1f64600d6e379c6b59eecad94cc4db7ff4351 100644 (file)
@@ -1266,8 +1266,13 @@ func (w *exportWriter) expr(n *Node) {
        // case OSTRUCTKEY:
        //      unreachable - handled in case OSTRUCTLIT by elemList
 
-       // case OCALLPART:
-       //      unimplemented - handled by default case
+       case OCALLPART:
+               // 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:
                w.op(OXDOT)
index 5f107eeec7e49613f938c5e5f25bc12abfe03101..107e96cc6adc13926442a92f6a100fc44554d284 100644 (file)
@@ -866,7 +866,7 @@ func (r *importReader) node() *Node {
        //      unreachable - handled in case OSTRUCTLIT by elemList
 
        // case OCALLPART:
-       //      unimplemented
+       //      unreachable - mapped to case OXDOT below by exporter
 
        // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
        //      unreachable - mapped to case OXDOT below by exporter
index ba12cf40b51ba7d4fc1ab5e2d743b09f96c20648..55a14d378e02fbf559031976bb861d134f0937ee 100644 (file)
@@ -374,8 +374,10 @@ func (v *hairyVisitor) visit(n *Node) bool {
                v.reason = "call to recover"
                return true
 
+       case OCALLPART:
+               // OCALLPART is inlineable, but no extra cost to the budget
+
        case OCLOSURE,
-               OCALLPART,
                ORANGE,
                OSELECT,
                OTYPESW,
@@ -454,7 +456,7 @@ func inlcopy(n *Node) *Node {
        }
 
        m := n.copy()
-       if m.Func != nil {
+       if n.Op != OCALLPART && m.Func != nil {
                Fatalf("unexpected Func: %v", m)
        }
        m.Left = inlcopy(n.Left)
index 0e41873de4ba5e3fed3ea2d2ac0d144f61a12a6e..9b75bc5065863aec4334d2087a17622d22ae85c5 100644 (file)
@@ -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)
+}