]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't copy all type nodes for builtin functions
authorIan Lance Taylor <iant@golang.org>
Fri, 11 Mar 2016 21:04:07 +0000 (13:04 -0800)
committerIan Lance Taylor <iant@golang.org>
Sat, 12 Mar 2016 00:30:44 +0000 (00:30 +0000)
Only copy the ones that actually change.  Also combine deep and substAny
functions into one.  The Type.Copyany field is now unused, so remove it.

Passes toolstash -cmp.

Change-Id: Id28a9bf144ecf3e522aad00496f8a21ae2b74680
Reviewed-on: https://go-review.googlesource.com/20600
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/type.go

index ff4d4409ea7c4a68f500d994317bae792b3fe428..9300df0da280c05553ec90d6174e3c4756627c90 100644 (file)
@@ -1078,51 +1078,91 @@ func substArgTypes(np **Node, types ...*Type) {
        for _, t := range types {
                dowidth(t)
        }
-       n.Type = deep(n.Type)
-       substAny(&n.Type, &types)
+       n.Type = substAny(n.Type, &types)
        if len(types) > 0 {
                Fatalf("substArgTypes: too many argument types")
        }
 }
 
-// substAny walks *tp, replacing instances of "any" with successive
-// elements removed from types.
-func substAny(tp **Type, types *[]*Type) {
-       for {
-               t := *tp
-               if t == nil {
-                       return
-               }
-               if t.Etype == TANY && t.Copyany {
-                       if len(*types) == 0 {
-                               Fatalf("substArgTypes: not enough argument types")
-                       }
-                       *tp = (*types)[0]
-                       *types = (*types)[1:]
+// substAny walks t, replacing instances of "any" with successive
+// elements removed from types.  It returns the substituted type.
+func substAny(t *Type, types *[]*Type) *Type {
+       if t == nil {
+               return nil
+       }
+
+       switch t.Etype {
+       default:
+               // Leave the type unchanged.
+
+       case TANY:
+               if len(*types) == 0 {
+                       Fatalf("substArgTypes: not enough argument types")
                }
+               t = (*types)[0]
+               *types = (*types)[1:]
 
-               switch t.Etype {
-               case TPTR32, TPTR64, TCHAN, TARRAY:
-                       tp = &t.Type
-                       continue
+       case TPTR32, TPTR64, TCHAN, TARRAY, TFIELD:
+               elem := substAny(t.Type, types)
+               if elem != t.Type {
+                       t = t.Copy()
+                       t.Type = elem
+               }
 
-               case TMAP:
-                       substAny(&t.Down, types)
-                       tp = &t.Type
-                       continue
+       case TMAP:
+               key := substAny(t.Down, types)
+               val := substAny(t.Type, types)
+               if key != t.Down || val != t.Type {
+                       t = t.Copy()
+                       t.Down = key
+                       t.Type = val
+               }
 
-               case TFUNC:
-                       substAny(t.RecvsP(), types)
-                       substAny(t.ParamsP(), types)
-                       substAny(t.ResultsP(), types)
+       case TFUNC:
+               recvs := substAny(t.Recvs(), types)
+               params := substAny(t.Params(), types)
+               results := substAny(t.Results(), types)
+               if recvs != t.Recvs() || params != t.Params() || results != t.Results() {
+                       // Note that this code has to be aware of the
+                       // representation underlying Recvs/Results/Params.
+                       if recvs == t.Recvs() {
+                               recvs = recvs.Copy()
+                       }
+                       if results == t.Results() {
+                               results = results.Copy()
+                       }
+                       t = t.Copy()
+                       *t.RecvsP() = recvs
+                       *t.ResultsP() = results
+                       *t.ParamsP() = params
+               }
 
-               case TSTRUCT:
-                       for t, it := IterFields(t); t != nil; t = it.Next() {
-                               substAny(&t.Type, types)
+       case TSTRUCT:
+               // nfs only has to be big enough for the builtin functions.
+               var nfs [8]*Type
+               fields := t.FieldSlice()
+               changed := false
+               for i, f := range fields {
+                       nf := substAny(f, types)
+                       if nf != f {
+                               if !changed {
+                                       for j := 0; j < i; j++ {
+                                               nfs[j] = fields[j].Copy()
+                                       }
+                               }
+                               changed = true
+                       } else if changed {
+                               nf = f.Copy()
                        }
+                       nfs[i] = nf
+               }
+               if changed {
+                       t = t.Copy()
+                       t.SetFields(nfs[:len(fields)])
                }
-               return
        }
+
+       return t
 }
 
 // Is this a 64-bit type?
@@ -1166,50 +1206,6 @@ func Noconv(t1 *Type, t2 *Type) bool {
        return false
 }
 
-func deep(t *Type) *Type {
-       if t == nil {
-               return nil
-       }
-
-       var nt *Type
-       switch t.Etype {
-       default:
-               nt = t // share from here down
-
-       case TANY:
-               nt = t.Copy()
-               nt.Copyany = true
-
-       case TPTR32, TPTR64, TCHAN, TARRAY:
-               nt = t.Copy()
-               nt.Type = deep(t.Type)
-
-       case TMAP:
-               nt = t.Copy()
-               nt.Down = deep(t.Down)
-               nt.Type = deep(t.Type)
-
-       case TFUNC:
-               nt = t.Copy()
-               *nt.RecvsP() = deep(t.Recvs())
-               *nt.ResultsP() = deep(t.Results())
-               *nt.ParamsP() = deep(t.Params())
-
-       case TSTRUCT:
-               nt = t.Copy()
-               nt.Type = t.Type.Copy()
-               xt := nt.Type
-
-               for t, it := IterFields(t); t != nil; t = it.Next() {
-                       xt.Type = deep(t.Type)
-                       xt.Down = t.Down.Copy()
-                       xt = xt.Down
-               }
-       }
-
-       return nt
-}
-
 func syslook(name string) *Node {
        s := Pkglookup(name, Runtimepkg)
        if s == nil || s.Def == nil {
index e5e12f0bb8f3a8ef73cf39039fdb19454128c16e..a8b52201a3dca03f3475b8f3c6a730556c8c5fdc 100644 (file)
@@ -110,8 +110,7 @@ type Type struct {
        Printed     bool
        Embedded    uint8 // TFIELD embedded type
        Funarg      bool  // on TSTRUCT and TFIELD
-       Copyany     bool
-       Local       bool // created in this file
+       Local       bool  // created in this file
        Deferwidth  bool
        Broke       bool // broken type definition.
        Isddd       bool // TFIELD is ... argument