]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: implement eqstring in assembly.
authorKeith Randall <khr@golang.org>
Tue, 17 Jun 2014 04:00:37 +0000 (21:00 -0700)
committerKeith Randall <khr@golang.org>
Tue, 17 Jun 2014 04:00:37 +0000 (21:00 -0700)
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

src/pkg/runtime/asm_386.s
src/pkg/runtime/asm_amd64.s
src/pkg/runtime/asm_amd64p32.s
src/pkg/runtime/asm_arm.s
src/pkg/runtime/runtime_test.go
src/pkg/runtime/string.goc

index 95312089d97d888ac3086e5ab6655069753969a1..088eecfd33e38c3b36888b7ee75e1be47b69a855 100644 (file)
@@ -1096,6 +1096,28 @@ TEXT runtime·memeq(SB),NOSPLIT,$0-12
        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
index 3c7eaf3433d22e6a2ae5ff65b0a4e2d9353a91dd..b352a5075253a24dc7ddcd7d02389c55727868cc 100644 (file)
@@ -1058,6 +1058,28 @@ TEXT runtime·memeq(SB),NOSPLIT,$0-24
        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
index d47f122836e9fe0dfdc802387d719941ce717e36..afe57340cea4caf25daa9c340024c0042cfd3615 100644 (file)
@@ -715,6 +715,28 @@ TEXT runtime·memeq(SB),NOSPLIT,$0-12
        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
index 1aea9036a78bdfe453b11aaf34760771c6d3f685..2b43ac41bbeda5b9408b0329c0bc4566da5a7c77 100644 (file)
@@ -646,6 +646,33 @@ _next:
        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
index 5a9f52fe0fd1a218737518ba9f5afd3aa083e114..a726f500d101ee1f6cb7e857b1c0d226f04d229a 100644 (file)
@@ -202,3 +202,41 @@ func testSetPanicOnFault(t *testing.T, addr uintptr) {
        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)
+                       }
+               }
+       }
+}
index 97a69d07b1bb73636a28c05302498cee067d6f01..64a1d9064b2bb34789fb5dbee9f2c10e737e5f05 100644 (file)
@@ -206,18 +206,6 @@ func concatstrings(s Slice) (res String) {
        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)
 {