mirror of
https://github.com/golang/go.git
synced 2025-05-19 06:14:40 +00:00
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>
This commit is contained in:
parent
e6e26eeb29
commit
562d06fc23
@ -2317,6 +2317,16 @@ func isdirectiface(t *Type) bool {
|
|||||||
return false
|
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,
|
// 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.
|
// '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.
|
// It is used to build calls to the conv* and assert* runtime routines.
|
||||||
|
@ -589,11 +589,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
|||||||
|
|
||||||
if !cond.Right.Type.IsEmptyInterface() {
|
if !cond.Right.Type.IsEmptyInterface() {
|
||||||
// Load type from itab.
|
// Load type from itab.
|
||||||
typ = NodSym(ODOTPTR, typ, nil)
|
typ = itabType(typ)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
// Load hash from type.
|
// Load hash from type.
|
||||||
h := NodSym(ODOTPTR, typ, nil)
|
h := NodSym(ODOTPTR, typ, nil)
|
||||||
|
@ -960,19 +960,27 @@ opswitch:
|
|||||||
fromKind := from.Type.iet()
|
fromKind := from.Type.iet()
|
||||||
toKind := t.iet()
|
toKind := t.iet()
|
||||||
|
|
||||||
|
res := n.List.First()
|
||||||
|
|
||||||
// Avoid runtime calls in a few cases of the form _, ok := i.(T).
|
// Avoid runtime calls in a few cases of the form _, ok := i.(T).
|
||||||
// This is faster and shorter and allows the corresponding assertX2X2
|
// This is faster and shorter and allows the corresponding assertX2X2
|
||||||
// routines to skip nil checks on their last argument.
|
// routines to skip nil checks on their last argument.
|
||||||
if isblank(n.List.First()) {
|
if isblank(res) {
|
||||||
var fast *Node
|
var fast *Node
|
||||||
switch {
|
switch toKind {
|
||||||
case fromKind == 'E' && toKind == 'T':
|
case 'T':
|
||||||
tab := Nod(OITAB, from, nil) // type:eface::tab:iface
|
tab := Nod(OITAB, from, nil)
|
||||||
typ := Nod(OCONVNOP, typename(t), nil)
|
if fromKind == 'E' {
|
||||||
typ.Type = Ptrto(Types[TUINTPTR])
|
typ := Nod(OCONVNOP, typename(t), nil)
|
||||||
fast = Nod(OEQ, tab, typ)
|
typ.Type = Ptrto(Types[TUINTPTR])
|
||||||
case fromKind == 'I' && toKind == 'E',
|
fast = Nod(OEQ, tab, typ)
|
||||||
fromKind == 'E' && toKind == 'E':
|
break
|
||||||
|
}
|
||||||
|
fast = Nod(OANDAND,
|
||||||
|
Nod(ONE, nodnil(), tab),
|
||||||
|
Nod(OEQ, itabType(tab), typename(t)),
|
||||||
|
)
|
||||||
|
case 'E':
|
||||||
tab := Nod(OITAB, from, nil)
|
tab := Nod(OITAB, from, nil)
|
||||||
fast = Nod(ONE, nodnil(), tab)
|
fast = Nod(ONE, nodnil(), tab)
|
||||||
}
|
}
|
||||||
@ -987,10 +995,10 @@ opswitch:
|
|||||||
}
|
}
|
||||||
|
|
||||||
var resptr *Node // &res
|
var resptr *Node // &res
|
||||||
if isblank(n.List.First()) {
|
if isblank(res) {
|
||||||
resptr = nodnil()
|
resptr = nodnil()
|
||||||
} else {
|
} else {
|
||||||
resptr = Nod(OADDR, n.List.First(), nil)
|
resptr = Nod(OADDR, res, nil)
|
||||||
}
|
}
|
||||||
resptr.Etype = 1 // addr does not escape
|
resptr.Etype = 1 // addr does not escape
|
||||||
|
|
||||||
|
@ -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 {
|
func assertI2T2(t *_type, i iface, r unsafe.Pointer) bool {
|
||||||
tab := i.tab
|
tab := i.tab
|
||||||
if tab == nil || tab._type != t {
|
if tab == nil || tab._type != t {
|
||||||
if r != nil {
|
memclr(r, t.size)
|
||||||
memclr(r, t.size)
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if r != nil {
|
if isDirectIface(t) {
|
||||||
if isDirectIface(t) {
|
writebarrierptr((*uintptr)(r), uintptr(i.data))
|
||||||
writebarrierptr((*uintptr)(r), uintptr(i.data))
|
} else {
|
||||||
} else {
|
typedmemmove(t, r, i.data)
|
||||||
typedmemmove(t, r, i.data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user