225 lines
3.3 KiB
C++
225 lines
3.3 KiB
C++
#include "stdafx.h"
|
|
#include "defs.h"
|
|
|
|
extern int nsym;
|
|
extern U symtab[];
|
|
extern U *varlist;
|
|
static void untag(U *);
|
|
static void untag_symbols(void);
|
|
static void alloc_next_block(void);
|
|
|
|
#define BLOCK_COUNT 10
|
|
#define BLOCK_SIZE 1000000
|
|
#define MEM (BLOCK_COUNT * BLOCK_SIZE)
|
|
|
|
static U mem[MEM];
|
|
static U *free_list;
|
|
int total_count; // total number of atoms
|
|
int free_count; // number of free atoms
|
|
static int mark;
|
|
|
|
void
|
|
init_alloc(void)
|
|
{
|
|
free_list = nil;
|
|
alloc_next_block();
|
|
}
|
|
|
|
void
|
|
mark_alloc(void)
|
|
{
|
|
mark = total_count - free_count;
|
|
}
|
|
|
|
U *
|
|
alloc(void)
|
|
{
|
|
U *p;
|
|
if (free_list == nil) {
|
|
gc();
|
|
if (free_count < total_count / 2)
|
|
alloc_next_block();
|
|
if (free_list == nil)
|
|
stop("atom space exhausted");
|
|
}
|
|
p = free_list;
|
|
free_list = free_list->u.cons.cdr;
|
|
free_count--;
|
|
return p;
|
|
}
|
|
|
|
U *
|
|
alloc_tensor(int nelem)
|
|
{
|
|
int i;
|
|
U *p;
|
|
p = alloc();
|
|
p->k = TENSOR;
|
|
p->u.tensor = (T *) malloc(sizeof (T) + nelem * sizeof (U *));
|
|
if (p->u.tensor == NULL)
|
|
out_of_memory();
|
|
p->u.tensor->nelem = nelem;
|
|
for (i = 0; i < nelem; i++)
|
|
p->u.tensor->elem[i] = _zero;
|
|
return p;
|
|
}
|
|
|
|
// garbage collector
|
|
|
|
void
|
|
gc(void)
|
|
{
|
|
int i;
|
|
|
|
// tag everything
|
|
|
|
for (i = 0; i < total_count; i++)
|
|
mem[i].tag = 1;
|
|
|
|
// untag what's used
|
|
|
|
untag_symbols(); // must be done first because tag is always zero
|
|
|
|
untag(varlist);
|
|
|
|
untag(p1);
|
|
untag(p2);
|
|
untag(p3);
|
|
untag(p4);
|
|
untag(p5);
|
|
untag(p6);
|
|
untag(p7);
|
|
untag(p8);
|
|
|
|
untag(last);
|
|
|
|
for (i = 0; i < tos; i++)
|
|
untag(stack[i]);
|
|
|
|
for (i = (int) (frame - stack); i < TOS; i++)
|
|
untag(stack[i]);
|
|
|
|
untag(table); // table of integrals
|
|
|
|
// collect everything that's still tagged
|
|
|
|
free_list = nil;
|
|
free_count = 0;
|
|
for (i = mark; i < total_count; i++) {
|
|
if (mem[i].tag) {
|
|
switch (mem[i].k) {
|
|
case TENSOR:
|
|
free(mem[i].u.tensor);
|
|
break;
|
|
case STR:
|
|
free(mem[i].u.str);
|
|
break;
|
|
case NUM:
|
|
mfree(mem[i].u.q.a);
|
|
mfree(mem[i].u.q.b);
|
|
break;
|
|
}
|
|
mem[i].k = 0; // so no more free above
|
|
mem[i].u.cons.cdr = free_list;
|
|
free_list = mem + i;
|
|
free_count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
untag_symbols(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < nsym; i++) {
|
|
untag(symtab[i].u.sym.binding);
|
|
untag(symtab[i].u.sym.binding2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
untag(U *p)
|
|
{
|
|
int i;
|
|
|
|
while (iscons(p) && p->tag == 1) {
|
|
p->tag = 0;
|
|
untag(p->u.cons.car);
|
|
p = p->u.cons.cdr;
|
|
}
|
|
|
|
if (p->tag != 1)
|
|
return;
|
|
|
|
p->tag = 0;
|
|
|
|
if (istensor(p)) {
|
|
for (i = 0; i < p->u.tensor->nelem; i++)
|
|
untag(p->u.tensor->elem[i]);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
int
|
|
count_freelist(void)
|
|
{
|
|
int n;
|
|
U *p;
|
|
n = 0;
|
|
p = freelist;
|
|
while (p != nil) {
|
|
n++;
|
|
p = p->u.cons.cdr;
|
|
}
|
|
return n;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
reset(void)
|
|
{
|
|
int i;
|
|
|
|
// clear symbols
|
|
|
|
nsym = 0;
|
|
|
|
// clear bignums, strings and tensors
|
|
|
|
for (i = 0; i < total_count; i++) {
|
|
if (mem[i].k == TENSOR)
|
|
free(mem[i].u.tensor);
|
|
else if (mem[i].k == STR)
|
|
free(mem[i].u.str);
|
|
else if (mem[i].k == NUM) {
|
|
mfree(mem[i].u.q.a);
|
|
mfree(mem[i].u.q.b);
|
|
}
|
|
mem[i].k = 0;
|
|
}
|
|
|
|
total_count = 0;
|
|
free_count = 0;
|
|
|
|
init();
|
|
|
|
defn();
|
|
}
|
|
|
|
static void
|
|
alloc_next_block(void)
|
|
{
|
|
int i, j;
|
|
if (total_count == MEM)
|
|
return;
|
|
j = total_count;
|
|
total_count += BLOCK_SIZE;
|
|
for (i = j; i < total_count - 1; i++) {
|
|
mem[i].k = 0; // so no free in gc
|
|
mem[i].u.cons.cdr = mem + i + 1;
|
|
}
|
|
mem[total_count - 1].u.cons.cdr = free_list;
|
|
free_list = mem + j;
|
|
free_count += BLOCK_SIZE;
|
|
}
|