Skip to content

Commit d227d68

Browse files
committed
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
1 parent 78c16c9 commit d227d68

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

src/cmd/gc/go.h

+1
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,7 @@ int duintptr(Sym *s, int off, uint64 v);
12631263
int dsname(Sym *s, int off, char *dat, int ndat);
12641264
void dumpobj(void);
12651265
Sym* stringsym(char*, int);
1266+
void slicebytes(Node*, char*, int);
12661267
LSym* linksym(Sym*);
12671268

12681269
/*

src/cmd/gc/obj.c

+28
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,31 @@ stringsym(char *s, int len)
253253

254254
return sym;
255255
}
256+
257+
void
258+
slicebytes(Node *nam, char *s, int len)
259+
{
260+
int off, n, m;
261+
static int gen;
262+
Sym *sym;
263+
264+
snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen);
265+
sym = pkglookup(namebuf, localpkg);
266+
sym->def = newname(sym);
267+
268+
off = 0;
269+
for(n=0; n<len; n+=m) {
270+
m = 8;
271+
if(m > len-n)
272+
m = len-n;
273+
off = dsname(sym, off, s+n, m);
274+
}
275+
ggloblsym(sym, off, 0, 0);
276+
277+
if(nam->op != ONAME)
278+
fatal("slicebytes %N", nam);
279+
off = nam->xoffset;
280+
off = dsymptr(nam->sym, off, sym, 0);
281+
off = duintxx(nam->sym, off, len, widthint);
282+
duintxx(nam->sym, off, len, widthint);
283+
}

src/cmd/gc/sinit.c

+9
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ staticassign(Node *l, Node *r, NodeList **out)
378378
InitPlan *p;
379379
InitEntry *e;
380380
int i;
381+
Strlit *sval;
381382

382383
switch(r->op) {
383384
default:
@@ -426,6 +427,14 @@ staticassign(Node *l, Node *r, NodeList **out)
426427
}
427428
break;
428429

430+
case OSTRARRAYBYTE:
431+
if(l->class == PEXTERN && r->left->op == OLITERAL) {
432+
sval = r->left->val.u.sval;
433+
slicebytes(l, sval->s, sval->len);
434+
return 1;
435+
}
436+
break;
437+
429438
case OARRAYLIT:
430439
initplan(r);
431440
if(isslice(r->type)) {

src/cmd/gc/typecheck.c

+3
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,9 @@ typecheck1(Node **np, int top)
14061406
}
14071407
break;
14081408
case OSTRARRAYBYTE:
1409+
// do not use stringtoarraylit.
1410+
// generated code and compiler memory footprint is better without it.
1411+
break;
14091412
case OSTRARRAYRUNE:
14101413
if(n->left->op == OLITERAL)
14111414
stringtoarraylit(&n);

0 commit comments

Comments
 (0)