From d89b70d43357e7f016331356014253647af02971 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 25 Oct 2016 16:25:57 -0700 Subject: [PATCH] cmd/compile: slightly regularize interface method types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/cmd/compile/internal/gc/dcl.go | 30 +++++++++++-------------- src/cmd/compile/internal/gc/universe.go | 22 +++--------------- 2 files changed, 16 insertions(+), 36 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index b16c9433ee..afe044acd6 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -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 diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 6798a9a906..30c9c3783a 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -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 := functypefield(fakethisfield(), nil, []*Field{field}) - f := typ(TFUNC) - f.FuncType().Receiver = rcvr - f.FuncType().Results = out - f.FuncType().Params = in - - 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 }