]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: improve generated eq algs for structs containing interfaces
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 24 Apr 2020 18:01:38 +0000 (11:01 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Mon, 27 Apr 2020 17:19:38 +0000 (17:19 +0000)
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>
src/cmd/compile/internal/gc/alg.go

index 16524773a06158b3662386bea99caa75706b8a21..571ac4c6c7ba32b406d45900551e30939afc7a54 100644 (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))
                                }