]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: simplify efaceeq and ifaceeq
authorKeith Randall <khr@golang.org>
Fri, 24 Mar 2017 21:03:15 +0000 (14:03 -0700)
committerKeith Randall <khr@golang.org>
Fri, 24 Mar 2017 23:03:09 +0000 (23:03 +0000)
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>
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/walk.go
src/runtime/alg.go
src/runtime/runtime_test.go

index 58d46dd67e668b5eb5071903475462d8227056af..4d67fe285a6e647e88a461e2b11447889d4983c9 100644 (file)
@@ -69,83 +69,83 @@ var runtimeDecls = [...]struct {
        {"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 @@ func runtimeTypes() []*Type {
        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[:]
 }
index cdd8d96745eaebb596a91bd329cbe919af415032..b89f0a3c0220264b3236659c56dbb0b11e588626 100644 (file)
@@ -87,8 +87,10 @@ func panicdottypeE(have, want, iface *byte)
 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)
index 32e5be1be2c2fb800de4260e43dc38def3051d76..63573f9017b5623662d4af9aacffa63eaf272b47 100644 (file)
@@ -1560,24 +1560,29 @@ opswitch:
 
                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)
-               }
-
-               // check itable/type before full compare.
+               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.
+               // 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) {
index 5c378c6a2ab7d84b2756881d7e8a1afa69e59c0b..504be61cd01e5296a8536d4e14b8f06967012fcd 100644 (file)
@@ -206,16 +206,16 @@ func strequal(p, q unsafe.Pointer) bool {
        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 @@ func efaceeq(x, y eface) bool {
                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)
index 9febbe621df4bed5835f6ef0c91ba4a8b329d078..666bc0a546d7f63ea8a5d31318da77127aa0da1e 100644 (file)
@@ -50,6 +50,23 @@ func BenchmarkIfaceCmpNil100(b *testing.B) {
        }
 }
 
+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()