shithub: mlisp

ref: e5cbdb2d92963fccf56980ea7a60ecc2b03204cf
dir: /mem.c/

View raw version
#include "lisp.h"

C cstore[NUMCONS];
F fstore[NUMFW];
word fmark[NUMFW/B2W];

void
mark(C *c)
{
	C *a;
	F *f;
	int n;

tail:
	if(c == nil)
		return;

	/* Mark full word */
	f = (F*)c;
	if(f >= &fstore[0] && f < &fstore[NUMFW]){
		n = f - fstore;
		fmark[n/B2W] |= (word)1 << n%B2W;
		return;
	}

	/* Must be a cons cell */
	if(c >= &cstore[0] && c < &cstore[NUMCONS]){
		if(c->ap & CAR_MARK)
			return;
		a = c->a;
		c->ap |= CAR_MARK;
		if(c->ap & CAR_ATOM){
			if(c->ap & (CAR_NUM|CAR_STR))
				return;
		}else
			mark(a);
		c = c->d;
		goto tail;
	}

	panic("invalid ptr: %p\n", c);
}

void
gc(void)
{
	int i, j;
	C *c, **cp;
	F *f;
	word m;
	int nc, nf;

	/* Mark */
	mark(oblist);
	for(i = 0; i < pdp; i++)
		mark(pdl[i]);
	for(cp = (C**)&temlis; cp < (C**)(&temlis+1); cp++)
		mark(*cp);

	/* Sweep */
	fclist = nil;
	nc = 0;
	for(c = cstore; c < &cstore[NUMCONS]; c++){
		if(c->ap & CAR_MARK)
			c->ap &= ~CAR_MARK;
		else{
			if(c->ap & CAR_ATOM){
				/* special handling for atoms */
				if(c->ap & CAR_STR)
					free(c->str);
			}
			c->a = nil;
			c->d = fclist;
			fclist = c;
			nc++;
		}
	}

	fflist = nil;
	f = fstore;
	nf = 0;
	for(i = 0; i < NUMFW/B2W; i++){
		m = fmark[i];
		fmark[i] = 0;
		for(j = 0; j < B2W; j++){
			if(!(m&1)){
				f->p = fflist;
				fflist = f;
				nf++;
			}
			m >>= 1;
			f++;
		}
	}

//	fprintf(syserr, "reclaimed: %d %d\n", nc, nf);
}