cmd/compile: simplify efaceeq and ifaceeq
Clean up code that does interface equality. Avoid doing checks
in efaceeq/ifaceeq that we already did before calling those routines.
No noticeable performance changes for existing benchmarks.
name old time/op new time/op delta
EfaceCmpDiff-8 604ns ± 1% 553ns ± 1% -8.41% (p=0.000 n=9+10)
Fixes #18618
Change-Id: I3bd46db82b96494873045bc3300c56400bc582eb
Reviewed-on: https://go-review.googlesource.com/38606
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index 58d46dd..4d67fe2 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -69,83 +69,83 @@
{"panicdottypeE", funcTag, 55},
{"panicdottypeI", funcTag, 55},
{"panicnildottype", funcTag, 56},
- {"ifaceeq", funcTag, 57},
- {"efaceeq", funcTag, 57},
- {"makemap", funcTag, 59},
- {"mapaccess1", funcTag, 60},
- {"mapaccess1_fast32", funcTag, 61},
- {"mapaccess1_fast64", funcTag, 61},
- {"mapaccess1_faststr", funcTag, 61},
- {"mapaccess1_fat", funcTag, 62},
- {"mapaccess2", funcTag, 63},
- {"mapaccess2_fast32", funcTag, 64},
- {"mapaccess2_fast64", funcTag, 64},
- {"mapaccess2_faststr", funcTag, 64},
- {"mapaccess2_fat", funcTag, 65},
- {"mapassign", funcTag, 60},
- {"mapassign_fast32", funcTag, 61},
- {"mapassign_fast64", funcTag, 61},
- {"mapassign_faststr", funcTag, 61},
- {"mapiterinit", funcTag, 66},
- {"mapdelete", funcTag, 66},
- {"mapdelete_fast32", funcTag, 67},
- {"mapdelete_fast64", funcTag, 67},
- {"mapdelete_faststr", funcTag, 67},
- {"mapiternext", funcTag, 68},
- {"makechan", funcTag, 70},
- {"chanrecv1", funcTag, 72},
- {"chanrecv2", funcTag, 73},
- {"chansend1", funcTag, 75},
+ {"ifaceeq", funcTag, 59},
+ {"efaceeq", funcTag, 59},
+ {"makemap", funcTag, 61},
+ {"mapaccess1", funcTag, 62},
+ {"mapaccess1_fast32", funcTag, 63},
+ {"mapaccess1_fast64", funcTag, 63},
+ {"mapaccess1_faststr", funcTag, 63},
+ {"mapaccess1_fat", funcTag, 64},
+ {"mapaccess2", funcTag, 65},
+ {"mapaccess2_fast32", funcTag, 66},
+ {"mapaccess2_fast64", funcTag, 66},
+ {"mapaccess2_faststr", funcTag, 66},
+ {"mapaccess2_fat", funcTag, 67},
+ {"mapassign", funcTag, 62},
+ {"mapassign_fast32", funcTag, 63},
+ {"mapassign_fast64", funcTag, 63},
+ {"mapassign_faststr", funcTag, 63},
+ {"mapiterinit", funcTag, 68},
+ {"mapdelete", funcTag, 68},
+ {"mapdelete_fast32", funcTag, 69},
+ {"mapdelete_fast64", funcTag, 69},
+ {"mapdelete_faststr", funcTag, 69},
+ {"mapiternext", funcTag, 70},
+ {"makechan", funcTag, 72},
+ {"chanrecv1", funcTag, 74},
+ {"chanrecv2", funcTag, 75},
+ {"chansend1", funcTag, 77},
{"closechan", funcTag, 23},
- {"writeBarrier", varTag, 77},
- {"writebarrierptr", funcTag, 78},
- {"typedmemmove", funcTag, 79},
- {"typedmemclr", funcTag, 80},
- {"typedslicecopy", funcTag, 81},
- {"selectnbsend", funcTag, 82},
- {"selectnbrecv", funcTag, 83},
- {"selectnbrecv2", funcTag, 85},
- {"newselect", funcTag, 86},
- {"selectsend", funcTag, 87},
- {"selectrecv", funcTag, 88},
+ {"writeBarrier", varTag, 79},
+ {"writebarrierptr", funcTag, 80},
+ {"typedmemmove", funcTag, 81},
+ {"typedmemclr", funcTag, 82},
+ {"typedslicecopy", funcTag, 83},
+ {"selectnbsend", funcTag, 84},
+ {"selectnbrecv", funcTag, 85},
+ {"selectnbrecv2", funcTag, 87},
+ {"newselect", funcTag, 88},
+ {"selectsend", funcTag, 89},
+ {"selectrecv", funcTag, 90},
{"selectdefault", funcTag, 56},
- {"selectgo", funcTag, 89},
+ {"selectgo", funcTag, 91},
{"block", funcTag, 5},
- {"makeslice", funcTag, 91},
- {"makeslice64", funcTag, 92},
- {"growslice", funcTag, 93},
- {"memmove", funcTag, 94},
- {"memclrNoHeapPointers", funcTag, 96},
- {"memclrHasPointers", funcTag, 96},
- {"memequal", funcTag, 97},
- {"memequal8", funcTag, 98},
- {"memequal16", funcTag, 98},
- {"memequal32", funcTag, 98},
- {"memequal64", funcTag, 98},
- {"memequal128", funcTag, 98},
- {"int64div", funcTag, 99},
- {"uint64div", funcTag, 100},
- {"int64mod", funcTag, 99},
- {"uint64mod", funcTag, 100},
- {"float64toint64", funcTag, 101},
- {"float64touint64", funcTag, 102},
- {"float64touint32", funcTag, 104},
- {"int64tofloat64", funcTag, 105},
- {"uint64tofloat64", funcTag, 106},
- {"uint32tofloat64", funcTag, 107},
- {"complex128div", funcTag, 108},
- {"racefuncenter", funcTag, 109},
+ {"makeslice", funcTag, 93},
+ {"makeslice64", funcTag, 94},
+ {"growslice", funcTag, 95},
+ {"memmove", funcTag, 96},
+ {"memclrNoHeapPointers", funcTag, 97},
+ {"memclrHasPointers", funcTag, 97},
+ {"memequal", funcTag, 98},
+ {"memequal8", funcTag, 99},
+ {"memequal16", funcTag, 99},
+ {"memequal32", funcTag, 99},
+ {"memequal64", funcTag, 99},
+ {"memequal128", funcTag, 99},
+ {"int64div", funcTag, 100},
+ {"uint64div", funcTag, 101},
+ {"int64mod", funcTag, 100},
+ {"uint64mod", funcTag, 101},
+ {"float64toint64", funcTag, 102},
+ {"float64touint64", funcTag, 103},
+ {"float64touint32", funcTag, 105},
+ {"int64tofloat64", funcTag, 106},
+ {"uint64tofloat64", funcTag, 107},
+ {"uint32tofloat64", funcTag, 108},
+ {"complex128div", funcTag, 109},
+ {"racefuncenter", funcTag, 110},
{"racefuncexit", funcTag, 5},
- {"raceread", funcTag, 109},
- {"racewrite", funcTag, 109},
- {"racereadrange", funcTag, 110},
- {"racewriterange", funcTag, 110},
- {"msanread", funcTag, 110},
- {"msanwrite", funcTag, 110},
+ {"raceread", funcTag, 110},
+ {"racewrite", funcTag, 110},
+ {"racereadrange", funcTag, 111},
+ {"racewriterange", funcTag, 111},
+ {"msanread", funcTag, 111},
+ {"msanwrite", funcTag, 111},
}
func runtimeTypes() []*Type {
- var typs [111]*Type
+ var typs [112]*Type
typs[0] = bytetype
typs[1] = typPtr(typs[0])
typs[2] = Types[TANY]
@@ -203,59 +203,60 @@
typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
typs[56] = functype(nil, []*Node{anonfield(typs[1])}, nil)
- typs[57] = functype(nil, []*Node{anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[11])})
- typs[58] = typMap(typs[2], typs[2])
- typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[58])})
- typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
- typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
- typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
- typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
- typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
- typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
- typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[3])}, nil)
- typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[58]), anonfield(typs[2])}, nil)
- typs[68] = functype(nil, []*Node{anonfield(typs[3])}, nil)
- typs[69] = typChan(typs[2], Cboth)
- typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[69])})
- typs[71] = typChan(typs[2], Crecv)
- typs[72] = functype(nil, []*Node{anonfield(typs[71]), anonfield(typs[3])}, nil)
- typs[73] = functype(nil, []*Node{anonfield(typs[71]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
- typs[74] = typChan(typs[2], Csend)
- typs[75] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, nil)
- typs[76] = typArray(typs[0], 3)
- typs[77] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[76]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
- typs[78] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil)
- typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
- typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
- typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
- typs[82] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
- typs[83] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[71])}, []*Node{anonfield(typs[11])})
- typs[84] = typPtr(typs[11])
- typs[85] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[84]), anonfield(typs[71])}, []*Node{anonfield(typs[11])})
- typs[86] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil)
- typs[87] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[74]), anonfield(typs[3])}, nil)
- typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[71]), anonfield(typs[3]), anonfield(typs[84])}, nil)
- typs[89] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])})
- typs[90] = typSlice(typs[2])
- typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[90])})
- typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[90])})
- typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[90]), anonfield(typs[32])}, []*Node{anonfield(typs[90])})
- typs[94] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[49])}, nil)
- typs[95] = Types[TUNSAFEPTR]
- typs[96] = functype(nil, []*Node{anonfield(typs[95]), anonfield(typs[49])}, nil)
- typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[49])}, []*Node{anonfield(typs[11])})
- typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
- typs[99] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
- typs[100] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
- typs[101] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
- typs[102] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
- typs[103] = Types[TUINT32]
- typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[103])})
- typs[105] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
- typs[106] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
- typs[107] = functype(nil, []*Node{anonfield(typs[103])}, []*Node{anonfield(typs[13])})
- typs[108] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
- typs[109] = functype(nil, []*Node{anonfield(typs[49])}, nil)
- typs[110] = functype(nil, []*Node{anonfield(typs[49]), anonfield(typs[49])}, nil)
+ typs[57] = typPtr(typs[49])
+ typs[58] = Types[TUNSAFEPTR]
+ typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])})
+ typs[60] = typMap(typs[2], typs[2])
+ typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[60])})
+ typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
+ typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
+ typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
+ typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
+ typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
+ typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
+ typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, nil)
+ typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, nil)
+ typs[70] = functype(nil, []*Node{anonfield(typs[3])}, nil)
+ typs[71] = typChan(typs[2], Cboth)
+ typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[71])})
+ typs[73] = typChan(typs[2], Crecv)
+ typs[74] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, nil)
+ typs[75] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
+ typs[76] = typChan(typs[2], Csend)
+ typs[77] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, nil)
+ typs[78] = typArray(typs[0], 3)
+ typs[79] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[78]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
+ typs[80] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil)
+ typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
+ typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
+ typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
+ typs[84] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
+ typs[85] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[73])}, []*Node{anonfield(typs[11])})
+ typs[86] = typPtr(typs[11])
+ typs[87] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[86]), anonfield(typs[73])}, []*Node{anonfield(typs[11])})
+ typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil)
+ typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[76]), anonfield(typs[3])}, nil)
+ typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[73]), anonfield(typs[3]), anonfield(typs[86])}, nil)
+ typs[91] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])})
+ typs[92] = typSlice(typs[2])
+ typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[92])})
+ typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[92])})
+ typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[92]), anonfield(typs[32])}, []*Node{anonfield(typs[92])})
+ typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[49])}, nil)
+ typs[97] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[49])}, nil)
+ typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[49])}, []*Node{anonfield(typs[11])})
+ typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
+ typs[100] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
+ typs[101] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
+ typs[102] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
+ typs[103] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
+ typs[104] = Types[TUINT32]
+ typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[104])})
+ typs[106] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
+ typs[107] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
+ typs[108] = functype(nil, []*Node{anonfield(typs[104])}, []*Node{anonfield(typs[13])})
+ typs[109] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
+ typs[110] = functype(nil, []*Node{anonfield(typs[49])}, nil)
+ typs[111] = functype(nil, []*Node{anonfield(typs[49]), anonfield(typs[49])}, nil)
return typs[:]
}
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index cdd8d96..b89f0a3 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -87,8 +87,10 @@
func panicdottypeI(have, want, iface *byte)
func panicnildottype(want *byte)
-func ifaceeq(i1 any, i2 any) (ret bool)
-func efaceeq(i1 any, i2 any) (ret bool)
+// interface equality. Type/itab pointers are already known to be equal, so
+// we only need to pass one.
+func ifaceeq(tab *uintptr, x, y unsafe.Pointer) (ret bool)
+func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool)
// *byte is really *runtime.Type
func makemap(mapType *byte, hint int64, mapbuf *any, bucketbuf *any) (hmap map[any]any)
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 32e5be1..63573f9 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1560,24 +1560,29 @@
n.Right = cheapexpr(n.Right, init)
n.Left = cheapexpr(n.Left, init)
- fn = substArgTypes(fn, n.Right.Type, n.Left.Type)
- r := mkcall1(fn, n.Type, init, n.Left, n.Right)
- // TODO(marvin): Fix Node.EType type union.
- if Op(n.Etype) == ONE {
- r = nod(ONOT, r, nil)
- }
+ lt := nod(OITAB, n.Left, nil)
+ rt := nod(OITAB, n.Right, nil)
+ ld := nod(OIDATA, n.Left, nil)
+ rd := nod(OIDATA, n.Right, nil)
+ ld.Type = Types[TUNSAFEPTR]
+ rd.Type = Types[TUNSAFEPTR]
+ ld.Typecheck = 1
+ rd.Typecheck = 1
+ call := mkcall1(fn, n.Type, init, lt, ld, rd)
- // check itable/type before full compare.
+ // Check itable/type before full compare.
+ // Note: short-circuited because order matters.
// TODO(marvin): Fix Node.EType type union.
+ var cmp *Node
if Op(n.Etype) == OEQ {
- r = nod(OANDAND, nod(OEQ, nod(OITAB, n.Left, nil), nod(OITAB, n.Right, nil)), r)
+ cmp = nod(OANDAND, nod(OEQ, lt, rt), call)
} else {
- r = nod(OOROR, nod(ONE, nod(OITAB, n.Left, nil), nod(OITAB, n.Right, nil)), r)
+ cmp = nod(OOROR, nod(ONE, lt, rt), nod(ONOT, call, nil))
}
- r = typecheck(r, Erv)
- r = walkexpr(r, init)
- r.Type = n.Type
- n = r
+ cmp = typecheck(cmp, Erv)
+ cmp = walkexpr(cmp, init)
+ cmp.Type = n.Type
+ n = cmp
case OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT, OPTRLIT:
if isStaticCompositeLiteral(n) {
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
index 5c378c6..504be61 100644
--- a/src/runtime/alg.go
+++ b/src/runtime/alg.go
@@ -206,16 +206,16 @@
return *(*string)(p) == *(*string)(q)
}
func interequal(p, q unsafe.Pointer) bool {
- return ifaceeq(*(*iface)(p), *(*iface)(q))
+ x := *(*iface)(p)
+ y := *(*iface)(q)
+ return x.tab == y.tab && ifaceeq(x.tab, x.data, y.data)
}
func nilinterequal(p, q unsafe.Pointer) bool {
- return efaceeq(*(*eface)(p), *(*eface)(q))
+ x := *(*eface)(p)
+ y := *(*eface)(q)
+ return x._type == y._type && efaceeq(x._type, x.data, y.data)
}
-func efaceeq(x, y eface) bool {
- t := x._type
- if t != y._type {
- return false
- }
+func efaceeq(t *_type, x, y unsafe.Pointer) bool {
if t == nil {
return true
}
@@ -224,27 +224,23 @@
panic(errorString("comparing uncomparable type " + t.string()))
}
if isDirectIface(t) {
- return eq(noescape(unsafe.Pointer(&x.data)), noescape(unsafe.Pointer(&y.data)))
+ return eq(noescape(unsafe.Pointer(&x)), noescape(unsafe.Pointer(&y)))
}
- return eq(x.data, y.data)
+ return eq(x, y)
}
-func ifaceeq(x, y iface) bool {
- xtab := x.tab
- if xtab != y.tab {
- return false
- }
- if xtab == nil {
+func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
+ if tab == nil {
return true
}
- t := xtab._type
+ t := tab._type
eq := t.alg.equal
if eq == nil {
panic(errorString("comparing uncomparable type " + t.string()))
}
if isDirectIface(t) {
- return eq(noescape(unsafe.Pointer(&x.data)), noescape(unsafe.Pointer(&y.data)))
+ return eq(noescape(unsafe.Pointer(&x)), noescape(unsafe.Pointer(&y)))
}
- return eq(x.data, y.data)
+ return eq(x, y)
}
// Testing adapters for hash quality tests (see hash_test.go)
diff --git a/src/runtime/runtime_test.go b/src/runtime/runtime_test.go
index 9febbe6..666bc0a 100644
--- a/src/runtime/runtime_test.go
+++ b/src/runtime/runtime_test.go
@@ -50,6 +50,23 @@
}
}
+var efaceCmp1 interface{}
+var efaceCmp2 interface{}
+
+func BenchmarkEfaceCmpDiff(b *testing.B) {
+ x := 5
+ efaceCmp1 = &x
+ y := 6
+ efaceCmp2 = &y
+ for i := 0; i < b.N; i++ {
+ for j := 0; j < 100; j++ {
+ if efaceCmp1 == efaceCmp2 {
+ b.Fatal("bad comparison")
+ }
+ }
+ }
+}
+
func BenchmarkDefer(b *testing.B) {
for i := 0; i < b.N; i++ {
defer1()