Skip to content

Commit f913651

Browse files
authored
Merge pull request #205 from jpco/pspace
Allocate memory from the parser in "pspace", not GC space
2 parents abad6b7 + a578f4b commit f913651

File tree

12 files changed

+241
-58
lines changed

12 files changed

+241
-58
lines changed

es.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ extern List *sortlist(List *list);
136136

137137
/* tree.c */
138138

139-
extern Tree *mk(NodeKind VARARGS);
139+
extern Tree *gcmk(NodeKind VARARGS); /* gcalloc a tree node */
140140

141141

142142
/* closure.c */
@@ -404,6 +404,12 @@ extern void gcenable(void); /* enable collections */
404404
extern void gcdisable(void); /* disable collections */
405405
extern Boolean gcisblocked(void); /* is collection disabled? */
406406

407+
/* operations with pspace, the explicitly-collected gc space for parse tree building */
408+
extern void *palloc(size_t n, Tag *t); /* allocate n with collection tag t, but in pspace */
409+
extern void *pseal(void *p); /* collect pspace into gcspace with root p */
410+
extern char *pdup(const char *s); /* copy a 0-terminated string into pspace */
411+
extern char *pndup(const char *s, size_t n); /* copy a counted string into pspace */
412+
407413

408414
/*
409415
* garbage collector tags

gc.c

Lines changed: 156 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ struct Space {
1919
#define INSPACE(p, sp) ((sp)->bot <= (char *) (p) && (char *) (p) < (sp)->top)
2020

2121
#define MIN_minspace 10000
22+
#define MIN_minpspace 1000
2223

2324
#if GCPROTECT
24-
#define NSPACES 10
25+
#define NSPACES 12
26+
#define FIRSTSPACE 1
2527
#endif
2628

2729
#if HAVE_SYSCONF
@@ -38,12 +40,13 @@ int gcblocked = 0;
3840
Tag StringTag;
3941

4042
/* own variables */
41-
static Space *new, *old;
43+
static Space *new, *old, *pspace;
4244
#if GCPROTECT
4345
static Space *spaces;
4446
#endif
4547
static Root *globalrootlist, *exceptionrootlist;
4648
static size_t minspace = MIN_minspace; /* minimum number of bytes in a new space */
49+
static size_t minpspace = MIN_minpspace;
4750

4851

4952
/*
@@ -136,14 +139,15 @@ static void initmmu(void) {
136139
#if GCPROTECT
137140

138141
/* mkspace -- create a new ``half'' space in debugging mode */
139-
static Space *mkspace(Space *space, Space *next) {
142+
static Space *mkspace(Space *space, Space *next, size_t size) {
140143
assert(space == NULL || (&spaces[0] <= space && space < &spaces[NSPACES]));
141144

145+
/* find and clear out any existing/next spaces */
142146
if (space != NULL) {
143147
Space *sp;
144148
if (space->bot == NULL)
145149
sp = NULL;
146-
else if ((size_t) SPACESIZE(space) < minspace)
150+
else if ((size_t) SPACESIZE(space) < size)
147151
sp = space;
148152
else {
149153
sp = space->next;
@@ -160,12 +164,13 @@ static Space *mkspace(Space *space, Space *next) {
160164
}
161165
}
162166

167+
/* build new space (or set up existing &space[n]) */
163168
if (space == NULL) {
164169
space = ealloc(sizeof (Space));
165170
memzero(space, sizeof (Space));
166171
}
167172
if (space->bot == NULL) {
168-
size_t n = PAGEROUND(minspace);
173+
size_t n = PAGEROUND(size);
169174
space->bot = take(n);
170175
space->top = space->bot + n / (sizeof (*space->bot));
171176
}
@@ -175,20 +180,23 @@ static Space *mkspace(Space *space, Space *next) {
175180

176181
return space;
177182
}
178-
#define newspace(next) mkspace(NULL, next)
183+
#define newspace(next) mkspace(NULL, next, minspace)
184+
#define newpspace(next) mkspace(NULL, next, minpspace)
179185

180186
#else /* !GCPROTECT */
181187

182188
/* newspace -- create a new ``half'' space */
183-
static Space *newspace(Space *next) {
184-
size_t n = ALIGN(minspace);
189+
static Space *newspacesz(Space *next, size_t size) {
190+
size_t n = ALIGN(size);
185191
Space *space = ealloc(sizeof (Space) + n);
186192
space->bot = (void *) &space[1];
187193
space->top = (void *) (((char *) space->bot) + n);
188194
space->current = space->bot;
189195
space->next = next;
190196
return space;
191197
}
198+
#define newspace(next) newspacesz(next, minspace)
199+
#define newpspace(next) newspacesz(next, minpspace)
192200

193201
#endif /* !GCPROTECT */
194202

@@ -273,12 +281,20 @@ extern void exceptionunroot(void) {
273281
#define FOLLOWTO(p) ((Tag *) (((char *) p) + 1))
274282
#define FOLLOW(tagp) ((void *) (((char *) tagp) - 1))
275283

284+
/* TODO: remove pmode: it's the Wrong Thing */
285+
static Boolean pmode = FALSE;
286+
276287
/* forward -- forward an individual pointer from old space */
277288
extern void *forward(void *p) {
278289
Tag *tag;
279290
void *np;
280291

281-
if (!isinspace(old, p)) {
292+
if (pmode && !isinspace(pspace, p)) {
293+
VERBOSE(("GC %8ux : <<not in pspace>>\n", p));
294+
return p;
295+
}
296+
297+
if (!pmode && !isinspace(old, p)) {
282298
VERBOSE(("GC %8ux : <<not in old space>>\n", p));
283299
return p;
284300
}
@@ -297,6 +313,12 @@ extern void *forward(void *p) {
297313
VERBOSE(("%s -> %8ux (forwarded)\n", tag->typename, np));
298314
TAG(p) = FOLLOWTO(np);
299315
}
316+
317+
if (pmode) {
318+
tag = TAG(np);
319+
(*tag->scan)(np);
320+
}
321+
300322
return np;
301323
}
302324

@@ -395,8 +417,8 @@ extern void gc(void) {
395417
for (; new->next != NULL; new = new->next)
396418
;
397419
if (++new >= &spaces[NSPACES])
398-
new = &spaces[0];
399-
new = mkspace(new, NULL);
420+
new = &spaces[FIRSTSPACE];
421+
new = mkspace(new, NULL, minspace);
400422
#else
401423
new = newspace(NULL);
402424
#endif
@@ -425,7 +447,7 @@ extern void gc(void) {
425447
#if GCINFO
426448
if (gcinfo)
427449
eprint(
428-
"[GC: old %8d live %8d min %8d (pid %5d)]\n",
450+
"[ GC: old %8d live %8d min %8d (pid %5d)]\n",
429451
olddata, livedata, minspace, getpid()
430452
);
431453
#endif
@@ -439,15 +461,91 @@ extern void gc(void) {
439461
} while (new->next != NULL);
440462
}
441463

464+
/* pseal -- collect pspace to new with p as its only root, and return the collected p */
465+
extern void *pseal(void *p) {
466+
size_t psize = 0;
467+
Space *sp;
468+
#if GCINFO
469+
size_t newdata = 0, livedata = 0;
470+
#endif
471+
#if GCPROTECT
472+
Space *base;
473+
#endif
474+
475+
for (sp = pspace; sp != NULL; sp = sp->next)
476+
psize += SPACEUSED(sp);
477+
478+
if (psize == 0)
479+
return p;
480+
481+
/* TODO: this is an overestimate since it counts garbage */
482+
gcreserve(psize);
483+
VERBOSE(("Reserved %d for pspace copy\n", psize));
484+
485+
#if GCINFO
486+
if (gcinfo)
487+
for (sp = new; sp != NULL; sp = sp->next)
488+
newdata += SPACEUSED(sp);
489+
#endif
490+
491+
assert (gcblocked >= 0);
492+
++gcblocked;
493+
494+
#if GCVERBOSE
495+
for (sp = pspace; sp != NULL; sp = sp->next)
496+
VERBOSE(("GC pspace = %ux ... %ux\n", sp->bot, sp->current));
497+
#endif
498+
if (p != NULL) {
499+
VERBOSE(("GC new space = %ux ... %ux\n", new->bot, new->top));
500+
501+
pmode = TRUE;
502+
p = forward(p);
503+
(*(TAG(p))->scan)(p);
504+
pmode = FALSE;
505+
}
506+
507+
#if GCINFO
508+
if (gcinfo) {
509+
for (sp = new; sp != NULL; sp = sp->next)
510+
livedata += SPACEUSED(sp);
511+
eprint(
512+
"[pseal: old %8d live %8d min %8d diff %5d (pid %5d)]\n",
513+
psize, livedata, minpspace, (livedata - newdata), getpid()
514+
);
515+
}
516+
#endif
517+
518+
if (psize > minpspace)
519+
minpspace = psize * 2;
520+
else if (psize < minpspace / 2 && MIN_minpspace <= minpspace / 2)
521+
minpspace /= 2;
522+
523+
#if GCPROTECT
524+
for (base = pspace; base->next != NULL; base = base->next)
525+
;
526+
#endif
527+
deprecate(pspace);
528+
#if GCPROTECT
529+
pspace = mkspace(base, NULL, minpspace);
530+
#else
531+
pspace = newpspace(NULL);
532+
#endif
533+
534+
--gcblocked;
535+
return p;
536+
}
537+
442538
/* initgc -- initialize the garbage collector */
443539
extern void initgc(void) {
444540
#if GCPROTECT
445541
initmmu();
446542
spaces = ealloc(NSPACES * sizeof (Space));
447543
memzero(spaces, NSPACES * sizeof (Space));
448-
new = mkspace(&spaces[0], NULL);
544+
new = mkspace(&spaces[FIRSTSPACE], NULL, minspace);
545+
pspace = mkspace(&spaces[0], NULL, minpspace);
449546
#else
450547
new = newspace(NULL);
548+
pspace = newpspace(NULL);
451549
#endif
452550
old = NULL;
453551
}
@@ -481,6 +579,24 @@ extern void *gcalloc(size_t nbytes, Tag *tag) {
481579
}
482580
}
483581

582+
/* palloc -- allocate an object in pspace */
583+
extern void *palloc(size_t nbytes, Tag *tag) {
584+
size_t n = ALIGN(nbytes + sizeof (Tag *));
585+
assert(tag == NULL || tag->magic == TAGMAGIC);
586+
for (;;) {
587+
Tag **p = (void *) pspace->current;
588+
char *q = ((char *) p) + n;
589+
if (q <= pspace->top) {
590+
pspace->current = q;
591+
*p++ = tag;
592+
return p;
593+
}
594+
if (minpspace < nbytes)
595+
minpspace = nbytes + sizeof (Tag *);
596+
pspace = newpspace(pspace);
597+
}
598+
}
599+
484600

485601
/*
486602
* strings
@@ -503,10 +619,25 @@ extern char *gcndup(const char *s, size_t n) {
503619
RefReturn(result);
504620
}
505621

622+
extern char *pndup(const char *s, size_t n) {
623+
char *ns;
624+
625+
ns = palloc((n + 1) * sizeof (char), &StringTag);
626+
memcpy(ns, s, n);
627+
ns[n] = '\0';
628+
assert(strlen(ns) == n);
629+
630+
return ns;
631+
}
632+
506633
extern char *gcdup(const char *s) {
507634
return gcndup(s, strlen(s));
508635
}
509636

637+
extern char *pdup(const char *s) {
638+
return pndup(s, strlen(s));
639+
}
640+
510641
static void *StringCopy(void *op) {
511642
size_t n = strlen(op) + 1;
512643
char *np = gcalloc(n, &StringTag);
@@ -547,12 +678,24 @@ extern char *sealbuffer(Buffer *buf) {
547678
return s;
548679
}
549680

681+
extern char *psealbuffer(Buffer *buf) {
682+
char *s = pdup(buf->str);
683+
efree(buf);
684+
return s;
685+
}
686+
550687
extern char *sealcountedbuffer(Buffer *buf) {
551688
char *s = gcndup(buf->str, buf->current);
552689
efree(buf);
553690
return s;
554691
}
555692

693+
extern char *psealcountedbuffer(Buffer *buf) {
694+
char *s = pndup(buf->str, buf->current);
695+
efree(buf);
696+
return s;
697+
}
698+
556699
extern Buffer *bufncat(Buffer *buf, const char *s, size_t len) {
557700
while (buf->current + len >= buf->len)
558701
buf = expandbuffer(buf, buf->current + len - buf->len);

gc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ extern Buffer *bufcat(Buffer *buf, const char *s);
5050
extern Buffer *bufputc(Buffer *buf, char c);
5151
extern char *sealbuffer(Buffer *buf);
5252
extern char *sealcountedbuffer(Buffer *buf);
53+
extern char *psealbuffer(Buffer *buf); /* pspace variant of sealbuffer */
54+
extern char *psealcountedbuffer(Buffer *buf); /* pspace variant of sealcountedbuffer */
5355
extern void freebuffer(Buffer *buf);
5456

5557
extern void *forward(void *p);

heredoc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extern Tree *getherevar(void) {
2222
while ((c = GETC()) != EOF && !dnw[c])
2323
buf = bufputc(buf, c);
2424
len = buf->len;
25-
s = sealcountedbuffer(buf);
25+
s = psealcountedbuffer(buf);
2626
if (len == 0) {
2727
yyerror("null variable name in here document");
2828
return NULL;
@@ -54,7 +54,7 @@ extern Tree *snarfheredoc(const char *eof, Boolean quoted) {
5454
if (buf->current == 0 && tree != NULL)
5555
freebuffer(buf);
5656
else
57-
*tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL);
57+
*tailp = treecons(mk(nQword, psealcountedbuffer(buf)), NULL);
5858
break;
5959
}
6060
if (s != (unsigned char *) eof)
@@ -72,7 +72,7 @@ extern Tree *snarfheredoc(const char *eof, Boolean quoted) {
7272
if (buf->current == 0)
7373
freebuffer(buf);
7474
else {
75-
*tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL);
75+
*tailp = treecons(mk(nQword, psealcountedbuffer(buf)), NULL);
7676
tailp = &(*tailp)->CDR;
7777
}
7878
var = getherevar();
@@ -133,7 +133,7 @@ extern Boolean queueheredoc(Tree *t) {
133133
return FALSE;
134134
}
135135

136-
here = gcalloc(sizeof (Here), NULL);
136+
here = palloc(sizeof (Here), NULL);
137137
here->next = hereq;
138138
here->marker = eof;
139139
hereq = here;

0 commit comments

Comments
 (0)