1
0
mirror of https://github.com/golang/go synced 2024-11-19 13:34:45 -07:00

cmd/compile: don't allocate convX2X or assertX2X func names before syslook

Change-Id: Ib632ee7ac893750bec4cfe223745bca5f31900ab
Reviewed-on: https://go-review.googlesource.com/20234
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Brad Fitzpatrick 2016-03-04 22:02:27 +00:00
parent 80e5b52566
commit e3a9dca7cc
2 changed files with 71 additions and 20 deletions

View File

@ -2804,15 +2804,15 @@ func isdirectiface(t *Type) bool {
return false return false
} }
// type2IET 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.
func type2IET(t *Type) string { func (t *Type) iet() byte {
if isnilinter(t) { if isnilinter(t) {
return "E" return 'E'
} }
if Isinter(t) { if Isinter(t) {
return "I" return 'I'
} }
return "T" return 'T'
} }

View File

@ -397,6 +397,63 @@ func walkexprlistcheap(l nodesOrNodeList, init nodesOrNodeListPtr) {
} }
} }
// Build name of function: convI2E etc.
// Not all names are possible
// (e.g., we'll never generate convE2E or convE2I).
func convFuncName(from, to *Type) string {
tkind := to.iet()
switch from.iet() {
case 'I':
switch tkind {
case 'E':
return "convI2E"
case 'I':
return "convI2I"
}
case 'T':
switch tkind {
case 'E':
return "convT2E"
case 'I':
return "convT2I"
}
}
Fatalf("unknown conv func %c2%c", from.iet(), to.iet())
panic("unreachable")
}
// Build name of function: assertI2E etc.
// If with2suffix is true, the form ending in "2" is returned".
func assertFuncName(from, to *Type, with2suffix bool) string {
l := len("assertX2X2")
if !with2suffix {
l--
}
tkind := to.iet()
switch from.iet() {
case 'E':
switch tkind {
case 'I':
return "assertE2I2"[:l]
case 'E':
return "assertE2E2"[:l]
case 'T':
return "assertE2T2"[:l]
}
case 'I':
switch tkind {
case 'I':
return "assertI2I2"[:l]
case 'E':
return "assertI2E2"[:l]
case 'T':
return "assertI2T2"[:l]
}
}
Fatalf("unknown assert func %c2%c", from.iet(), to.iet())
panic("unreachable")
}
func walkexpr(np **Node, init nodesOrNodeListPtr) { func walkexpr(np **Node, init nodesOrNodeListPtr) {
n := *np n := *np
@ -689,8 +746,7 @@ opswitch:
Warn("type assertion not inlined") Warn("type assertion not inlined")
} }
buf := "assert" + type2IET(r.Left.Type) + "2" + type2IET(r.Type) fn := syslook(assertFuncName(r.Left.Type, r.Type, false), 1)
fn := syslook(buf, 1)
substArgTypes(fn, r.Left.Type, r.Type) substArgTypes(fn, r.Left.Type, r.Type)
n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1) n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
@ -892,8 +948,8 @@ opswitch:
oktype = ok.Type oktype = ok.Type
} }
fromKind := type2IET(from.Type) fromKind := from.Type.iet()
toKind := type2IET(t) toKind := t.iet()
// 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
@ -901,13 +957,13 @@ opswitch:
if isblank(nodeSeqFirst(n.List)) { if isblank(nodeSeqFirst(n.List)) {
var fast *Node var fast *Node
switch { switch {
case fromKind == "E" && toKind == "T": case fromKind == 'E' && toKind == 'T':
tab := Nod(OITAB, from, nil) // type:eface::tab:iface tab := Nod(OITAB, from, nil) // type:eface::tab:iface
typ := Nod(OCONVNOP, typename(t), nil) typ := Nod(OCONVNOP, typename(t), nil)
typ.Type = Ptrto(Types[TUINTPTR]) typ.Type = Ptrto(Types[TUINTPTR])
fast = Nod(OEQ, tab, typ) fast = Nod(OEQ, tab, typ)
case fromKind == "I" && toKind == "E", case fromKind == 'I' && toKind == 'E',
fromKind == "E" && toKind == "E": fromKind == 'E' && toKind == 'E':
tab := Nod(OITAB, from, nil) tab := Nod(OITAB, from, nil)
fast = Nod(ONE, nodnil(), tab) fast = Nod(ONE, nodnil(), tab)
} }
@ -932,8 +988,7 @@ opswitch:
if Debug_typeassert > 0 { if Debug_typeassert > 0 {
Warn("type assertion not inlined") Warn("type assertion not inlined")
} }
buf := "assert" + fromKind + "2" + toKind + "2" fn := syslook(assertFuncName(from.Type, t, true), 1)
fn := syslook(buf, 1)
substArgTypes(fn, from.Type, t) substArgTypes(fn, from.Type, t)
call := mkcall1(fn, oktype, init, typename(t), from, resptr) call := mkcall1(fn, oktype, init, typename(t), from, resptr)
n = Nod(OAS, ok, call) n = Nod(OAS, ok, call)
@ -1046,11 +1101,7 @@ opswitch:
ll = list(ll, r) ll = list(ll, r)
} }
// Build name of function: convI2E etc. fn := syslook(convFuncName(n.Left.Type, n.Type), 1)
// Not all names are possible
// (e.g., we'll never generate convE2E or convE2I).
buf := "conv" + type2IET(n.Left.Type) + "2" + type2IET(n.Type)
fn := syslook(buf, 1)
if !Isinter(n.Left.Type) { if !Isinter(n.Left.Type) {
substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type) substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type)
} else { } else {