]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: set itab function pointers at compile time
authorKeith Randall <khr@golang.org>
Tue, 30 May 2017 19:59:25 +0000 (12:59 -0700)
committerKeith Randall <khr@golang.org>
Tue, 15 Aug 2017 19:00:03 +0000 (19:00 +0000)
I noticed that we don't set an itab's function pointers at compile
time. Instead, we currently do it at executable startup.

Set the function pointers at compile time instead. This shortens
startup time. It has no effect on normal binary size. Object files
will have more relocations, but that isn't a big deal.

For PIE there are additional pointers that will need to be adjusted at
load time. There are already other pointers in an itab that need to be
adjusted, so the cache line will already be paged in. There might be
some binary size overhead to mark these pointers. The "go test -c
-buildmode=pie net/http" binary is 0.18% bigger.

Update #20505

Change-Id: I267c82489915b509ff66e512fc7319b2dd79b8f7
Reviewed-on: https://go-review.googlesource.com/44341
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
src/cmd/compile/internal/gc/reflect.go
src/runtime/iface.go
src/runtime/plugin.go

index e3d8b1537e0ec5e049d149efc6325b3d3921a566..a08ea0f73bd44248ab4b558e479bd304b16c3ec8 100644 (file)
@@ -1463,14 +1463,13 @@ func dumptabs() {
                // }
                o := dsymptr(i.lsym, 0, dtypesym(i.itype).Linksym(), 0)
                o = dsymptr(i.lsym, o, dtypesym(i.t).Linksym(), 0)
-               o = duint32(i.lsym, o, typehash(i.t))  // copy of type hash
-               o += 4                                 // skip unused field
-               o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
-               // at runtime the itab will contain pointers to types, other itabs and
-               // method functions. None are allocated on heap, so we can use obj.NOPTR.
-               ggloblsym(i.lsym, int32(o), int16(obj.DUPOK|obj.NOPTR))
-               // TODO: mark readonly after we pre-add the function pointers
-
+               o = duint32(i.lsym, o, typehash(i.t)) // copy of type hash
+               o += 4                                // skip unused field
+               for _, fn := range genfun(i.t, i.itype) {
+                       o = dsymptr(i.lsym, o, fn, 0) // method pointer for each method
+               }
+               // Nothing writes static itabs, so they are read only.
+               ggloblsym(i.lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
                ilink := itablinkpkg.Lookup(i.t.ShortString() + "," + i.itype.ShortString()).Linksym()
                dsymptr(ilink, 0, i.lsym, 0)
                ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
index 665dbdbc1655931ebb86dde8168bf351507107b2..1f31bcae6d493131fe1c0783e9bdd06e73f02eba 100644 (file)
@@ -167,13 +167,6 @@ func itabAdd(m *itab) {
        }
 }
 
-// Adds m to the set of initial itabs.
-// itabLock must be held.
-func itabAddStartup(m *itab) {
-       m.init() // TODO: remove after CL 44341
-       itabAdd(m)
-}
-
 // init fills in the m.fun array with all the code pointers for
 // the m.inter/m._type pair. If the type does not implement the interface,
 // it sets m.fun[0] to 0 and returns the name of an interface function that is missing.
@@ -230,7 +223,7 @@ func itabsinit() {
        lock(&itabLock)
        for _, md := range activeModules() {
                for _, i := range md.itablinks {
-                       itabAddStartup(i)
+                       itabAdd(i)
                }
        }
        unlock(&itabLock)
index 34b306ae2502c05ea535ffd9d1174629870fdee6..caecba67f84eb665406aae19823e92d78ab3a12c 100644 (file)
@@ -56,7 +56,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, mismatch
 
        lock(&itabLock)
        for _, i := range md.itablinks {
-               itabAddStartup(i)
+               itabAdd(i)
        }
        unlock(&itabLock)