aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2016-06-06 08:29:52 -0700
committerJosh Bleecher Snyder <josharian@gmail.com>2016-08-16 15:24:33 +0000
commit562d06fc23261b21d12fbcbd407aadee9cb428cb (patch)
tree6da849975366a238b8be485ce3f5716a00996100
parente6e26eeb299f9829ac70bd400d011bfdd266f1c1 (diff)
downloadgo-562d06fc23261b21d12fbcbd407aadee9cb428cb.tar.gz
go-562d06fc23261b21d12fbcbd407aadee9cb428cb.zip
cmd/compile: inline _, ok = i.(T)
We already inlined _, ok = e.(T) _, ok = i.(E) _, ok = e.(E) The only ok-only variants not inlined are now _, ok = i.(I) _, ok = e.(I) These call getitab, so are non-trivial. Change-Id: Ie45fd8933ee179a679b92ce925079b94cff0ee12 Reviewed-on: https://go-review.googlesource.com/26658 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/subr.go10
-rw-r--r--src/cmd/compile/internal/gc/swt.go6
-rw-r--r--src/cmd/compile/internal/gc/walk.go30
-rw-r--r--src/runtime/iface.go15
4 files changed, 36 insertions, 25 deletions
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index c3f2b60509..8c82c22f97 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -2317,6 +2317,16 @@ func isdirectiface(t *Type) bool {
return false
}
+// itabType loads the _type field from a runtime.itab struct.
+func itabType(itab *Node) *Node {
+ typ := NodSym(ODOTPTR, itab, nil)
+ typ.Type = Ptrto(Types[TUINT8])
+ typ.Typecheck = 1
+ typ.Xoffset = int64(Widthptr) // offset of _type in runtime.itab
+ typ.Bounded = true // guaranteed not to fault
+ return typ
+}
+
// iet returns 'T' if t is a concrete type,
// 'I' if t is an interface type, and 'E' if t is an empty interface type.
// It is used to build calls to the conv* and assert* runtime routines.
diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go
index f44c747d36..09ce443530 100644
--- a/src/cmd/compile/internal/gc/swt.go
+++ b/src/cmd/compile/internal/gc/swt.go
@@ -589,11 +589,7 @@ func (s *typeSwitch) walk(sw *Node) {
if !cond.Right.Type.IsEmptyInterface() {
// Load type from itab.
- typ = NodSym(ODOTPTR, typ, nil)
- typ.Type = Ptrto(Types[TUINT8])
- typ.Typecheck = 1
- typ.Xoffset = int64(Widthptr) // offset of _type in runtime.itab
- typ.Bounded = true // guaranteed not to fault
+ typ = itabType(typ)
}
// Load hash from type.
h := NodSym(ODOTPTR, typ, nil)
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 88ac347ad7..4e6647cef7 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -960,19 +960,27 @@ opswitch:
fromKind := from.Type.iet()
toKind := t.iet()
+ res := n.List.First()
+
// Avoid runtime calls in a few cases of the form _, ok := i.(T).
// This is faster and shorter and allows the corresponding assertX2X2
// routines to skip nil checks on their last argument.
- if isblank(n.List.First()) {
+ if isblank(res) {
var fast *Node
- switch {
- case fromKind == 'E' && toKind == 'T':
- tab := Nod(OITAB, from, nil) // type:eface::tab:iface
- typ := Nod(OCONVNOP, typename(t), nil)
- typ.Type = Ptrto(Types[TUINTPTR])
- fast = Nod(OEQ, tab, typ)
- case fromKind == 'I' && toKind == 'E',
- fromKind == 'E' && toKind == 'E':
+ switch toKind {
+ case 'T':
+ tab := Nod(OITAB, from, nil)
+ if fromKind == 'E' {
+ typ := Nod(OCONVNOP, typename(t), nil)
+ typ.Type = Ptrto(Types[TUINTPTR])
+ fast = Nod(OEQ, tab, typ)
+ break
+ }
+ fast = Nod(OANDAND,
+ Nod(ONE, nodnil(), tab),
+ Nod(OEQ, itabType(tab), typename(t)),
+ )
+ case 'E':
tab := Nod(OITAB, from, nil)
fast = Nod(ONE, nodnil(), tab)
}
@@ -987,10 +995,10 @@ opswitch:
}
var resptr *Node // &res
- if isblank(n.List.First()) {
+ if isblank(res) {
resptr = nodnil()
} else {
- resptr = Nod(OADDR, n.List.First(), nil)
+ resptr = Nod(OADDR, res, nil)
}
resptr.Etype = 1 // addr does not escape
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index 1690147fac..7f24a6e69c 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -218,20 +218,17 @@ func assertI2T(t *_type, i iface, r unsafe.Pointer) {
}
}
+// The compiler ensures that r is non-nil.
func assertI2T2(t *_type, i iface, r unsafe.Pointer) bool {
tab := i.tab
if tab == nil || tab._type != t {
- if r != nil {
- memclr(r, t.size)
- }
+ memclr(r, t.size)
return false
}
- if r != nil {
- if isDirectIface(t) {
- writebarrierptr((*uintptr)(r), uintptr(i.data))
- } else {
- typedmemmove(t, r, i.data)
- }
+ if isDirectIface(t) {
+ writebarrierptr((*uintptr)(r), uintptr(i.data))
+ } else {
+ typedmemmove(t, r, i.data)
}
return true
}