mirror of
https://github.com/golang/go
synced 2024-11-02 11:50:30 +00:00
cmd/compile: emit itabs and itablinks
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>
This commit is contained in:
parent
7043d2bb5e
commit
f00bbd5f81
5 changed files with 66 additions and 6 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue