]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: escape analysis of method expression calls
authorMatthew Dempsky <mdempsky@google.com>
Wed, 23 Jun 2021 07:31:16 +0000 (00:31 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 23 Jun 2021 16:48:23 +0000 (16:48 +0000)
This CL extends escape analysis to analyze function calls using method
expressions the same as it would a normal method call. That is, it now
analyzes "T.M(recv, args...)" the same as "recv.M(args...)".

This is useful because it means the frontend can eventually stop
supporting both function calls and method calls. We can simply desugar
method calls into function calls, like we already do in the backend to
simplify SSA construction.

Change-Id: I9cd5ec0d534cbcd9860f0014c86e4ae416920c26
Reviewed-on: https://go-review.googlesource.com/c/go/+/330331
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/escape/call.go
test/escape5.go

index 7b9dbe0dbc6b104783b46c71282a80b00e8c45e2..850b9cbde28346db40b9d2c1a5cfb05c13a8053a 100644 (file)
@@ -56,11 +56,15 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
                var fn *ir.Name
                switch call.Op() {
                case ir.OCALLFUNC:
-                       switch v := ir.StaticValue(call.X); {
-                       case v.Op() == ir.ONAME && v.(*ir.Name).Class == ir.PFUNC:
-                               fn = v.(*ir.Name)
-                       case v.Op() == ir.OCLOSURE:
+                       switch v := ir.StaticValue(call.X); v.Op() {
+                       case ir.ONAME:
+                               if v := v.(*ir.Name); v.Class == ir.PFUNC {
+                                       fn = v
+                               }
+                       case ir.OCLOSURE:
                                fn = v.(*ir.ClosureExpr).Func.Nname
+                       case ir.OMETHEXPR:
+                               fn = ir.MethodExprName(v)
                        }
                case ir.OCALLMETH:
                        fn = ir.MethodExprName(call.X)
@@ -77,19 +81,30 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
                        }
                }
 
-               if r := fntype.Recv(); r != nil {
-                       dot := call.X.(*ir.SelectorExpr)
-                       argumentFunc(fn, e.tagHole(ks, fn, r), &dot.X)
-               } else {
+               var recvp *ir.Node
+               if call.Op() == ir.OCALLFUNC {
                        // Evaluate callee function expression.
                        //
-                       // Note: We use argument and not argumentFunc, because call.X
-                       // here may be an argument to runtime.{new,defer}proc, but it's
-                       // not an argument to fn itself.
+                       // Note: We use argument and not argumentFunc, because while
+                       // call.X here may be an argument to runtime.{new,defer}proc,
+                       // it's not an argument to fn itself.
                        argument(e.discardHole(), &call.X)
+               } else {
+                       recvp = &call.X.(*ir.SelectorExpr).X
                }
 
                args := call.Args
+               if recv := fntype.Recv(); recv != nil {
+                       if recvp == nil {
+                               // Function call using method expression. Recevier argument is
+                               // at the front of the regular arguments list.
+                               recvp = &args[0]
+                               args = args[1:]
+                       }
+
+                       argumentFunc(fn, e.tagHole(ks, fn, recv), recvp)
+               }
+
                for i, param := range fntype.Params().FieldSlice() {
                        argumentFunc(fn, e.tagHole(ks, fn, param), &args[i])
                }
index 73acfb46a94af6070dcfdcf0d0df531e82d8309e..97aaf23b2d124df2125c1caceaeb140f150e58ec 100644 (file)
@@ -180,8 +180,7 @@ func _() {
 }
 
 func fbad24305() {
-       // BAD u should not be heap allocated
-       var u U // ERROR "moved to heap: u"
+       var u U
        (*U).M(&u)
        (*U).N(&u)
 }