]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: inline _, ok = i.(T)
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 6 Jun 2016 15:29:52 +0000 (08:29 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 16 Aug 2016 15:24:33 +0000 (15:24 +0000)
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>
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/swt.go
src/cmd/compile/internal/gc/walk.go
src/runtime/iface.go

index c3f2b605099ffbad36b48fb9ba1775d0f2afc22f..8c82c22f973b2441167778f6258383816a6f2144 100644 (file)
@@ -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.
index f44c747d366436512081c1fcea329129c105f776..09ce443530c1a427b2a5cb383521c545f93d13dc 100644 (file)
@@ -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)
index 88ac347ad7f51aaf1278cf2a8e80504ac0ae75a4..4e6647cef7828fbb2b5983710ab06932d252bcda 100644 (file)
@@ -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
 
index 1690147fac3dc0298b2f6631d7dc4af944e7f295..7f24a6e69cccf7d7ec3b598279ca2f121c3e473d 100644 (file)
@@ -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
 }