]> Cypherpunks repositories - gostls13.git/commitdiff
gc: make string x + y + z + ... + w efficient
authorRuss Cox <rsc@golang.org>
Sun, 12 Sep 2010 04:53:04 +0000 (00:53 -0400)
committerRuss Cox <rsc@golang.org>
Sun, 12 Sep 2010 04:53:04 +0000 (00:53 -0400)
1 malloc per concatenation.

R=ken2
CC=golang-dev
https://golang.org/cl/2124045

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

index ce86e12e5f61b912bb50e4dd66f430fc61052fb3..12f870d7812b474736a6009b22f08bd3237284be 100644 (file)
@@ -20,7 +20,7 @@ char *runtimeimport =
        "func \"\".printnl ()\n"
        "func \"\".printsp ()\n"
        "func \"\".printf ()\n"
-       "func \"\".catstring (? string, ? string) string\n"
+       "func \"\".concatstring ()\n"
        "func \"\".cmpstring (? string, ? string) int\n"
        "func \"\".slicestring (? string, ? int, ? int) string\n"
        "func \"\".slicestring1 (? string, ? int) string\n"
index 253134476e5377d14ffa4f6a813558e6575f96f7..36ed7e96fff76a301739c52ec1fbd84012ca4d80 100644 (file)
@@ -33,7 +33,9 @@ func printnl()
 func printsp()
 func printf()
 
-func catstring(string, string) string
+// filled in by compiler: int n, string, string, ...
+func concatstring()
+
 func cmpstring(string, string) int
 func slicestring(string, int, int) string
 func slicestring1(string, int) string
index fc8f19ec132cdb8ed416ef98f9c3f729a1c608a6..803977482e219d8ea998545b1c0702a4e22038e3 100644 (file)
@@ -17,6 +17,7 @@ static        void    heapmoves(void);
 static NodeList*       paramstoheap(Type **argin, int out);
 static NodeList*       reorder1(NodeList*);
 static NodeList*       reorder3(NodeList*);
+static Node*   addstr(Node*, NodeList**);
 
 static NodeList*       walkdefstack;
 
@@ -1205,10 +1206,7 @@ walkexpr(Node **np, NodeList **init)
                goto ret;
 
        case OADDSTR:
-               // sys_catstring(s1, s2)
-               n = mkcall("catstring", n->type, init,
-                       conv(n->left, types[TSTRING]),
-                       conv(n->right, types[TSTRING]));
+               n = addstr(n, init);
                goto ret;
 
        case OSLICESTR:
@@ -2234,3 +2232,42 @@ mapfn(char *name, Type *t)
        argtype(fn, t->type);
        return fn;
 }
+
+static Node*
+addstr(Node *n, NodeList **init)
+{
+       Node *r, *cat, *typstr;
+       NodeList *in, *args;
+       int i, count;
+       
+       count = 0;
+       for(r=n; r->op == OADDSTR; r=r->left)
+               count++;        // r->right
+       count++;        // r
+
+       // 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));
+
+       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);
+
+       r = nod(OCALL, cat, N);
+       r->list = args;
+       typecheck(&r, Erv);
+       walkexpr(&r, init);
+       r->type = n->type;
+       
+       return r;
+}
index ca76729ec20d6a0acde853767e7a5708948d3040..88f53e2a2efe722ceb06269ff0cb90e613d42d52 100644 (file)
@@ -395,6 +395,7 @@ void        memmove(void*, void*, uint32);
 void*  mal(uintptr);
 uint32 cmpstring(String, String);
 String catstring(String, String);
+String concatstring(int32, String*);
 String gostring(byte*);
 String  gostringn(byte*, int32);
 String gostringnocopy(byte*);
index ec45735164f4e5a5e649e427e586ea10f12c404c..7bf8f8b37c7880ce81abe2efe954c42d7eb945f2 100644 (file)
@@ -114,9 +114,33 @@ catstring(String s1, String s2)
        return s3;
 }
 
+String
+concatstring(int32 n, String *s)
+{
+       int32 i, l;
+       String out;
+
+       l = 0;
+       for(i=0; i<n; i++) {
+               if(l + s[i].len < l)
+                       throw("string concatenation too long");
+               l += s[i].len;
+       }
+       
+       out = gostringsize(l);
+       l = 0;
+       for(i=0; i<n; i++) {
+               mcpy(out.str+l, s[i].str, s[i].len);
+               l += s[i].len;
+       }
+       return out;
+}
 
-func catstring(s1 String, s2 String) (s3 String) {
-       s3 = catstring(s1, s2);
+#pragma textflag 7
+// s1 is the first of n strings.
+// the output string follows.
+func concatstring(n int32, s1 String) {
+       (&s1)[n] = concatstring(n, &s1);
 }
 
 uint32