]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: emit itabs and itablinks
authorMichel Lespinasse <walken@google.com>
Thu, 17 Mar 2016 13:18:13 +0000 (06:18 -0700)
committerMichel Lespinasse <walken@google.com>
Tue, 29 Mar 2016 02:18:03 +0000 (02:18 +0000)
See #14874

This change tells the compiler to emit itab and itablink symbols in
situations where they could be useful; however the compiled code does
not actually make use of the new symbols yet.

Change-Id: I0db3e6ec0cb1f3b7cebd4c60229e4a48372fe586
Reviewed-on: https://go-review.googlesource.com/20888
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: Michel Lespinasse <walken@google.com>

src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/walk.go
src/runtime/runtime2.go

index 448a0fd3222036e0b6cd72ebf7d91a60154a1191..5925208514bf04b91639e9fad9e0b328a0664bf3 100644 (file)
@@ -250,6 +250,10 @@ var importpkg *Pkg // package being imported
 
 var itabpkg *Pkg // fake pkg for itab cache
 
+var itab2pkg *Pkg // fake pkg for itab entries
+
+var itablinkpkg *Pkg // fake package for runtime itab entries
+
 var Runtimepkg *Pkg // package runtime
 
 var racepkg *Pkg // package runtime/race
index 09b433d7f2b6f630df49ecb4390a355954cea864..5c5e5acdff65600a32d87a0dbb3f2c139473c693 100644 (file)
@@ -124,14 +124,21 @@ func Main() {
 
        // pseudo-packages used in symbol tables
        itabpkg = mkpkg("go.itab")
-
        itabpkg.Name = "go.itab"
        itabpkg.Prefix = "go.itab" // not go%2eitab
 
+       itab2pkg = mkpkg("go.itab2")
+       itab2pkg.Name = "go.itab2"
+       itab2pkg.Prefix = "go.itab2" // not go%2eitab2
+
        typelinkpkg = mkpkg("go.typelink")
        typelinkpkg.Name = "go.typelink"
        typelinkpkg.Prefix = "go.typelink" // not go%2etypelink
 
+       itablinkpkg = mkpkg("go.itablink")
+       itablinkpkg.Name = "go.itablink"
+       itablinkpkg.Prefix = "go.itablink" // not go%2eitablink
+
        trackpkg = mkpkg("go.track")
 
        trackpkg.Name = "go.track"
index 4239d4068a9e31ecfa4095f931ee25a3256d2dbd..ecf98b93880f2cdd34a08a3080183629bce1c23c 100644 (file)
@@ -13,8 +13,14 @@ import (
        "strings"
 )
 
+type itabEntry struct {
+       t, itype *Type
+       sym      *Sym
+}
+
 // runtime interface and reflection data structures
 var signatlist []*Node
+var itabs []itabEntry
 
 // byMethodNameAndPackagePath sorts method signatures by name, then package path.
 type byMethodNameAndPackagePath []*Sig
@@ -919,13 +925,9 @@ func typenamesym(t *Type) *Sym {
        }
        s := typesym(t)
        if s.Def == nil {
-               n := Nod(ONAME, nil, nil)
-               n.Sym = s
+               n := newname(s)
                n.Type = Types[TUINT8]
-               n.Addable = true
-               n.Ullman = 1
                n.Class = PEXTERN
-               n.Xoffset = 0
                n.Typecheck = 1
                s.Def = n
 
@@ -945,6 +947,23 @@ func typename(t *Type) *Node {
        return n
 }
 
+func itabnamesym(t, itype *Type) *Sym {
+       if t == nil || (Isptr[t.Etype] && t.Type == nil) || isideal(t) {
+               Fatalf("itabname %v", t)
+       }
+       s := Pkglookup(Tconv(t, FmtLeft)+","+Tconv(itype, FmtLeft), itab2pkg)
+       if s.Def == nil {
+               n := newname(s)
+               n.Type = Types[TUINT8]
+               n.Class = PEXTERN
+               n.Typecheck = 1
+               s.Def = n
+
+               itabs = append(itabs, itabEntry{t: t, itype: itype, sym: s})
+       }
+       return s.Def.Sym
+}
+
 // isreflexive reports whether t has a reflexive equality operator.
 // That is, if x==x for all x of type t.
 func isreflexive(t *Type) bool {
@@ -1320,6 +1339,30 @@ func dumptypestructs() {
                }
        }
 
+       // process itabs
+       for _, i := range itabs {
+               // dump empty itab symbol into i.sym
+               // type itab struct {
+               //   inter  *interfacetype
+               //   _type  *_type
+               //   link   *itab
+               //   bad    int32
+               //   unused int32
+               //   fun    [1]uintptr // variable sized
+               // }
+               o := dsymptr(i.sym, 0, dtypesym(i.itype), 0)
+               o = dsymptr(i.sym, o, dtypesym(i.t), 0)
+               o += Widthptr + 8                      // skip link/bad/unused fields
+               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.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
+
+               ilink := Pkglookup(Tconv(i.t, FmtLeft)+","+Tconv(i.itype, FmtLeft), itablinkpkg)
+               dsymptr(ilink, 0, i.sym, 0)
+               ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
+       }
+
        // generate import strings for imported packages
        for _, p := range pkgs {
                if p.Direct {
index 6d077d5890b3f03d1c27aa36530e6ca55e710b28..90ed401a43f097e927abfc8358b451e10bd509d8 100644 (file)
@@ -996,6 +996,10 @@ opswitch:
                        break
                }
 
+               if isdirectiface(n.Left.Type) {
+                       itabnamesym(n.Left.Type, n.Type)
+               }
+
                var ll []*Node
                if !Isinter(n.Left.Type) {
                        ll = append(ll, typename(n.Left.Type))
index a54dc552c1f15b593abd29b0b5455e6c6da48f8d..e1b1c83453233946379c016c5cebc0122f0ef15e 100644 (file)
@@ -577,6 +577,8 @@ type _func struct {
 
 // layout of Itab known to compilers
 // allocated in non-garbage-collected memory
+// Needs to be in sync with
+// ../cmd/compile/internal/gc/reflect.go:/^func.dumptypestructs.
 type itab struct {
        inter  *interfacetype
        _type  *_type