From f47d403cb48f669fe4a6c4ba6bcaaa33eb2e51af Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 12 Sep 2010 00:53:04 -0400 Subject: [PATCH] gc: make string x + y + z + ... + w efficient 1 malloc per concatenation. R=ken2 CC=golang-dev https://golang.org/cl/2124045 --- src/cmd/gc/builtin.c.boot | 2 +- src/cmd/gc/runtime.go | 4 +++- src/cmd/gc/walk.c | 45 ++++++++++++++++++++++++++++++++++---- src/pkg/runtime/runtime.h | 1 + src/pkg/runtime/string.goc | 28 ++++++++++++++++++++++-- 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index ce86e12e5f6..12f870d7812 100644 --- a/src/cmd/gc/builtin.c.boot +++ b/src/cmd/gc/builtin.c.boot @@ -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" diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index 253134476e5..36ed7e96fff 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -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 diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index fc8f19ec132..803977482e2 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -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; intype->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; +} diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index ca76729ec20..88f53e2a2ef 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -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*); diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc index ec45735164f..7bf8f8b37c7 100644 --- a/src/pkg/runtime/string.goc +++ b/src/pkg/runtime/string.goc @@ -114,9 +114,33 @@ catstring(String s1, String s2) return s3; } +String +concatstring(int32 n, String *s) +{ + int32 i, l; + String out; -func catstring(s1 String, s2 String) (s3 String) { - s3 = catstring(s1, s2); + l = 0; + for(i=0; i