Commit f47d403c authored by Russ Cox's avatar Russ Cox

gc: make string x + y + z + ... + w efficient

1 malloc per concatenation.

R=ken2
CC=golang-dev
https://golang.org/cl/2124045
parent 698fb4f1
...@@ -20,7 +20,7 @@ char *runtimeimport = ...@@ -20,7 +20,7 @@ char *runtimeimport =
"func \"\".printnl ()\n" "func \"\".printnl ()\n"
"func \"\".printsp ()\n" "func \"\".printsp ()\n"
"func \"\".printf ()\n" "func \"\".printf ()\n"
"func \"\".catstring (? string, ? string) string\n" "func \"\".concatstring ()\n"
"func \"\".cmpstring (? string, ? string) int\n" "func \"\".cmpstring (? string, ? string) int\n"
"func \"\".slicestring (? string, ? int, ? int) string\n" "func \"\".slicestring (? string, ? int, ? int) string\n"
"func \"\".slicestring1 (? string, ? int) string\n" "func \"\".slicestring1 (? string, ? int) string\n"
......
...@@ -33,7 +33,9 @@ func printnl() ...@@ -33,7 +33,9 @@ func printnl()
func printsp() func printsp()
func printf() func printf()
func catstring(string, string) string // filled in by compiler: int n, string, string, ...
func concatstring()
func cmpstring(string, string) int func cmpstring(string, string) int
func slicestring(string, int, int) string func slicestring(string, int, int) string
func slicestring1(string, int) string func slicestring1(string, int) string
......
...@@ -17,6 +17,7 @@ static void heapmoves(void); ...@@ -17,6 +17,7 @@ static void heapmoves(void);
static NodeList* paramstoheap(Type **argin, int out); static NodeList* paramstoheap(Type **argin, int out);
static NodeList* reorder1(NodeList*); static NodeList* reorder1(NodeList*);
static NodeList* reorder3(NodeList*); static NodeList* reorder3(NodeList*);
static Node* addstr(Node*, NodeList**);
static NodeList* walkdefstack; static NodeList* walkdefstack;
...@@ -1205,10 +1206,7 @@ walkexpr(Node **np, NodeList **init) ...@@ -1205,10 +1206,7 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OADDSTR: case OADDSTR:
// sys_catstring(s1, s2) n = addstr(n, init);
n = mkcall("catstring", n->type, init,
conv(n->left, types[TSTRING]),
conv(n->right, types[TSTRING]));
goto ret; goto ret;
case OSLICESTR: case OSLICESTR:
...@@ -2234,3 +2232,42 @@ mapfn(char *name, Type *t) ...@@ -2234,3 +2232,42 @@ mapfn(char *name, Type *t)
argtype(fn, t->type); argtype(fn, t->type);
return fn; 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;
}
...@@ -395,6 +395,7 @@ void memmove(void*, void*, uint32); ...@@ -395,6 +395,7 @@ void memmove(void*, void*, uint32);
void* mal(uintptr); void* mal(uintptr);
uint32 cmpstring(String, String); uint32 cmpstring(String, String);
String catstring(String, String); String catstring(String, String);
String concatstring(int32, String*);
String gostring(byte*); String gostring(byte*);
String gostringn(byte*, int32); String gostringn(byte*, int32);
String gostringnocopy(byte*); String gostringnocopy(byte*);
......
...@@ -114,9 +114,33 @@ catstring(String s1, String s2) ...@@ -114,9 +114,33 @@ catstring(String s1, String s2)
return s3; 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) { #pragma textflag 7
s3 = catstring(s1, s2); // s1 is the first of n strings.
// the output string follows.
func concatstring(n int32, s1 String) {
(&s1)[n] = concatstring(n, &s1);
} }
uint32 uint32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment