123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- #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 "objects.h"
- #include "vm.h"
- #include "glovars.h"
- #include "interpreter.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_port(FILE *a, FILE *b) {
- scm *p;
- p = heap_alloc(3);
-
- p[0] = make_hdr(HDR_WHITE, 2, 0);
- p[1] = SCM_PTR(a);
- p[2] = SCM_PTR(b);
- return mk_port(p);
- }
- */
- //#define DEBUG
- void mark() {
- // int i;
- scm gc_stack_ptr;
- scm gc_stack_base_ptr;
- scm tmp;
- struct global *g;
- #ifdef DEBUG
- puts("MARK REG");
- #endif
-
- mark_object(reg_acc);
- mark_object(reg_clo);
- if (reg_env)
- mark_object(scm_puttag(reg_env-2, TAG_CLOS));
- #ifdef DEBUG
- puts("MARK GLO");
- #endif
-
- if(glovars) {
- for(g = glovars; g; g = g->next) {
- mark_object(g->val);
- }
- }
- #ifdef DEBUG
- puts("MARK STK");
- #endif
-
- gc_stack_ptr = reg_rsp;
- gc_stack_base_ptr = reg_rbp;
- while(gc_stack_ptr > gc_stack_base_ptr) {
- mark_object(stack[gc_stack_ptr--]);
- }
-
- while(gc_stack_ptr > 0) {
- tmp = stack[gc_stack_ptr--];
- assert(tmp == 0xDEADBEEFDEADBEEF);
-
- // rbp
- gc_stack_base_ptr = stack[gc_stack_ptr--];
-
- // reg env
- if(stack[gc_stack_ptr])
- mark_object(scm_puttag(((scm*)PTR_SCM(stack[gc_stack_ptr]))-2, TAG_CLOS));
- gc_stack_ptr--;
-
- // ret addr
- gc_stack_ptr--;
-
- tmp = stack[gc_stack_ptr--];
- assert(tmp == 0xC0FFEEEEEEEEEEEE);
-
- #ifdef DEBUG
- puts(" FRAME");
- #endif
-
- while(gc_stack_ptr > gc_stack_base_ptr) {
- mark_object(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;
- if (scm_isptr(obj)) {
- p = (scm*)(obj & ~0b111);
- hdr = *p;
- if(get_hdr_color(hdr) == HDR_BLACK)
- return;
-
- *p = set_hdr_color(hdr, HDR_BLACK);
-
- raw_size = get_hdr_raw_size(hdr);
- scm_size = get_hdr_scm_size(hdr);
-
- for(i = 0; i < scm_size; i++) {
- mark_object(p[1 + raw_size + i]);
- }
- }
- }
- void sweep() {
- struct list *link;
- struct list *tmp;
- scm hdr;
- link = gc_objects;
- while(link) {
- //printf("%p\n", link->data);
- hdr = *(link->data);
- if(get_hdr_color(hdr) == HDR_WHITE) {
- bzero(link->data, (1 + get_hdr_raw_size(hdr) + get_hdr_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 + get_hdr_raw_size(hdr) + get_hdr_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) = set_hdr_color(hdr, HDR_WHITE);
-
- link = link->next;
- }
- }
- }
|