#ifndef GC_H_6b8a27c99f2eb5eb5437e045fa4af1c3 #define GC_H_6b8a27c99f2eb5eb5437e045fa4af1c3 #include #include #include #include #ifndef NDEBUG # define debug(printf_args) ((void)printf printf_args) #else # define debug(printf_args) ((void)0) #endif typedef uintptr_t value_t; /* NIL: 00000000 00000000 00000000 00000000 */ /* Object: aaaaaaaa aaaaaaaa aaaaaaaa aaaaaa00 (where aa... >= 1024) */ /* Pair: aaaaaaaa aaaaaaaa aaaaaaaa aaaaaa10 */ /* Fixnum: snnnnnnn nnnnnnnn nnnnnnnn nnnnnnn1 */ #define NIL ((value_t)0) /* Special values (0 <= n < 1024) */ /* These correspond to objects within the first page of memory */ #define SPECIAL_VALUE(n) ((value_t)(4*n+2)) #define MAX_SPECIAL SPECIAL_VALUE(1023) #define BROKEN_HEART SPECIAL_VALUE(0) #define TYPE_TAG_BOX SPECIAL_VALUE(1) #define TYPE_TAG_VECTOR SPECIAL_VALUE(2) #define TYPE_TAG_BYTESTR SPECIAL_VALUE(3) typedef struct object { value_t tag; union { value_t values[0]; char bytes[0]; } payload; } object_t; typedef struct box { value_t tag; value_t value; } box_t; typedef struct pair { value_t car; value_t cdr; } pair_t; typedef struct vector { value_t tag; size_t size; value_t elements[0]; } vector_t; typedef struct byte_string { value_t tag; size_t size; uint8_t bytes[0]; } byte_string_t; typedef struct gc_root { value_t value; struct gc_root *prev; struct gc_root *next; } gc_root_t; typedef struct gc_stats { int collections; clock_t total_ticks; size_t high_water; } gc_stats_t; extern gc_stats_t gc_stats; object_t *get_object(value_t v); pair_t *get_pair(value_t pair); value_t cons(value_t car, value_t cdr); value_t make_box(value_t initial_value); box_t *get_box(value_t v); value_t make_vector(size_t elements, value_t default_value); vector_t *get_vector(value_t v); value_t make_byte_string(size_t size, int default_value); byte_string_t *get_byte_string(value_t v); intptr_t get_fixnum(value_t v); /****************************************************************************/ static inline value_t object_value(void *obj) { assert((uintptr_t)obj >= 4096); assert(((uintptr_t)obj & 3) == 0); return (value_t)obj; } static inline bool is_object(value_t v) { /* Neither pairs nor other objects can exist below (void*)4096. */ return ((v & 0x1) == 0) && (v > MAX_SPECIAL); } /* Pairs are a type of object, but the value representation is different */ static inline object_t *_get_object(value_t v) { return (object_t*)(v & ~(value_t)3); } static inline value_t pair_value(pair_t *p) { assert((uintptr_t)p >= 4096); assert(((uintptr_t)p & 3) == 0); return (value_t)p + 2; } static inline bool is_pair(value_t v) { return ((v & 0x3) == 2); } static inline pair_t *_get_pair(value_t v) { return (pair_t*)_get_object(v); } static inline bool is_box(value_t v) { return is_object(v) && (_get_object(v)->tag == TYPE_TAG_BOX); } static inline box_t *_get_box(value_t v) { return (box_t*)_get_object(v); } static inline bool is_vector(value_t v) { return is_object(v) && (_get_object(v)->tag == TYPE_TAG_VECTOR); } static inline vector_t *_get_vector(value_t v) { return (vector_t*)_get_object(v); } static inline size_t vector_size(value_t v) { return get_vector(v)->size; } static inline bool is_byte_string(value_t v) { return is_object(v) && (_get_object(v)->tag == TYPE_TAG_BYTESTR); } static inline byte_string_t *_get_byte_string(value_t v) { return (byte_string_t*)_get_object(v); } static inline size_t byte_string_size(value_t v) { return get_byte_string(v)->size; } static inline bool is_fixnum(value_t v) { return (v & 1) != 0; } static inline value_t make_fixnum(intptr_t n) { return (value_t)(n << 1) | 1; } static inline intptr_t _get_fixnum(value_t n) { return ((intptr_t)n) >> 1; } void gc_init(size_t min_size, size_t max_size); void register_gc_root(gc_root_t *root, value_t v); void unregister_gc_root(gc_root_t *root); void *gc_alloc(size_t nbytes); void collect_garbage(size_t min_free); /* To be provided by the main application */ void out_of_memory(void) __attribute__ ((noreturn)); #endif /* vim:set sw=2 expandtab: */