1
0
mirror of https://github.com/golang/go synced 2024-11-23 16:50:06 -07:00

cmd/compile: improve generated eq algs for structs containing interfaces

type T struct {
    s interface{}
    i int
}

Prior to this change, we generated this equality algorithm for T:

func eqT(p, q *T) bool {
    return p.s.type == q.s.type &&
      runtime.efaceeq(p.s.type, p.s.data, q.s.data) &&
      p.i == q.i
}

This change splits the two halves of the interface equality,
so that we can do the cheap (type) half early and the expensive
(data) half late. We now generate:

func eqT(p, q *T) bool {
    return p.s.type == q.s.type &&
      p.i == q.i &&
      runtime.efaceeq(p.s.type, p.s.data, q.s.data)
}

The generated code tends to be a bit smaller. Examples:

go/ast
.eq."".ForStmt 306 -> 304  (-0.65%)
.eq."".TypeAssertExpr 221 -> 219  (-0.90%)
.eq."".TypeSwitchStmt 228 -> 226  (-0.88%)
.eq."".ParenExpr 150 -> 148  (-1.33%)
.eq."".IndexExpr 221 -> 219  (-0.90%)
.eq."".SwitchStmt 228 -> 226  (-0.88%)
.eq."".RangeStmt 334 -> 332  (-0.60%)

Change-Id: Iec9e24f214ca772416202b9fb9252e625c22380e
Reviewed-on: https://go-review.googlesource.com/c/go/+/230207
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2020-04-24 11:01:38 -07:00
parent f4e13b83aa
commit 1cc7be89a9

View File

@ -585,6 +585,14 @@ func geneq(t *types.Type) *obj.LSym {
eqlen, eqmem := eqstring(p, q)
and(eqlen)
and(eqmem)
case f.Type.IsInterface():
p.Type = f.Type
p = typecheck(p, ctxExpr)
q.Type = f.Type
q = typecheck(q, ctxExpr)
eqtab, eqdata := eqinterface(p, q)
and(eqtab)
and(eqdata)
default:
and(nod(OEQ, p, q))
}