diff --git a/runtime/gc_runtime.s b/runtime/gc_runtime.s index 3df87be0a..1dcbe6698 100644 --- a/runtime/gc_runtime.s +++ b/runtime/gc_runtime.s @@ -7,18 +7,24 @@ printf_format5: .string "LOL\n" __gc_stack_bottom: .long 0 __gc_stack_top: .long 0 - .globl L__gc_init - .globl __gc_root_scan_stack - + .globl L__gc_init + .globl __gc_root_scan_stack + .extern init_pool + .extern __gc_test_and_copy_root .text L__gc_init: movl %esp, __gc_stack_bottom addl $4, __gc_stack_bottom + call init_pool ret __gc_root_scan_stack: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %edx movl %esp, __gc_stack_top movl %esp, %eax - jmp next + jmp next loop: movl (%eax), %ebx @@ -54,15 +60,22 @@ check22: loop2: andl $0x00000001, %ebx jnz next +gc_run_t: pushl %eax - pushl (%eax) - pushl $printf_format - call printf - addl $8, %esp +// pushl (%eax) + pushl %eax + call __gc_test_and_copy_root + addl $4, %esp popl %eax next: addl $4, %eax cmpl %eax, __gc_stack_bottom jne loop +returnn: + movl $0, %eax + popl %edx + popl %ebx + movl %ebp, %esp + popl %ebp ret diff --git a/runtime/runtime.c b/runtime/runtime.c index 530990f8b..e85c1b0a1 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -2,18 +2,18 @@ # include # include -# include # include # include -# include # include +# include +# include -# define STRING_TAG 0x00000000 -# define ARRAY_TAG 0x01000000 -# define SEXP_TAG 0x02000000 +# define STRING_TAG 0x00000001 +# define ARRAY_TAG 0x00000003 +# define SEXP_TAG 0x00000005 -# define LEN(x) (x & 0x00FFFFFF) -# define TAG(x) (x & 0xFF000000) +# define LEN(x) ((x & 0xFFFFFFF8) >> 3) +# define TAG(x) (x & 0x00000007) # define TO_DATA(x) ((data*)((char*)(x)-sizeof(int))) # define TO_SEXP(x) ((sexp*)((char*)(x)-2*sizeof(int))) @@ -32,6 +32,8 @@ typedef struct { data contents; } sexp; +static void* alloc (size_t); + extern int Blength (void *p) { data *a = TO_DATA(p); return BOX(LEN(a->tag)); @@ -153,9 +155,9 @@ extern void* Belem (void *p, int i) { extern void* Bstring (void *p) { int n = strlen (p); - data *r = (data*) malloc (n + 1 + sizeof (int)); + data *r = (data*) alloc (n + 1 + sizeof (int)); - r->tag = n; + r->tag = STRING_TAG | (n << 3); strncpy (r->contents, p, n + 1); return r->contents; @@ -177,9 +179,9 @@ extern void* Bstringval (void *p) { extern void* Barray (int n, ...) { va_list args; int i; - data *r = (data*) malloc (sizeof(int) * (n+1)); + data *r = (data*) alloc (sizeof(int) * (n+1)); - r->tag = ARRAY_TAG | n; + r->tag = ARRAY_TAG | (n << 3); va_start(args, n); @@ -196,10 +198,16 @@ extern void* Barray (int n, ...) { extern void* Bsexp (int n, ...) { va_list args; int i; - sexp *r = (sexp*) malloc (sizeof(int) * (n+2)); - data *d = &(r->contents); + // sexp *r = (sexp*) alloc (sizeof(int) * (n+2)); + // data *d = &(r->contents); + sexp *r; + data *d; - d->tag = SEXP_TAG | (n-1); + printf("Bsexp: allocate %zu!\n",sizeof(int) * (n+2)); + r = (sexp*) alloc (sizeof(int) * (n+2)); + d = &(r->contents); + + d->tag = SEXP_TAG | ((n-1) << 3); va_start(args, n); @@ -303,7 +311,7 @@ extern void* Lstrcat (void *a, void *b) { data *da = TO_DATA(a); data *db = TO_DATA(b); - data *d = (data *) malloc (sizeof(int) + LEN(da->tag) + LEN(db->tag) + 1); + data *d = (data *) alloc (sizeof(int) + LEN(da->tag) + LEN(db->tag) + 1); d->tag = LEN(da->tag) + LEN(db->tag); @@ -355,17 +363,6 @@ extern size_t __gc_stack_bottom, __gc_stack_top; extern void L__gc_init (); -extern void __gc_root_scan_data () { - size_t * p = &__gc_data_start; - - printf ("Start, end: %lx, %lx\n", &__gc_data_start, &__gc_data_end); - - while (p != &__gc_data_end) { - if (!UNBOXED(*p)) printf ("Root: %lx\n", *p); - p++; - } -} - extern void __gc_root_scan_stack (); @@ -385,14 +382,205 @@ extern void __gc_root_scan_stack (); extern char __executable_start; extern char __etext; -extern void Ltest () { - printf("\n"); - printf("STA 0x%lx\n", (unsigned long)&__executable_start); - printf("END 0x%lx\n", (unsigned long)&__etext); - __gc_root_scan_data (); - __gc_root_scan_stack (); +/* extern void Ltest () { */ +/* printf("\n"); */ +/* printf("STA 0x%lx\n", (unsigned long)&__executable_start); */ +/* printf("END 0x%lx\n", (unsigned long)&__etext); */ +/* __gc_root_scan_data (); */ +/* __gc_root_scan_stack (); */ - // printf("STA 0x%lx\n", (unsigned long)&__executable_start); - // printf("END 0x%lx\n", (unsigned long)&__etext); - // printf("RET 0x%lx\n\n", __builtin_return_address(0)); +/* // printf("STA 0x%lx\n", (unsigned long)&__executable_start); */ +/* // printf("END 0x%lx\n", (unsigned long)&__etext); */ +/* // printf("RET 0x%lx\n\n", __builtin_return_address(0)); */ +/* } */ + +/* ======================================== */ +/* Mark-and-copy */ +/* ======================================== */ + +static size_t SPACE_SIZE = 128; +# define POOL_SIZE (2*SPACE_SIZE) + +typedef struct { + size_t * begin; + size_t * end; + size_t * current; + size_t size; +} pool; + +static pool from_space; +static pool to_space; +size_t * current; + +static void swap (size_t ** a, size_t ** b) { + size_t * t = *a; + *a = *b; + *b = t; +} + +static void __gc_swap_spaces (void) { + swap (&from_space.begin, &to_space.begin); + swap (&from_space.end , &to_space.end ); + from_space.current = current; + to_space.current = to_space.begin; +} + +# define IS_VALID_HEAP_POINTER(p)\ + (!UNBOXED(p) && \ + from_space.begin <= p && \ + from_space.end > p) + +# define IN_PASSIVE_SPACE(p) \ + (to_space.begin <= p && \ + to_space.end > p) + +# define IS_FORWARD_PTR(p) \ + (!UNBOXED(p) && IN_PASSIVE_SPACE(p)) + +extern size_t * gc_copy (size_t *obj); + +static void copy_elements (size_t *where, size_t *from, int len) { + int i = 0; + for (i = 0; i < len; i++) { + size_t elem = from[i]; + // if (UNBOXED(elem)) *++where = elem; + if (!IS_VALID_HEAP_POINTER(elem)) *++where = elem; + else *++where = gc_copy ((size_t*) elem); + } +} + +extern size_t * gc_copy (size_t *obj) { + data *d = TO_DATA(obj); + sexp *s = NULL; + size_t *copy = NULL; + int i = 0; + int len1, len2, len3; + void * objj; + void * newobjj = (void*)current; + printf("gc_copy: %x cur = %x starts\n", obj, current); + + if (!IS_VALID_HEAP_POINTER(obj)) { + printf ("gc_copy: invalid ptr: %x\n", obj); + return obj; + } + + if (!IN_PASSIVE_SPACE(current)) { + printf("ERROR: gc_copy: out-of-space %x %x %x\n", current, to_space.begin, to_space.end); + fflush(stdout); + perror("ERROR: gc_copy: out-of-space\n"); + exit (6); + } + + if (IS_FORWARD_PTR(d->tag)) + return (size_t *) d->tag; + + copy = current; + objj = d; + switch (TAG(d->tag)) { + case ARRAY_TAG: + current += (LEN(d->tag) + 1) * sizeof (int); + *copy = d->tag; + copy++; + copy_elements (copy, obj, LEN(d->tag)); + d->tag = (int) copy; + break; + case STRING_TAG: + current += (LEN(d->tag) + 1) * sizeof (int); + *copy = d->tag; + copy++; + d->tag = (int) copy; + strcpy (©[1], (char*) obj); + break; + case SEXP_TAG : + s = TO_SEXP(obj); + objj = s; + len1 = LEN(s->contents.tag); + len2 = LEN(s->tag); + len3 = LEN(d->tag); + printf("len1 = %li, len2=%li, len3 = %li\n",len1,len2,len3); + current += (LEN(s->contents.tag) + 2) * sizeof (int); + *copy = s->tag; + copy++; + *copy = s->contents.tag; + copy++; + len3 = LEN(s->contents.tag); + s->contents.tag = (int) copy; + copy_elements (copy, obj, len3); + break; + default: + printf ("ERROR: gc_copy: weird tag: %x", TAG(d->tag)); + fflush(stdout); + perror ("ERROR: gc_copy: weird tag"); + exit(5); + } + printf("gc_copy: %x -> %x\n", objj, newobjj); + fflush(stdout); + return copy; +} + +extern void __gc_test_and_copy_root (size_t ** root) { + if (IS_VALID_HEAP_POINTER(*root)) + *root = gc_copy (*root); +} + +extern void __gc_root_scan_data (void) { + size_t * p = &__gc_data_start; + while (p != &__gc_data_end) { + __gc_test_and_copy_root (p); + p++; + } +} + +extern void init_pool (void) { + from_space.begin = mmap(NULL, SPACE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + to_space.begin = mmap(NULL, SPACE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + if (to_space.begin == MAP_FAILED || + from_space.begin == MAP_FAILED) { + perror("EROOR: init_pool: mmap failed\n"); + exit(1); + } + from_space.current = from_space.begin; + from_space.end = from_space.begin + SPACE_SIZE; + from_space.size = SPACE_SIZE; + to_space.current = to_space.begin; + to_space.end = to_space.begin + SPACE_SIZE; + to_space.size = SPACE_SIZE; +} + +static int free_pool (pool * p) { + return munmap((void *)p->begin, p->size); +} + +static void * gc (size_t size) { + current = to_space.begin; + printf("gc: current: %x; to_space.b = %x; to_space.e = %x; f_space.b = %x; f_space.e = %x\n", current, to_space.begin, to_space.end, from_space.begin, from_space.end); + __gc_root_scan_data (); + __gc_root_scan_stack (); + if (!IN_PASSIVE_SPACE(current)) { + perror ("ASSERT: !IN_PASSIVE_SPACE(current)\n"); + exit(1); + } + + if (current + size >= to_space.end) { + perror ("ERROR: gc: out of memory\n"); + exit(4); + } + + __gc_swap_spaces (); + from_space.current = current + size; + return current; +} + +static void * alloc (size_t size) { + if (from_space.current + size < from_space.end) { + printf("alloc: current: %x %zu", from_space.current, size); + void * p = (void*) from_space.current; + from_space.current += size; + printf(";new current: %x \n", from_space.current); + return p; + } + printf("alloc: call gc: %zu\n", size); + return gc (size); }