]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: slightly regularize interface method types
authorMatthew Dempsky <mdempsky@google.com>
Tue, 25 Oct 2016 23:25:57 +0000 (16:25 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 25 Oct 2016 23:54:41 +0000 (23:54 +0000)
Use a single *struct{} type instance rather than reconstructing one
for every declared/imported interface method. Minor allocations win:

name       old alloc/op    new alloc/op    delta
Template      41.8MB ± 0%     41.7MB ± 0%  -0.10%         (p=0.000 n=9+10)
Unicode       34.2MB ± 0%     34.2MB ± 0%    ~           (p=0.971 n=10+10)
GoTypes        123MB ± 0%      122MB ± 0%  -0.03%         (p=0.000 n=9+10)
Compiler       495MB ± 0%      495MB ± 0%  -0.01%        (p=0.000 n=10+10)

name       old allocs/op   new allocs/op   delta
Template        409k ± 0%       408k ± 0%  -0.13%        (p=0.000 n=10+10)
Unicode         354k ± 0%       354k ± 0%    ~           (p=0.516 n=10+10)
GoTypes        1.22M ± 0%      1.22M ± 0%  -0.03%        (p=0.009 n=10+10)
Compiler       4.43M ± 0%      4.43M ± 0%  -0.02%        (p=0.000 n=10+10)

Change-Id: Id3a4ca3dd09112bb96ccc982b06c9e79f661d31f
Reviewed-on: https://go-review.googlesource.com/32051
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/universe.go

index b16c9433ee53d59b73bf4c7d023560607ba3bf90..afe044acd6500e07c052cd49d8c8f033aa1264f5 100644 (file)
@@ -988,34 +988,30 @@ func embedded(s *Sym, pkg *Pkg) *Node {
        return n
 }
 
+// thisT is the singleton type used for interface method receivers.
+var thisT *Type
+
 func fakethis() *Node {
-       n := nod(ODCLFIELD, nil, typenod(ptrto(typ(TSTRUCT))))
-       return n
+       if thisT == nil {
+               thisT = ptrto(typ(TSTRUCT))
+       }
+       return nod(ODCLFIELD, nil, typenod(thisT))
 }
 
 func fakethisfield() *Field {
+       if thisT == nil {
+               thisT = ptrto(typ(TSTRUCT))
+       }
        f := newField()
-       f.Type = ptrto(typ(TSTRUCT))
+       f.Type = thisT
        return f
 }
 
 // Is this field a method on an interface?
-// Those methods have an anonymous *struct{} as the receiver.
+// Those methods have thisT as the receiver.
 // (See fakethis above.)
 func isifacemethod(f *Type) bool {
-       rcvr := f.Recv()
-       if rcvr.Sym != nil {
-               return false
-       }
-       t := rcvr.Type
-       if !t.IsPtr() {
-               return false
-       }
-       t = t.Elem()
-       if t.Sym != nil || !t.IsStruct() || t.NumFields() != 0 {
-               return false
-       }
-       return true
+       return f.Recv().Type == thisT
 }
 
 // turn a parsed function declaration into a type
index 6798a9a906c5cca30e2af90c748ac35e5e9c137e..30c9c3783af187cbefa9797e038f0c984691fdca 100644 (file)
@@ -374,32 +374,16 @@ func typeinit() {
 }
 
 func makeErrorInterface() *Type {
-       rcvr := typ(TSTRUCT)
-       rcvr.StructType().Funarg = FunargRcvr
        field := newField()
-       field.Type = ptrto(typ(TSTRUCT))
-       rcvr.SetFields([]*Field{field})
-
-       in := typ(TSTRUCT)
-       in.StructType().Funarg = FunargParams
-
-       out := typ(TSTRUCT)
-       out.StructType().Funarg = FunargResults
-       field = newField()
        field.Type = Types[TSTRING]
-       out.SetFields([]*Field{field})
-
-       f := typ(TFUNC)
-       f.FuncType().Receiver = rcvr
-       f.FuncType().Results = out
-       f.FuncType().Params = in
+       f := functypefield(fakethisfield(), nil, []*Field{field})
 
-       t := typ(TINTER)
        field = newField()
        field.Sym = lookup("Error")
        field.Type = f
-       t.SetFields([]*Field{field})
 
+       t := typ(TINTER)
+       t.SetFields([]*Field{field})
        return t
 }