/* gc.c -- simple garbage collector */ /* Copyright (c) 2009 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include #define SEXP_INITIAL_HEAP_SIZE 10000000 #define SEXP_MINIMUM_OBJECT_SIZE (sexp_sizeof(flonum)) static char* sexp_heap; static char* sexp_heap_end; static sexp sexp_free_list; sexp_uint_t sexp_allocated_bytes (sexp x) { switch (sexp_tag(x)) { case SEXP_PAIR: return sexp_sizeof(pair); case SEXP_SYMBOL: return sexp_sizeof(symbol); case SEXP_STRING: return sexp_sizeof(string)+sexp_string_length(x); case SEXP_VECTOR: return sexp_sizeof(vector)+(sexp_vector_length(x)*sizeof(sexp)); case SEXP_FLONUM: return sexp_sizeof(flonum); case SEXP_BIGNUM: return sexp_sizeof(bignum); case SEXP_IPORT: case SEXP_OPORT: return sexp_sizeof(port); case SEXP_EXCEPTION: return sexp_sizeof(exception); case SEXP_PROCEDURE: return sexp_sizeof(procedure); case SEXP_MACRO: return sexp_sizeof(macro); case SEXP_SYNCLO: return sexp_sizeof(synclo); case SEXP_ENV: return sexp_sizeof(env); case SEXP_BYTECODE: return sexp_sizeof(bytecode)+sexp_bytecode_length(x); case SEXP_CORE: return sexp_sizeof(core); case SEXP_OPCODE: return sexp_sizeof(opcode); case SEXP_LAMBDA: return sexp_sizeof(lambda); case SEXP_CND: return sexp_sizeof(cnd); case SEXP_REF: return sexp_sizeof(ref); case SEXP_SET: return sexp_sizeof(set); case SEXP_SEQ: return sexp_sizeof(seq); case SEXP_LIT: return sexp_sizeof(lit); case SEXP_CONTEXT: return sexp_sizeof(context); default: return 0; } } void *sexp_alloc (sexp ctx, size_t size) { sexp ls1, ls2, ls3; try_alloc: ls1=sexp_free_list; for (ls2=sexp_cdr(ls1); sexp_pairp(ls2); ls1=ls2, ls2=sexp_cdr(ls2)) if (sexp_car(ls2) >= size) { if (sexp_car(ls2) >= size + SEXP_MINIMUM_OBJECT_SIZE) { ls3 = (sexp) (((char*)ls2)+size); sexp_car(ls3) = (sexp) (sexp_car(ls2) - size); sexp_cdr(ls3) = sexp_cdr(ls2); sexp_cdr(ls1) = sexp_cdr(ls3); } else { sexp_cdr(ls1) = sexp_cdr(ls2); } return ls2; } if (sexp_unbox_integer(sexp_gc(ctx)) >= size) { goto try_alloc; } else { fprintf(stderr, "chibi: out of memory trying to allocate %ld bytes, aborting\n", size); exit(70); } } void sexp_mark (sexp x) { sexp *data; sexp_uint_t i; loop: if ((! sexp_pointerp(x)) || sexp_mark(x)) return; sexp_gc_mark(x) = 1; switch (sexp_tag(x)) { case SEXP_PAIR: sexp_mark(sexp_car(x)); x = sexp_cdr(x); goto loop; case SEXP_VECTOR: data = sexp_vector_data(x); for (i=sexp_vector_length(x)-1; i>=0; i--) sexp_mark(data[i]); } } sexp sexp_sweep () { sexp_uint_t freed=0, size; sexp p=(sexp)sexp_heap, f1=sexp_free_list, f2; while (p