From e1366f94ee0b3d40db69cdf42f72d68890cbd74d Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 30 Mar 2015 02:03:03 +0000 Subject: [PATCH] reflect, runtime: check equality, not identity, for method names When dynamically linking Go code, it is no longer safe to assume that strings that end up in method names are identical if they are equal. The performance impact seems to be noise: benchmark old ns/op new ns/op delta BenchmarkAssertI2E2 13.3 13.1 -1.50% BenchmarkAssertE2I 23.5 23.2 -1.28% BenchmarkAssertE2E2Blank 0.83 0.82 -1.20% BenchmarkConvT2ISmall 60.7 60.1 -0.99% BenchmarkAssertI2T 10.2 10.1 -0.98% BenchmarkAssertE2T 10.2 10.3 +0.98% BenchmarkConvT2ESmall 56.7 57.2 +0.88% BenchmarkConvT2ILarge 59.4 58.9 -0.84% BenchmarkConvI2E 13.0 12.9 -0.77% BenchmarkAssertI2E 13.4 13.3 -0.75% BenchmarkConvT2IUintptr 57.9 58.3 +0.69% BenchmarkConvT2ELarge 55.9 55.6 -0.54% BenchmarkAssertI2I 23.8 23.7 -0.42% BenchmarkConvT2EUintptr 55.4 55.5 +0.18% BenchmarkAssertE2E 6.12 6.11 -0.16% BenchmarkAssertE2E2 14.4 14.4 +0.00% BenchmarkAssertE2T2 10.0 10.0 +0.00% BenchmarkAssertE2T2Blank 0.83 0.83 +0.00% BenchmarkAssertE2TLarge 10.7 10.7 +0.00% BenchmarkAssertI2E2Blank 0.83 0.83 +0.00% BenchmarkConvI2I 23.4 23.4 +0.00% Change-Id: I0b3dfc314215a4d4e09eec6b42c1e3ebce33eb56 Reviewed-on: https://go-review.googlesource.com/8239 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/reflect/type.go | 4 ++-- src/runtime/iface.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index 8cfae98e08..48d9b85797 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1150,7 +1150,7 @@ func implements(T, V *rtype) bool { for j := 0; j < len(v.methods); j++ { tm := &t.methods[i] vm := &v.methods[j] - if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.typ == tm.typ { + if *vm.name == *tm.name && vm.pkgPath == tm.pkgPath && vm.typ == tm.typ { if i++; i >= len(t.methods) { return true } @@ -1167,7 +1167,7 @@ func implements(T, V *rtype) bool { for j := 0; j < len(v.methods); j++ { tm := &t.methods[i] vm := &v.methods[j] - if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.mtyp == tm.typ { + if *vm.name == *tm.name && vm.pkgPath == tm.pkgPath && vm.mtyp == tm.typ { if i++; i >= len(t.methods) { return true } diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 0d4989b2e5..656bb4b8e5 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -94,7 +94,7 @@ search: itype := i._type for ; j < nt; j++ { t := &x.mhdr[j] - if t.mtyp == itype && t.name == iname && t.pkgpath == ipkgpath { + if t.mtyp == itype && (t.name == iname || *t.name == *iname) && t.pkgpath == ipkgpath { if m != nil { *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*ptrSize)) = t.ifn }