diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index 58d46dd67e..4d67fe285a 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -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[:] } diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go index cdd8d96745..b89f0a3c02 100644 --- a/src/cmd/compile/internal/gc/builtin/runtime.go +++ b/src/cmd/compile/internal/gc/builtin/runtime.go @@ -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) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 32e5be1be2..63573f9017 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -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) - } + 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 5c378c6a2a..504be61cd0 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -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) diff --git a/src/runtime/runtime_test.go b/src/runtime/runtime_test.go index 9febbe621d..666bc0a546 100644 --- a/src/runtime/runtime_test.go +++ b/src/runtime/runtime_test.go @@ -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()