123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <strings.h>
- //#define TIME_GC
- #ifdef TIME_GC
- #include <sys/time.h>
- #endif
- #include "gc.h"
- #include "globals.h"
- #include "stack.h"
- #include "bytecode.h"
- typedef struct list {
- scm *data;
- struct list *next;
- struct list *prev;
- } list;
- struct list *gc_objects = NULL;
- scm gc_timer = 0;
- scm gc_fib = 1;
- scm gc_timeout = 1;
- void gc_list_push(scm *p) {
- struct list *link;
- link = malloc(sizeof(list));
- link->data = p;
- link->next = gc_objects;
- if(link->next) {
- link->next->prev = link;
- }
- link->prev = NULL;
-
- gc_objects = link;
- }
- #ifdef TIME_GC
- FILE *fptr;
- #endif
- scm *heap_alloc(scm n) {
- scm *p;
- scm tmp;
- gc_timer++;
- if(gc_timer > gc_timeout) {
- gc_timer = 0;
-
- tmp = gc_timeout;
- gc_timeout += gc_fib;
- gc_fib = tmp;
- #ifdef TIME_GC
- if(!fptr) {
- fptr = fopen("gc-log.txt", "w");
- }
- struct timeval time;
- long microsec;
- gettimeofday(&time, NULL);
- microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
- fprintf(fptr, "%ld 0\n", microsec);
- #endif
-
- mark();
- sweep();
- #ifdef TIME_GC
- gettimeofday(&time, NULL);
- microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
- fprintf(fptr, "%ld 1\n", microsec);
- #endif
- }
- p = calloc(n, sizeof(scm));
- gc_list_push(p);
- return p;
- }
- scm heap_alloc_closure(scm n, scm lbl) {
- scm *p;
- p = heap_alloc(1 + 1 + n);
- p[0] = make_header(color_white, 1, n);
- p[1] = lbl;
- return mk_clos(p);
- }
- scm heap_alloc_cons(scm car, scm cdr) {
- scm *p;
- p = heap_alloc(1 + 2);
- p[0] = make_header(color_white, 0, 2);
- p[1] = car;
- p[2] = cdr;
- return mk_cons(p);
- }
- scm heap_alloc_vect(scm n, scm val) {
- scm *p;
- int i;
-
- p = heap_alloc(1 + n);
-
- p[0] = make_header(color_white, 0, n);
- for(i = 0; i < n; i++) {
- p[1 + i] = val;
- }
-
- return mk_vect(p);
- }
- scm heap_alloc_strn(char *str, int i) {
- scm w;
- scm *p;
- unsigned char *s;
-
- w = (i + 8 + 1)/8;
-
- p = heap_alloc(2 + w);
-
- p[0] = make_header(color_white, 1 + w, 0);
- p[1] = i;
- s = (void*)(p+2);
- strncpy((char*)s, str, i);
-
- return mk_strn(p);
- }
- //#define DEBUG
- void mark() {
- int i;
- scm gc_stack_ptr;
- scm gc_stack_base_ptr;
- scm tmp;
- #ifdef DEBUG
- puts("MARK REG");
- #endif
-
- mark_object(vm_reg_ret);
- mark_object(vm_reg_env);
- #ifdef DEBUG
- puts("MARK GLO");
- #endif
-
- for(i = 0; i < VM_GLOBALS_SIZE; i++) {
- mark_object(vm_globals[i]);
- }
- #ifdef DEBUG
- puts("MARK STK");
- #endif
-
- gc_stack_ptr = vm_stack_ptr;
- gc_stack_base_ptr = vm_stack_base_ptr;
- while(gc_stack_ptr > gc_stack_base_ptr) {
- mark_object(vm_stack[--gc_stack_ptr]);
- }
-
- while(gc_stack_ptr > 0) {
- tmp = vm_stack[--gc_stack_ptr];
- assert(tmp == 0xC0FFEEEEEEEEEEEE);
- --gc_stack_ptr;
- mark_object(vm_stack[--gc_stack_ptr]);
- gc_stack_base_ptr = vm_stack[--gc_stack_ptr];
- tmp = vm_stack[--gc_stack_ptr];
- assert(tmp == 0xC0DEDBADC0DEDBAD);
- #ifdef DEBUG
- puts(" FRAME");
- #endif
- while(gc_stack_ptr > gc_stack_base_ptr) {
- mark_object(vm_stack[--gc_stack_ptr]);
- }
- }
-
- #ifdef DEBUG
- puts("MARK ARGS");
- #endif
- for(i = 0; i < bytecode_args_num; i++) {
- mark_object(bytecode_args[i]);
- }
-
- #ifdef DEBUG
- puts("MARK.");
- #endif
- }
- void mark_object(scm obj) {
- scm *p;
- scm hdr;
- scm raw_size, scm_size;
- int i;
- //printf("MARK %ld\n", scm_get_tag(obj));
- switch(scm_get_tag(obj)) {
- case atom_tag_fals:
- case atom_tag_true:
- case atom_tag_null:
- case atom_tag_symb:
- case atom_tag_char:
- case tag_numb:
- break;
- case tag_cons:
- case tag_clos:
- case tag_vect:
- case tag_strn:
- p = (scm*)(obj & ~0b111);
- hdr = *p;
- if(header_color(hdr) == color_black)
- break;
-
- *p = color_header(hdr, color_black);
-
- raw_size = header_raw_size(hdr);
- scm_size = header_scm_size(hdr);
-
- for(i = 0; i < scm_size; i++) {
- mark_object(p[1 + raw_size + i]);
- }
- break;
- default:
- fprintf(stderr, "Unknown object type");
- exit(-1);
- }
- }
- void sweep() {
- struct list *link;
- struct list *tmp;
- scm hdr;
- link = gc_objects;
- while(link) {
- //printf("%p\n", link->data);
- hdr = *(link->data);
- if(header_color(hdr) == color_white) {
- bzero(link->data, (1 + header_raw_size(hdr) + header_scm_size(hdr)) * sizeof(scm));
- free(link->data);
- tmp = link;
- link = link->next;
- if(tmp->prev)
- tmp->prev->next = tmp->next;
- else {
- gc_objects = tmp->next;
- tmp->next->prev = NULL;
- }
- if(tmp->next)
- tmp->next->prev = tmp->prev;
- tmp->data = NULL;
- tmp->next = NULL;
- tmp->prev = NULL;
- free(tmp);
-
- /*
- bzero(link->data, (1 + header_raw_size(hdr) + header_scm_size(hdr)) * sizeof(scm));
- free(link->data);
- if(link->prev) {
- link->prev->next = link->next;
- }
- else {
- gc_objects = link;
- }
-
- if(link->next) {
- link->next->prev = link->prev;
- }
-
- tmp = link;
- link = link->next;
- tmp->data = NULL;
- tmp->next = NULL;
- tmp->prev = NULL;
- free(tmp);
- */
- }
- else {
- *(link->data) = color_header(hdr, color_white);
-
- link = link->next;
- }
- }
- }
|