From: Russ Cox Date: Tue, 7 Jan 2014 01:43:44 +0000 (-0500) Subject: cmd/gc: use 100x less memory for []byte("string") X-Git-Tag: go1.3beta1~1045 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d227d680ece216603c31e36ee995b814259325dc;p=gostls13.git cmd/gc: use 100x less memory for []byte("string") []byte("string") was simplifying to []byte{0: 0x73, 1: 0x74, 2: 0x72, 3: 0x69, 4: 0x6e, 5: 0x67}, but that latter form takes up much more memory in the compiler. Preserve the string form and recognize it to turn global variables initialized this way into linker-initialized data. Reduces the compiler memory footprint for a large []byte initialized this way from approximately 10 kB/B to under 100 B/B. See also issue 6643. R=golang-codereviews, r, iant, oleku.konko, dave, gobot, bradfitz CC=golang-codereviews https://golang.org/cl/15930045 --- diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 2e03898cda..a00f5c8ab0 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -1263,6 +1263,7 @@ int duintptr(Sym *s, int off, uint64 v); int dsname(Sym *s, int off, char *dat, int ndat); void dumpobj(void); Sym* stringsym(char*, int); +void slicebytes(Node*, char*, int); LSym* linksym(Sym*); /* diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index c17be5c398..c6ba367647 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -253,3 +253,31 @@ stringsym(char *s, int len) return sym; } + +void +slicebytes(Node *nam, char *s, int len) +{ + int off, n, m; + static int gen; + Sym *sym; + + snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen); + sym = pkglookup(namebuf, localpkg); + sym->def = newname(sym); + + off = 0; + for(n=0; n len-n) + m = len-n; + off = dsname(sym, off, s+n, m); + } + ggloblsym(sym, off, 0, 0); + + if(nam->op != ONAME) + fatal("slicebytes %N", nam); + off = nam->xoffset; + off = dsymptr(nam->sym, off, sym, 0); + off = duintxx(nam->sym, off, len, widthint); + duintxx(nam->sym, off, len, widthint); +} diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index 446b1110ac..59c5097e04 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -378,6 +378,7 @@ staticassign(Node *l, Node *r, NodeList **out) InitPlan *p; InitEntry *e; int i; + Strlit *sval; switch(r->op) { default: @@ -426,6 +427,14 @@ staticassign(Node *l, Node *r, NodeList **out) } break; + case OSTRARRAYBYTE: + if(l->class == PEXTERN && r->left->op == OLITERAL) { + sval = r->left->val.u.sval; + slicebytes(l, sval->s, sval->len); + return 1; + } + break; + case OARRAYLIT: initplan(r); if(isslice(r->type)) { diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 6f8b6adbbf..4d0a636bb9 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -1406,6 +1406,9 @@ reswitch: } break; case OSTRARRAYBYTE: + // do not use stringtoarraylit. + // generated code and compiler memory footprint is better without it. + break; case OSTRARRAYRUNE: if(n->left->op == OLITERAL) stringtoarraylit(&n);