aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2017-01-03 16:15:38 -0800
committerKeith Randall <khr@golang.org>2017-02-13 18:16:31 +0000
commit5a75d6a08ebb727c0e2bf5c8fbcbc104d260d302 (patch)
tree7fa0fe7218a250e9636b7bcbb487a8cd8e765907 /src/runtime
parentee2f5fafd88b5ce1404fa40e3645a409e9630897 (diff)
downloadgo-5a75d6a08ebb727c0e2bf5c8fbcbc104d260d302.tar.xz
cmd/compile: optimize non-empty-interface type conversions
When doing i.(T) for non-empty-interface i and concrete type T, there's no need to read the type out of the itab. Just compare the itab to the itab we expect for that interface/type pair. Also optimize type switches by putting the type hash of the concrete type in the itab. That way we don't need to load the type pointer out of the itab. Update #18492 Change-Id: I49e280a21e5687e771db5b8a56b685291ac168ce Reviewed-on: https://go-review.googlesource.com/34810 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/iface.go24
-rw-r--r--src/runtime/plugin.go2
-rw-r--r--src/runtime/runtime2.go6
3 files changed, 22 insertions, 10 deletions
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index b5c31a301d..f043724a56 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -53,7 +53,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
}
for m = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
if m.inter == inter && m._type == typ {
- if m.bad != 0 {
+ if m.bad {
if !canfail {
// this can only happen if the conversion
// was already done once using the , ok form
@@ -78,7 +78,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
m._type = typ
additab(m, true, canfail)
unlock(&ifaceLock)
- if m.bad != 0 {
+ if m.bad {
return nil
}
return m
@@ -130,7 +130,7 @@ func additab(m *itab, locked, canfail bool) {
}
panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), iname})
}
- m.bad = 1
+ m.bad = true
break
nextimethod:
}
@@ -139,7 +139,7 @@ func additab(m *itab, locked, canfail bool) {
}
h := itabhash(inter, typ)
m.link = hash[h]
- m.inhash = 1
+ m.inhash = true
atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
}
@@ -152,7 +152,7 @@ func itabsinit() {
// and thanks to the way global symbol resolution works, the
// pointed-to itab may already have been inserted into the
// global 'hash'.
- if i.inhash == 0 {
+ if !i.inhash {
additab(i, true, false)
}
}
@@ -160,11 +160,11 @@ func itabsinit() {
unlock(&ifaceLock)
}
-// panicdottype is called when doing an i.(T) conversion and the conversion fails.
+// panicdottypeE is called when doing an e.(T) conversion and the conversion fails.
// have = the dynamic type we have.
// want = the static type we're trying to convert to.
// iface = the static type we're converting from.
-func panicdottype(have, want, iface *_type) {
+func panicdottypeE(have, want, iface *_type) {
haveString := ""
if have != nil {
haveString = have.string()
@@ -172,6 +172,16 @@ func panicdottype(have, want, iface *_type) {
panic(&TypeAssertionError{iface.string(), haveString, want.string(), ""})
}
+// panicdottypeI is called when doing an i.(T) conversion and the conversion fails.
+// Same args as panicdottypeE, but "have" is the dynamic itab we have.
+func panicdottypeI(have *itab, want, iface *_type) {
+ var t *_type
+ if have != nil {
+ t = have._type
+ }
+ panicdottypeE(t, want, iface)
+}
+
// panicnildottype is called when doing a i.(T) conversion and the interface i is nil.
// want = the static type we're trying to convert to.
func panicnildottype(want *_type) {
diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go
index 8edb29c9fe..ea246509cc 100644
--- a/src/runtime/plugin.go
+++ b/src/runtime/plugin.go
@@ -56,7 +56,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, mismatch
lock(&ifaceLock)
for _, i := range md.itablinks {
- if i.inhash == 0 {
+ if !i.inhash {
additab(i, true, false)
}
}
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 9cb2b85f33..8cf13e96d8 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -644,8 +644,10 @@ type itab struct {
inter *interfacetype
_type *_type
link *itab
- bad int32
- inhash int32 // has this itab been added to hash?
+ hash uint32 // copy of _type.hash. Used for type switches.
+ bad bool // type does not implement interface
+ inhash bool // has this itab been added to hash?
+ unused [2]byte
fun [1]uintptr // variable sized
}