]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: get rid of concatstring's vararg C argument.
authorKeith Randall <khr@golang.org>
Tue, 3 Dec 2013 18:39:19 +0000 (10:39 -0800)
committerKeith Randall <khr@golang.org>
Tue, 3 Dec 2013 18:39:19 +0000 (10:39 -0800)
Pass as a slice of strings instead.  For 2-5 strings, implement
dedicated routines so no slices are needed.

static call counts in the go binary:
 2 strings: 342 occurrences
 3 strings:  98
 4 strings:  30
 5 strings:  13
6+ strings:  14

Why?  C varags, bad for stack scanning and copying.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/36380043

src/cmd/gc/builtin.c
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/pkg/runtime/string.goc

index 7d4b3e5590dea7b1714e5f9d7237b8779f11cf79..f88659ee00558b1b0bd14d531cd100aa9e23912d 100644 (file)
@@ -23,7 +23,11 @@ char *runtimeimport =
        "func @\"\".printnl ()\n"
        "func @\"\".printsp ()\n"
        "func @\"\".goprintf ()\n"
-       "func @\"\".concatstring ()\n"
+       "func @\"\".concatstring2 (? string, ? string) (? string)\n"
+       "func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
+       "func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
+       "func @\"\".concatstring5 (? string, ? string, ? string, ? string, ? string) (? string)\n"
+       "func @\"\".concatstrings (? []string) (? string)\n"
        "func @\"\".cmpstring (? string, ? string) (? int)\n"
        "func @\"\".eqstring (? string, ? string) (? bool)\n"
        "func @\"\".intstring (? int64) (? string)\n"
index 34c9e9016946ff758bd40868f33bbc198c137be5..662eb8251fcd7a34c05a2df428f7dd2f68d824b4 100644 (file)
@@ -36,8 +36,11 @@ func printnl()
 func printsp()
 func goprintf()
 
-// filled in by compiler: int n, string, string, ...
-func concatstring()
+func concatstring2(string, string) string
+func concatstring3(string, string, string) string
+func concatstring4(string, string, string, string) string
+func concatstring5(string, string, string, string, string) string
+func concatstrings([]string) string
 
 func cmpstring(string, string) int
 func eqstring(string, string) bool
index 4648b7488734a3ea38b5f35882b47ca72bd778a3..a3647a5a9ee9d538e4da76bb892194c54268e133 100644 (file)
@@ -2558,33 +2558,39 @@ mapfndel(char *name, Type *t)
 static Node*
 addstr(Node *n, NodeList **init)
 {
-       Node *r, *cat, *typstr;
-       NodeList *in, *args;
-       int i, count;
+       Node *r, *cat, *slice;
+       NodeList *args;
+       int count;
+       Type *t;
 
        count = 0;
        for(r=n; r->op == OADDSTR; r=r->left)
                count++;        // r->right
        count++;        // r
+       if(count < 2)
+               yyerror("addstr count %d too small", count);
 
-       // prepare call of runtime.catstring of type int, string, string, string
-       // with as many strings as we have.
-       cat = syslook("concatstring", 1);
-       cat->type = T;
-       cat->ntype = nod(OTFUNC, N, N);
-       in = list1(nod(ODCLFIELD, N, typenod(types[TINT])));    // count
-       typstr = typenod(types[TSTRING]);
-       for(i=0; i<count; i++)
-               in = list(in, nod(ODCLFIELD, N, typstr));
-       cat->ntype->list = in;
-       cat->ntype->rlist = list1(nod(ODCLFIELD, N, typstr));
-
+       // build list of string arguments
        args = nil;
        for(r=n; r->op == OADDSTR; r=r->left)
                args = concat(list1(conv(r->right, types[TSTRING])), args);
        args = concat(list1(conv(r, types[TSTRING])), args);
-       args = concat(list1(nodintconst(count)), args);
 
+       if(count <= 5) {
+               // small numbers of strings use direct runtime helpers.
+               snprint(namebuf, sizeof(namebuf), "concatstring%d", count);
+       } else {
+               // large numbers of strings are passed to the runtime as a slice.
+               strcpy(namebuf, "concatstrings");
+               t = typ(TARRAY);
+               t->type = types[TSTRING];
+               t->bound = -1;
+               slice = nod(OCOMPLIT, N, typenod(t));
+               slice->list = args;
+               slice->esc = EscNone;
+               args = list1(slice);
+       }
+       cat = syslook(namebuf, 1);
        r = nod(OCALL, cat, N);
        r->list = args;
        typecheck(&r, Erv);
index b79acbe1c2f3e058b76757e3e1c9db9e01b51000..57b3546c3f3e76a7b8694dbcbe9bbcb5e1c04fa8 100644 (file)
@@ -179,14 +179,35 @@ concatstring(intgo n, String *s)
        return out;
 }
 
-// NOTE: Cannot use func syntax, because we need the ...,
-// to signal to the garbage collector that this function does
-// not have a fixed size argument count.
 #pragma textflag NOSPLIT
-void
-runtime·concatstring(intgo n, String s1, ...)
-{
-       (&s1)[n] = concatstring(n, &s1);
+func concatstring2(s1 String, s2 String) (res String) {
+       USED(&s2);
+       res = concatstring(2, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstring3(s1 String, s2 String, s3 String) (res String) {
+       USED(&s2);
+       USED(&s3);
+       res = concatstring(3, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstring4(s1 String, s2 String, s3 String, s4 String) (res String) {
+       USED(&s2);
+       USED(&s3);
+       USED(&s4);
+       res = concatstring(4, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstring5(s1 String, s2 String, s3 String, s4 String, s5 String) (res String) {
+       USED(&s2);
+       USED(&s3);
+       USED(&s4);
+       USED(&s5);
+       res = concatstring(5, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstrings(s Slice) (res String) {
+       res = concatstring(s.len, (String*)s.array);
 }
 
 func eqstring(s1 String, s2 String) (v bool) {