]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: don't copy []byte during string comparison
authorDmitry Vyukov <dvyukov@google.com>
Tue, 27 Jan 2015 20:57:12 +0000 (23:57 +0300)
committerDmitry Vyukov <dvyukov@google.com>
Wed, 28 Jan 2015 19:36:50 +0000 (19:36 +0000)
Currently we allocate a new string during []byte->string conversion
in string comparison expressions. String allocation is unnecessary in
this case, because comparison does memorize the strings for later use.
This change uses slicebytetostringtmp to construct temp string directly
from []byte buffer and passes it to runtime.eqstring.

Change-Id: If00f1faaee2076baa6f6724d245d5b5e0f59b563
Reviewed-on: https://go-review.googlesource.com/3410
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/gc/order.c
src/runtime/string.go
src/runtime/string_test.go

index 2cd155d4d7391550adae6afd109093ac95c5a5de..6603efe8d1f34d520bd1e15291c5c6e9761e892c 100644 (file)
@@ -1031,6 +1031,18 @@ orderexpr(Node **np, Order *order)
                }
                break;
 
+       case OCMPSTR:
+               orderexpr(&n->left, order);
+               orderexpr(&n->right, order);
+               // Mark string(byteSlice) arguments to reuse byteSlice backing
+               // buffer during conversion. String comparison does not
+               // memorize the strings for later use, so it is safe.
+               if(n->left->op == OARRAYBYTESTR)
+                       n->left->op = OARRAYBYTESTRTMP;
+               if(n->right->op == OARRAYBYTESTR)
+                       n->right->op = OARRAYBYTESTRTMP;
+               break;
+
        case OINDEXMAP:
                // key must be addressable
                orderexpr(&n->left, order);
index 8aa0dd076d0ddf233eca152c82f47e3995f02339..6f7de4de1e5d95bc92fa4502b533d0bb306b04a0 100644 (file)
@@ -76,6 +76,7 @@ func slicebytetostringtmp(b []byte) string {
        // First such case is a m[string(k)] lookup where
        // m is a string-keyed map and k is a []byte.
        // Second such case is "<"+string(b)+">" concatenation where b is []byte.
+       // Third such case is string(b)=="foo" comparison where b is []byte.
 
        if raceenabled && len(b) > 0 {
                racereadrangepc(unsafe.Pointer(&b[0]),
index 1551ecc82b68a7a30be2b017fa480092a644c25b..03c8948467ac1e7eebe95ce257f22dd41f19efd1 100644 (file)
@@ -158,3 +158,20 @@ func TestGostringnocopy(t *testing.T) {
                t.Errorf("want %d, got %d", max+9, newmax)
        }
 }
+
+func TestCompareTempString(t *testing.T) {
+       s := "foo"
+       b := []byte(s)
+       n := testing.AllocsPerRun(1000, func() {
+               if string(b) != s {
+                       t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
+               }
+               if string(b) == s {
+               } else {
+                       t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
+               }
+       })
+       if n != 0 {
+               t.Fatalf("want 0 allocs, got %v", n)
+       }
+}