factor/native/gc.h

128 lines
2.8 KiB
C
Raw Normal View History

2005-05-13 00:09:49 -04:00
/* generational copying GC divides memory into zones */
typedef struct {
/* start of zone */
CELL base;
/* allocation pointer */
CELL here;
/* only for nursery: when it gets this full, call GC */
CELL alarm;
/* end of zone */
CELL limit;
} ZONE;
2005-02-17 21:19:27 -05:00
2005-05-13 00:09:49 -04:00
/* total number of generations. */
2005-07-13 15:14:57 -04:00
CELL gen_count;
2005-05-13 00:09:49 -04:00
/* the 0th generation is where new objects are allocated. */
#define NURSERY 0
/* the oldest generation */
2005-07-13 15:14:57 -04:00
#define TENURED (gen_count-1)
2005-05-13 00:09:49 -04:00
ZONE *generations;
2005-05-13 00:09:49 -04:00
/* used during garbage collection only */
ZONE *newspace;
#define tenured generations[TENURED]
#define nursery generations[NURSERY]
/* spare semi-space; rotates with tenured. */
ZONE prior;
INLINE bool in_zone(ZONE* z, CELL pointer)
{
return pointer >= z->base && pointer < z->limit;
}
CELL init_zone(ZONE *z, CELL size, CELL base);
void init_arena(CELL gen_count, CELL young_size, CELL aging_size);
2005-02-17 21:19:27 -05:00
/* statistics */
2005-03-21 20:59:30 -05:00
s64 gc_time;
CELL minor_collections;
CELL cards_scanned;
2004-07-16 02:26:21 -04:00
2005-05-11 00:43:52 -04:00
/* only meaningful during a GC */
CELL collecting_gen;
CELL collecting_gen_start;
2005-05-11 00:43:52 -04:00
/* test if the pointer is in generation being collected, or a younger one.
init_arena() arranges things so that the older generations are first,
so we have to check that the pointer occurs after the beginning of
the requested generation. */
#define COLLECTING_GEN(ptr) (collecting_gen_start <= ptr)
2005-05-11 00:43:52 -04:00
2005-05-10 22:30:58 -04:00
/* #define GC_DEBUG */
INLINE void gc_debug(char* msg, CELL x) {
#ifdef GC_DEBUG
2005-05-12 01:02:39 -04:00
printf("%s %ld\n",msg,x);
2005-05-10 22:30:58 -04:00
#endif
}
INLINE bool should_copy(CELL untagged)
{
if(collecting_gen == TENURED)
return !in_zone(newspace,untagged);
else
return(in_zone(&prior,untagged) || COLLECTING_GEN(untagged));
}
2005-05-12 01:02:39 -04:00
CELL copy_object(CELL pointer);
2005-06-12 20:55:30 -04:00
#define COPY_OBJECT(lvalue) if(should_copy(lvalue)) lvalue = copy_object(lvalue)
2005-02-19 23:25:21 -05:00
2005-05-12 01:02:39 -04:00
INLINE void copy_handle(CELL *handle)
2005-02-19 23:25:21 -05:00
{
COPY_OBJECT(*handle);
}
2005-05-12 03:52:56 -04:00
/* in case a generation fills up in the middle of a gc, we jump back
up to try collecting the next generation. */
jmp_buf gc_jmp;
2005-05-13 00:09:49 -04:00
/* A heap walk allows useful things to be done, like finding all
references to an object for debugging purposes. */
CELL heap_scan_ptr;
/* GC is off during heap walking */
bool heap_scan;
INLINE void *allot_zone(ZONE *z, CELL a)
{
CELL h = z->here;
z->here = h + align8(a);
2006-02-08 22:12:20 -05:00
if(z->here > z->limit)
{
fprintf(stderr,"Nursery space exhausted\n");
factorbug();
}
2005-05-13 00:09:49 -04:00
allot_barrier(h);
return (void*)h;
}
INLINE void *allot(CELL a)
{
return allot_zone(&nursery,a);
}
/*
* It is up to the caller to fill in the object's fields in a meaningful
* fashion!
*/
INLINE void* allot_object(CELL type, CELL length)
{
CELL* object = allot(length);
*object = tag_header(type);
return object;
}
void update_cards_offset(void);
2005-05-13 00:09:49 -04:00
CELL collect_next(CELL scan);
void garbage_collection(CELL gen);
void primitive_gc(void);
void maybe_gc(CELL size);
DLLEXPORT void simple_gc(void);
2005-05-13 00:09:49 -04:00
void primitive_gc_time(void);