mirror of
https://github.com/golang/go
synced 2024-10-04 06:21:23 -06: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 @\"\".printnl ()\n"
|
||||||
"func @\"\".printsp ()\n"
|
"func @\"\".printsp ()\n"
|
||||||
"func @\"\".goprintf ()\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 @\"\".cmpstring (? string, ? string) (? int)\n"
|
||||||
"func @\"\".eqstring (? string, ? string) (? bool)\n"
|
"func @\"\".eqstring (? string, ? string) (? bool)\n"
|
||||||
"func @\"\".intstring (? int64) (? string)\n"
|
"func @\"\".intstring (? int64) (? string)\n"
|
||||||
|
@ -36,8 +36,11 @@ func printnl()
|
|||||||
func printsp()
|
func printsp()
|
||||||
func goprintf()
|
func goprintf()
|
||||||
|
|
||||||
// filled in by compiler: int n, string, string, ...
|
func concatstring2(string, string) string
|
||||||
func concatstring()
|
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 cmpstring(string, string) int
|
||||||
func eqstring(string, string) bool
|
func eqstring(string, string) bool
|
||||||
|
@ -2558,33 +2558,39 @@ mapfndel(char *name, Type *t)
|
|||||||
static Node*
|
static Node*
|
||||||
addstr(Node *n, NodeList **init)
|
addstr(Node *n, NodeList **init)
|
||||||
{
|
{
|
||||||
Node *r, *cat, *typstr;
|
Node *r, *cat, *slice;
|
||||||
NodeList *in, *args;
|
NodeList *args;
|
||||||
int i, count;
|
int count;
|
||||||
|
Type *t;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for(r=n; r->op == OADDSTR; r=r->left)
|
for(r=n; r->op == OADDSTR; r=r->left)
|
||||||
count++; // r->right
|
count++; // r->right
|
||||||
count++; // r
|
count++; // r
|
||||||
|
if(count < 2)
|
||||||
|
yyerror("addstr count %d too small", count);
|
||||||
|
|
||||||
// prepare call of runtime.catstring of type int, string, string, string
|
// build list of string arguments
|
||||||
// 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;
|
args = nil;
|
||||||
for(r=n; r->op == OADDSTR; r=r->left)
|
for(r=n; r->op == OADDSTR; r=r->left)
|
||||||
args = concat(list1(conv(r->right, types[TSTRING])), args);
|
args = concat(list1(conv(r->right, types[TSTRING])), args);
|
||||||
args = concat(list1(conv(r, 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 = nod(OCALL, cat, N);
|
||||||
r->list = args;
|
r->list = args;
|
||||||
typecheck(&r, Erv);
|
typecheck(&r, Erv);
|
||||||
|
@ -179,14 +179,35 @@ concatstring(intgo n, String *s)
|
|||||||
return out;
|
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
|
#pragma textflag NOSPLIT
|
||||||
void
|
func concatstring2(s1 String, s2 String) (res String) {
|
||||||
runtime·concatstring(intgo n, String s1, ...)
|
USED(&s2);
|
||||||
{
|
res = concatstring(2, &s1);
|
||||||
(&s1)[n] = concatstring(n, &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) {
|
func eqstring(s1 String, s2 String) (v bool) {
|
||||||
|
Loading…
Reference in New Issue
Block a user