From 83cd4ee0705677c94db0307fbc27c8fc6781ba8c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 May 2009 13:47:40 -0700 Subject: [PATCH] 6g: generate string data as individual symbols, so that 6l can discard strings used by dead code. also, for short strings, generate DUPOK global symbols so that references to, say, "%s: %s" in multiple files result in only a single symbol. R=ken OCL=28361 CL=28361 --- src/cmd/6g/gg.h | 1 + src/cmd/6g/gsubr.c | 8 +- src/cmd/6g/obj.c | 194 ++++++++++++++++++++++++++++++++------------- src/cmd/gc/go.h | 20 +---- src/cmd/gc/lex.c | 3 - src/cmd/gc/obj.c | 38 +-------- 6 files changed, 144 insertions(+), 120 deletions(-) diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index ed2e703dba0..0cebfba469e 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -122,6 +122,7 @@ int isfat(Type*); void sudoclean(void); int sudoaddable(int, Node*, Addr*); void afunclit(Addr*); +void datagostring(Strlit*, Addr*); /* * list.c diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index 25a16a20e12..b29cab30413 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -152,8 +152,6 @@ ggloblsym(Sym *s, int32 width, int dupok) p = gins(AGLOBL, N, N); p->from.type = D_EXTERN; - if(s == symstringl || s == symstringc) - p->from.type = D_STATIC; p->from.index = D_NONE; p->from.sym = s; p->to.type = D_CONST; @@ -1146,11 +1144,7 @@ naddr(Node *n, Addr *a) a->offset = mpgetfix(n->val.u.xval); break; case CTSTR: - a->etype = simtype[n->etype]; - a->sym = symstringl; - a->type = D_STATIC; - a->offset = symstringl->offset; - stringpool(n); + datagostring(n->val.u.sval, a); break; case CTBOOL: a->sym = S; diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c index ac249b6b6d0..bdbf5c76712 100644 --- a/src/cmd/6g/obj.c +++ b/src/cmd/6g/obj.c @@ -261,23 +261,75 @@ dumpfuncs(void) } } +/* deferred DATA output */ +static Prog *strdat; +static Prog *estrdat; +static int gflag; +static Prog *savepc; + +static void +data(void) +{ + gflag = debug['g']; + debug['g'] = 0; + + if(estrdat == nil) { + strdat = mal(sizeof(*pc)); + clearp(strdat); + estrdat = strdat; + } + if(savepc) + fatal("data phase error"); + savepc = pc; + pc = estrdat; +} + +static void +text(void) +{ + if(!savepc) + fatal("text phase error"); + debug['g'] = gflag; + estrdat = pc; + pc = savepc; + savepc = nil; +} + +void +dumpdata(void) +{ + Prog *p; + + if(estrdat == nil) + return; + *pc = *strdat; + if(gflag) + for(p=pc; p!=estrdat; p=p->link) + print("%P\n", p); + pc = estrdat; +} + /* - * dump the characters of the string - * pool into the array symstringc + * make a refer to the data s, s+len + * emitting DATA if needed. */ void -datastring(char *s, int len) +datastring(char *s, int len, Addr *a) { int w; Prog *p; Addr ac, ao; - + static int gen; + struct { + Strlit lit; + char buf[100]; + } tmp; + // string memset(&ao, 0, sizeof(ao)); ao.type = D_STATIC; ao.index = D_NONE; ao.etype = TINT32; - ao.sym = symstringc; ao.offset = 0; // fill in // constant @@ -286,13 +338,37 @@ datastring(char *s, int len) ac.index = D_NONE; ac.offset = 0; // fill in + // huge strings are made static to avoid long names. + if(len > 100) { + snprint(namebuf, sizeof(namebuf), ".string.%d", gen++); + ao.sym = lookup(namebuf); + ao.type = D_STATIC; + } else { + if(len > 0 && s[len-1] == '\0') + len--; + tmp.lit.len = len; + memmove(tmp.lit.s, s, len); + tmp.lit.s[len] = '\0'; + len++; + snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit); + ao.sym = pkglookup(namebuf, "string"); + ao.type = D_EXTERN; + } + *a = ao; + + // only generate data the first time. + if(ao.sym->uniq) + return; + ao.sym->uniq = 1; + + data(); for(w=0; w+oo, [NSNAME], $"xxx" + // DATA s+w, [NSNAME], $"xxx" p->from = ao; - p->from.offset = stringc; + p->from.offset = w; p->from.scale = NSNAME; if(w+8 > len) @@ -302,25 +378,25 @@ datastring(char *s, int len) p->to.type = D_SCONST; p->to.offset = len; memmove(p->to.sval, s+w, p->from.scale); - stringc += p->from.scale; } + p = pc; + ggloblsym(ao.sym, len, ao.type == D_EXTERN); + if(ao.type == D_STATIC) + p->from.type = D_STATIC; + text(); } /* - * dump the strings into thye pool - * symstingl that consists of a pointer - * to the characters and a count + * make a refer to the string sval, + * emitting DATA if needed. */ void -dumpstrings(void) +datagostring(Strlit *sval, Addr *a) { - Pool *l; Prog *p; Addr ac, ao, ap; - int32 wi, wp, ws; - - if(poolist == nil) - return; + int32 wi, wp; + static int gen; memset(&ac, 0, sizeof(ac)); memset(&ao, 0, sizeof(ao)); @@ -332,49 +408,61 @@ dumpstrings(void) ac.offset = 0; // fill in // string len+ptr - ao.type = D_STATIC; + ao.type = D_STATIC; // fill in ao.index = D_NONE; ao.etype = TINT32; - ao.sym = symstringl; - ao.offset = 0; // fill in + ao.sym = nil; // fill in // $string len+ptr + datastring(sval->s, sval->len, &ap); + ap.index = ap.type; ap.type = D_ADDR; - ap.index = D_STATIC; ap.etype = TINT32; - ap.sym = symstringc; - ap.offset = 0; // fill in wi = types[TUINT32]->width; wp = types[tptr]->width; - ws = types[TSTRING]->width; - - // lay out (count+string) - for(l=poolist; l!=nil; l=l->link) { - - // .stringl<>+ol, wp, $.stringc<>+oc - p = pc; - gins(ADATA, N, N); - p->from = ao; - p->from.offset = stringl; - p->from.scale = wp; - p->to = ap; - p->to.offset = stringc; - stringl += wp; - - // .stringl<>+ol, wi, $len - p = pc; - gins(ADATA, N, N); - p->from = ao; - p->from.offset = stringl; - p->from.scale = wi; - p->to = ac; - p->to.offset = l->sval->len; - stringl += wi; - - stringl = rnd(stringl, ws); - datastring(l->sval->s, l->sval->len); + + if(ap.index == D_STATIC) { + // huge strings are made static to avoid long names + snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen); + ao.sym = lookup(namebuf); + ao.type = D_STATIC; + } else { + // small strings get named by their contents, + // so that multiple modules using the same string + // can share it. + snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval); + ao.sym = pkglookup(namebuf, "go.string"); + ao.type = D_EXTERN; } + + *a = ao; + if(ao.sym->uniq) + return; + ao.sym->uniq = 1; + + data(); + // DATA gostring, wp, $cstring + p = pc; + gins(ADATA, N, N); + p->from = ao; + p->from.scale = wp; + p->to = ap; + + // DATA gostring+wp, wi, $len + p = pc; + gins(ADATA, N, N); + p->from = ao; + p->from.offset = wp; + p->from.scale = wi; + p->to = ac; + p->to.offset = sval->len; + + p = pc; + ggloblsym(ao.sym, types[TSTRING]->width, ao.type == D_EXTERN); + if(ao.type == D_STATIC) + p->from.type = D_STATIC; + text(); } int @@ -390,14 +478,12 @@ dstringptr(Sym *s, int off, char *str) p->from.offset = off; p->from.scale = widthptr; + datastring(str, strlen(str)+1, &p->to); + p->to.index = p->to.type; p->to.type = D_ADDR; - p->to.index = D_STATIC; p->to.etype = TINT32; - p->to.sym = symstringc; - p->to.offset = stringc; off += widthptr; - datastring(str, strlen(str)+1); return off; } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index cdf2e2f1f96..5b0da4cad21 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -463,20 +463,6 @@ struct Sig Sig* link; }; -typedef struct Pool Pool; -struct Pool -{ - Strlit* sval; - Pool* link; -}; - -EXTERN Pool* poolist; -EXTERN Pool* poolast; -EXTERN Sym* symstringl; // string literals -EXTERN Sym* symstringc; // string characters -EXTERN int32 stringl; // size of string literals -EXTERN int32 stringc; // size of string characters - typedef struct Io Io; struct Io { @@ -785,7 +771,6 @@ int brrev(int); void setmaxarg(Type*); Sig* lsort(Sig*, int(*)(Sig*, Sig*)); int dotoffset(Node*, int*, Node**); -void stringpool(Node*); void tempname(Node*, Type*); int Econv(Fmt*); @@ -1029,7 +1014,6 @@ Plist* newplist(void); * obj.c */ void Bputdot(Biobuf *b); -void dumpfuncs(void); void dumpglobls(void); void dumpobj(void); void ieeedtod(uint64 *ieee, double native); @@ -1060,17 +1044,15 @@ int isfat(Type*); void clearfat(Node *n); void cgen(Node*, Node*); void gused(Node*); -void dumpstrings(void); void dumpsignatures(void); void dumpfuncs(void); +void dumpdata(void); void ggloblnod(Node *nam, int32 width); void ggloblsym(Sym *s, int32 width, int dupok); void zfile(Biobuf *b, char *p, int n); void zhist(Biobuf *b, int line, vlong offset); void zname(Biobuf *b, Sym *s, int t); -void dumpstrings(void); void nopout(Prog*); -void datastring(char *s, int len); int dstringptr(Sym *s, int off, char *str); int dsymptr(Sym *s, int off, Sym *x); int duint16(Sym *s, int off, uint32 v); diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 6457bf12a23..b84d91ba74d 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -66,9 +66,6 @@ main(int argc, char *argv[]) lexinit(); typeinit(LBASETYPE); - symstringl = lookup(".stringl"); // string literals (ptr to char and count) - symstringc = lookup(".stringc"); // string characters - lineno = 1; block = 1; blockgen = 1; diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index 037cd4d4822..6c67b6dfa84 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -28,8 +28,8 @@ dumpobj(void) newplist(); dumpglobls(); - dumpstrings(); dumpsignatures(); + dumpdata(); dumpfuncs(); Bterm(bout); @@ -483,42 +483,6 @@ dumpsignatures(void) //print("s=%S\n", s); dumpsigt(progt, ifacet, rcvrt, methodt, s); } - - if(stringl > 0) { - stringl = rnd(stringl, maxround); - ggloblsym(symstringl, stringl, 0); - if(stringc == 0) - stringc = 1; - } - if(stringc > 0) { - stringc = rnd(stringc, maxround); - ggloblsym(symstringc, stringc, 0); - } -} - -void -stringpool(Node *n) -{ - Pool *p; - - if(n->op != OLITERAL || n->val.ctype != CTSTR) { - if(n->val.ctype == CTNIL) - return; - fatal("stringpool: not string %N", n); - } - - p = mal(sizeof(*p)); - - p->sval = n->val.u.sval; - p->link = nil; - - if(poolist == nil) - poolist = p; - else - poolast->link = p; - poolast = p; - - symstringl->offset += types[TSTRING]->width; } Sig*