Skip to content

Commit

Permalink
cmd/compile: don't allocate convX2X or assertX2X func names before sy…
Browse files Browse the repository at this point in the history
…slook

Change-Id: Ib632ee7ac893750bec4cfe223745bca5f31900ab
Reviewed-on: https://go-review.googlesource.com/20234
Reviewed-by: Matthew Dempsky <[email protected]>
Run-TryBot: Brad Fitzpatrick <[email protected]>
Reviewed-by: David Crawshaw <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
bradfitz committed Mar 4, 2016
1 parent 80e5b52 commit e3a9dca
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 20 deletions.
12 changes: 6 additions & 6 deletions src/cmd/compile/internal/gc/subr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2804,15 +2804,15 @@ func isdirectiface(t *Type) bool {
return false
}

// type2IET returns "T" if t is a concrete type,
// "I" if t is an interface type, and "E" if t is an empty interface 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.
// 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) {
return "E"
return 'E'
}
if Isinter(t) {
return "I"
return 'I'
}
return "T"
return 'T'
}
79 changes: 65 additions & 14 deletions src/cmd/compile/internal/gc/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
n := *np

Expand Down Expand Up @@ -689,8 +746,7 @@ opswitch:
Warn("type assertion not inlined")
}

buf := "assert" + type2IET(r.Left.Type) + "2" + type2IET(r.Type)
fn := syslook(buf, 1)
fn := syslook(assertFuncName(r.Left.Type, r.Type, false), 1)
substArgTypes(fn, r.Left.Type, r.Type)

n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
Expand Down Expand Up @@ -892,22 +948,22 @@ opswitch:
oktype = ok.Type
}

fromKind := type2IET(from.Type)
toKind := type2IET(t)
fromKind := from.Type.iet()
toKind := t.iet()

// 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(nodeSeqFirst(n.List)) {
var fast *Node
switch {
case fromKind == "E" && toKind == "T":
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":
case fromKind == 'I' && toKind == 'E',
fromKind == 'E' && toKind == 'E':
tab := Nod(OITAB, from, nil)
fast = Nod(ONE, nodnil(), tab)
}
Expand All @@ -932,8 +988,7 @@ opswitch:
if Debug_typeassert > 0 {
Warn("type assertion not inlined")
}
buf := "assert" + fromKind + "2" + toKind + "2"
fn := syslook(buf, 1)
fn := syslook(assertFuncName(from.Type, t, true), 1)
substArgTypes(fn, from.Type, t)
call := mkcall1(fn, oktype, init, typename(t), from, resptr)
n = Nod(OAS, ok, call)
Expand Down Expand Up @@ -1046,11 +1101,7 @@ opswitch:
ll = list(ll, r)
}

// Build name of function: convI2E etc.
// 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)
fn := syslook(convFuncName(n.Left.Type, n.Type), 1)
if !Isinter(n.Left.Type) {
substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type)
} else {
Expand Down

0 comments on commit e3a9dca

Please sign in to comment.