BenchmarkCompareStringEqual 10.4 7.33 -29.52%
BenchmarkCompareStringIdentical 3.99 3.67 -8.02%
BenchmarkCompareStringSameLength 9.80 6.84 -30.20%
BenchmarkCompareStringDifferentLength 1.09 0.95 -12.84%
BenchmarkCompareStringBigUnaligned 75220 76071 +1.13%
BenchmarkCompareStringBig 69843 74746 +7.02%
LGTM=bradfitz, josharian
R=golang-codereviews, bradfitz, josharian, dave, khr
CC=golang-codereviews
https://golang.org/cl/
105280044
MOVL count+8(FP), BX
JMP runtime·memeqbody(SB)
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivlaent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-17
+ MOVL s1len+4(FP), AX
+ MOVL s2len+12(FP), BX
+ CMPL AX, BX
+ JNE different
+ MOVL s1str+0(FP), SI
+ MOVL s2str+8(FP), DI
+ CMPL SI, DI
+ JEQ same
+ CALL runtime·memeqbody(SB)
+ MOVB AX, v+16(FP)
+ RET
+same:
+ MOVB $1, v+16(FP)
+ RET
+different:
+ MOVB $0, v+16(FP)
+ RET
+
TEXT bytes·Equal(SB),NOSPLIT,$0-25
MOVL a_len+4(FP), BX
MOVL b_len+16(FP), CX
MOVQ count+16(FP), BX
JMP runtime·memeqbody(SB)
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivlaent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
+ MOVQ s1len+8(FP), AX
+ MOVQ s2len+24(FP), BX
+ CMPQ AX, BX
+ JNE different
+ MOVQ s1str+0(FP), SI
+ MOVQ s2str+16(FP), DI
+ CMPQ SI, DI
+ JEQ same
+ CALL runtime·memeqbody(SB)
+ MOVB AX, v+32(FP)
+ RET
+same:
+ MOVB $1, v+32(FP)
+ RET
+different:
+ MOVB $0, v+32(FP)
+ RET
+
// a in SI
// b in DI
// count in BX
MOVL count+8(FP), BX
JMP runtime·memeqbody(SB)
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivlaent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-17
+ MOVL s1len+4(FP), AX
+ MOVL s2len+12(FP), BX
+ CMPL AX, BX
+ JNE different
+ MOVL s1str+0(FP), SI
+ MOVL s2str+8(FP), DI
+ CMPL SI, DI
+ JEQ same
+ CALL runtime·memeqbody(SB)
+ MOVB AX, v+16(FP)
+ RET
+same:
+ MOVB $1, v+16(FP)
+ RET
+different:
+ MOVB $0, v+16(FP)
+ RET
+
// a in SI
// b in DI
// count in BX
MOVW $0, R0
RET
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivlaent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
+ MOVW s1len+4(FP), R0
+ MOVW s2len+12(FP), R1
+ MOVW $0, R7
+ CMP R0, R1
+ MOVB.NE R7, v+16(FP)
+ RET.NE
+ MOVW s1str+0(FP), R2
+ MOVW s2str+8(FP), R3
+ MOVW $1, R8
+ MOVB R8, v+16(FP)
+ CMP R2, R3
+ RET.EQ
+ ADD R2, R0, R6
+_eqnext:
+ CMP R2, R6
+ RET.EQ
+ MOVBU.P 1(R2), R4
+ MOVBU.P 1(R3), R5
+ CMP R4, R5
+ BEQ _eqnext
+ MOVB R7, v+16(FP)
+ RET
+
// We have to resort to TLS variable to save g(R10) and
// m(R9). One reason is that external code might trigger
// SIGSEGV, and our runtime.sigtramp don't even know we
println(*p)
t.Fatalf("still here - should have faulted on address %#x", addr)
}
+
+func eqstring_generic(s1, s2 string) bool {
+ if len(s1) != len(s2) {
+ return false
+ }
+ // optimization in assembly versions:
+ // if s1.str == s2.str { return true }
+ for i := 0; i < len(s1); i++ {
+ if s1[i] != s2[i] {
+ return false
+ }
+ }
+ return true
+}
+
+func TestEqString(t *testing.T) {
+ // This isn't really an exhaustive test of eqstring, it's
+ // just a convenient way of documenting (via eqstring_generic)
+ // what eqstring does.
+ s := []string{
+ "",
+ "a",
+ "c",
+ "aaa",
+ "ccc",
+ "cccc"[:3], // same contents, different string
+ "1234567890",
+ }
+ for _, s1 := range s {
+ for _, s2 := range s {
+ x := s1 == s2
+ y := eqstring_generic(s1, s2)
+ if x != y {
+ t.Errorf(`eqstring("%s","%s") = %t, want %t`, s1, s2, x, y)
+ }
+ }
+ }
+}
res = concatstring(s.len, (String*)s.array);
}
-func eqstring(s1 String, s2 String) (v bool) {
- if(s1.len != s2.len) {
- v = false;
- return;
- }
- if(s1.str == s2.str) {
- v = true;
- return;
- }
- v = runtime·memeq(s1.str, s2.str, s1.len);
-}
-
int32
runtime·strcmp(byte *s1, byte *s2)
{