factor/native/gc.c

152 lines
3.0 KiB
C
Raw Normal View History

2004-07-16 02:26:21 -04:00
#include "factor.h"
/* Stop-and-copy garbage collection using Cheney's algorithm. */
/* #define GC_DEBUG */
2004-07-16 02:26:21 -04:00
INLINE void gc_debug(char* msg, CELL x) {
#ifdef GC_DEBUG
printf("%s %d\n",msg,x);
#endif
}
2004-08-10 00:58:52 -04:00
/* Given a pointer to oldspace, copy it to newspace. */
2004-08-04 22:43:58 -04:00
void* copy_untagged_object(void* pointer, CELL size)
2004-07-16 02:26:21 -04:00
{
2004-08-04 22:43:58 -04:00
void* newpointer = allot(size);
2004-07-16 02:26:21 -04:00
memcpy(newpointer,pointer,size);
return newpointer;
}
/*
Given a pointer to a tagged pointer to oldspace, copy it to newspace.
If the object has already been copied, return the forwarding
pointer address without copying anything; otherwise, install
a new forwarding pointer.
*/
void copy_object(CELL* handle)
{
CELL pointer = *handle;
CELL tag = TAG(pointer);
CELL header, newpointer;
2004-09-08 02:31:03 -04:00
if(tag == FIXNUM_TYPE || pointer == F)
2004-07-16 02:26:21 -04:00
return;
if(in_zone(&active,pointer))
2004-07-31 14:58:16 -04:00
critical_error("copy_object given newspace ptr",pointer);
2004-07-16 02:26:21 -04:00
header = get(UNTAG(pointer));
if(TAG(header) == GC_COLLECTED)
{
newpointer = UNTAG(header);
gc_debug("FORWARDING",newpointer);
}
2004-08-10 00:58:52 -04:00
else if(TAG(pointer) == GC_COLLECTED)
{
critical_error("asked to copy forwarding pointer",pointer);
newpointer = 0; /* to shut up gcc */
}
2004-07-16 02:26:21 -04:00
else
{
gc_debug("copy_object",pointer);
2004-08-04 22:43:58 -04:00
newpointer = (CELL)copy_untagged_object((void*)UNTAG(pointer),
2004-07-16 02:26:21 -04:00
object_size(pointer));
put(UNTAG(pointer),RETAG(newpointer,GC_COLLECTED));
}
if(tag == GC_COLLECTED)
2004-07-20 02:59:32 -04:00
critical_error("installing forwarding pointer in newspace",newpointer);
2004-07-16 02:26:21 -04:00
*handle = RETAG(newpointer,tag);
}
void collect_object(void)
{
CELL size = untagged_object_size(scan);
gc_debug("collect_object",scan);
gc_debug("collect_object size=",size);
switch(untag_header(get(scan)))
{
2004-07-27 23:29:37 -04:00
case WORD_TYPE:
collect_word((WORD*)scan);
break;
2004-07-16 02:26:21 -04:00
case ARRAY_TYPE:
collect_array((ARRAY*)scan);
break;
case VECTOR_TYPE:
collect_vector((VECTOR*)scan);
break;
case SBUF_TYPE:
collect_sbuf((SBUF*)scan);
break;
case PORT_TYPE:
collect_port((PORT*)scan);
2004-07-31 14:58:16 -04:00
break;
2004-07-16 02:26:21 -04:00
}
scan += size;
}
void collect_next(void)
{
gc_debug("collect_next",scan);
gc_debug("collect_next header",get(scan));
switch(TAG(get(scan)))
{
case HEADER_TYPE:
collect_object();
break;
default:
2004-08-04 22:43:58 -04:00
copy_object((CELL*)scan);
2004-07-16 02:26:21 -04:00
scan += CELLS;
break;
}
}
2004-08-13 02:19:22 -04:00
void collect_roots(void)
2004-07-16 02:26:21 -04:00
{
int i;
2004-08-12 02:13:43 -04:00
CELL ptr;
2004-07-16 02:26:21 -04:00
gc_debug("collect_roots",scan);
2004-09-08 02:31:03 -04:00
/*T must be the first in the heap */
2004-07-16 02:26:21 -04:00
copy_object(&T);
2004-08-29 01:04:42 -04:00
/* the bignum 0 1 -1 constants must be the next three */
2004-08-25 02:00:52 -04:00
copy_bignum_constants();
2004-08-29 01:04:42 -04:00
copy_object(&callframe);
2004-08-12 02:13:43 -04:00
2004-08-20 18:48:08 -04:00
for(ptr = ds_bot; ptr < ds; ptr += CELLS)
2004-08-12 02:13:43 -04:00
copy_object((void*)ptr);
2004-08-20 18:48:08 -04:00
for(ptr = cs_bot; ptr < cs; ptr += CELLS)
2004-08-12 02:13:43 -04:00
copy_object((void*)ptr);
2004-07-16 02:26:21 -04:00
for(i = 0; i < USER_ENV; i++)
2004-08-20 18:48:08 -04:00
copy_object(&userenv[i]);
2004-07-16 02:26:21 -04:00
}
void primitive_gc(void)
{
2004-08-29 03:20:19 -04:00
gc_in_progress = true;
2004-07-16 02:26:21 -04:00
flip_zones();
scan = active.here = active.base;
2004-08-13 02:19:22 -04:00
collect_roots();
collect_io_tasks();
/* collect literal objects referenced from compiled code */
collect_literals();
while(scan < active.here)
2004-07-16 02:26:21 -04:00
{
gc_debug("scan loop",scan);
collect_next();
}
gc_debug("gc done",0);
2004-08-29 03:20:19 -04:00
gc_in_progress = false;
2004-07-16 02:26:21 -04:00
}