mirror of
https://github.com/golang/go
synced 2024-11-11 23:10:23 -07:00
runtime: insert itabs into hash table during init
See #14874 This change makes the runtime register all compiler generated itabs (as obtained from the moduledata) during init. Change-Id: I9969a0985b99b8bda820a631f7fe4c78f1174cdf Reviewed-on: https://go-review.googlesource.com/20900 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Michel Lespinasse <walken@google.com>
This commit is contained in:
parent
deb83d0639
commit
7043d2bb5e
@ -19,25 +19,28 @@ var (
|
||||
hash [hashSize]*itab
|
||||
)
|
||||
|
||||
func itabhash(inter *interfacetype, typ *_type) uint32 {
|
||||
// compiler has provided some good hash codes for us.
|
||||
h := inter.typ.hash
|
||||
h += 17 * typ.hash
|
||||
// TODO(rsc): h += 23 * x.mhash ?
|
||||
return h % hashSize
|
||||
}
|
||||
|
||||
func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
|
||||
if len(inter.mhdr) == 0 {
|
||||
throw("internal error - misuse of itab")
|
||||
}
|
||||
|
||||
// easy case
|
||||
x := typ.uncommon()
|
||||
if x == nil {
|
||||
if typ.tflag&tflagUncommon == 0 {
|
||||
if canfail {
|
||||
return nil
|
||||
}
|
||||
panic(&TypeAssertionError{"", typ._string, inter.typ._string, inter.mhdr[0].name.name()})
|
||||
}
|
||||
|
||||
// compiler has provided some good hash codes for us.
|
||||
h := inter.typ.hash
|
||||
h += 17 * typ.hash
|
||||
// TODO(rsc): h += 23 * x.mhash ?
|
||||
h %= hashSize
|
||||
h := itabhash(inter, typ)
|
||||
|
||||
// look twice - once without lock, once with.
|
||||
// common case will be no lock contention.
|
||||
@ -56,10 +59,9 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
|
||||
// was already done once using the , ok form
|
||||
// and we have a cached negative result.
|
||||
// the cached result doesn't record which
|
||||
// interface function was missing, so jump
|
||||
// down to the interface check, which will
|
||||
// do more work but give a better error.
|
||||
goto search
|
||||
// interface function was missing, so try
|
||||
// adding the itab again, which will throw an error.
|
||||
additab(m, locked != 0, false)
|
||||
}
|
||||
}
|
||||
if locked != 0 {
|
||||
@ -73,8 +75,19 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
|
||||
m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
|
||||
m.inter = inter
|
||||
m._type = typ
|
||||
additab(m, true, canfail)
|
||||
unlock(&ifaceLock)
|
||||
if m.bad != 0 {
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func additab(m *itab, locked, canfail bool) {
|
||||
inter := m.inter
|
||||
typ := m._type
|
||||
x := typ.uncommon()
|
||||
|
||||
search:
|
||||
// both inter and typ have method sorted by name,
|
||||
// and interface names are unique,
|
||||
// so can iterate over both in lock step;
|
||||
@ -107,7 +120,7 @@ search:
|
||||
}
|
||||
// didn't find method
|
||||
if !canfail {
|
||||
if locked != 0 {
|
||||
if locked {
|
||||
unlock(&ifaceLock)
|
||||
}
|
||||
panic(&TypeAssertionError{"", typ._string, inter.typ._string, iname})
|
||||
@ -116,16 +129,22 @@ search:
|
||||
break
|
||||
nextimethod:
|
||||
}
|
||||
if locked == 0 {
|
||||
if !locked {
|
||||
throw("invalid itab locking")
|
||||
}
|
||||
h := itabhash(inter, typ)
|
||||
m.link = hash[h]
|
||||
atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
|
||||
unlock(&ifaceLock)
|
||||
if m.bad != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func itabsinit() {
|
||||
lock(&ifaceLock)
|
||||
for m := &firstmoduledata; m != nil; m = m.next {
|
||||
for _, i := range m.itablinks {
|
||||
additab(i, true, false)
|
||||
}
|
||||
}
|
||||
return m
|
||||
unlock(&ifaceLock)
|
||||
}
|
||||
|
||||
func typ2Itab(t *_type, inter *interfacetype, cache **itab) *itab {
|
||||
|
@ -435,6 +435,7 @@ func schedinit() {
|
||||
tracebackinit()
|
||||
moduledataverify()
|
||||
stackinit()
|
||||
itabsinit()
|
||||
mallocinit()
|
||||
mcommoninit(_g_.m)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user