Commit e3a9dca7 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

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

Change-Id: Ib632ee7ac893750bec4cfe223745bca5f31900ab
Reviewed-on: https://go-review.googlesource.com/20234Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 80e5b525
...@@ -2804,15 +2804,15 @@ func isdirectiface(t *Type) bool { ...@@ -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'
} }
...@@ -397,6 +397,63 @@ func walkexprlistcheap(l nodesOrNodeList, init nodesOrNodeListPtr) { ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment