mirror of
https://github.com/golang/go
synced 2024-11-23 16:30:06 -07:00
runtime: get rid of concatstring's vararg C argument.
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
This commit is contained in:
parent
c0f2294577
commit
24699fb05c
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user