gc.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <strings.h>
  5. //#define TIME_GC
  6. #ifdef TIME_GC
  7. #include <sys/time.h>
  8. #endif
  9. #include "gc.h"
  10. #include "globals.h"
  11. #include "stack.h"
  12. #include "bytecode.h"
  13. typedef struct list {
  14. scm *data;
  15. struct list *next;
  16. struct list *prev;
  17. } list;
  18. struct list *gc_objects = NULL;
  19. scm gc_timer = 0;
  20. scm gc_fib = 1;
  21. scm gc_timeout = 1;
  22. void gc_list_push(scm *p) {
  23. struct list *link;
  24. link = malloc(sizeof(list));
  25. link->data = p;
  26. link->next = gc_objects;
  27. if(link->next) {
  28. link->next->prev = link;
  29. }
  30. link->prev = NULL;
  31. gc_objects = link;
  32. }
  33. #ifdef TIME_GC
  34. FILE *fptr;
  35. #endif
  36. scm *heap_alloc(scm n) {
  37. scm *p;
  38. scm tmp;
  39. gc_timer++;
  40. if(gc_timer > gc_timeout) {
  41. gc_timer = 0;
  42. tmp = gc_timeout;
  43. gc_timeout += gc_fib;
  44. gc_fib = tmp;
  45. #ifdef TIME_GC
  46. if(!fptr) {
  47. fptr = fopen("gc-log.txt", "w");
  48. }
  49. struct timeval time;
  50. long microsec;
  51. gettimeofday(&time, NULL);
  52. microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
  53. fprintf(fptr, "%ld 0\n", microsec);
  54. #endif
  55. mark();
  56. sweep();
  57. #ifdef TIME_GC
  58. gettimeofday(&time, NULL);
  59. microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
  60. fprintf(fptr, "%ld 1\n", microsec);
  61. #endif
  62. }
  63. p = calloc(n, sizeof(scm));
  64. gc_list_push(p);
  65. return p;
  66. }
  67. scm heap_alloc_closure(scm n, scm lbl) {
  68. scm *p;
  69. p = heap_alloc(1 + 1 + n);
  70. p[0] = make_header(color_white, 1, n);
  71. p[1] = lbl;
  72. return mk_clos(p);
  73. }
  74. scm heap_alloc_cons(scm car, scm cdr) {
  75. scm *p;
  76. p = heap_alloc(1 + 2);
  77. p[0] = make_header(color_white, 0, 2);
  78. p[1] = car;
  79. p[2] = cdr;
  80. return mk_cons(p);
  81. }
  82. scm heap_alloc_vect(scm n, scm val) {
  83. scm *p;
  84. int i;
  85. p = heap_alloc(1 + n);
  86. p[0] = make_header(color_white, 0, n);
  87. for(i = 0; i < n; i++) {
  88. p[1 + i] = val;
  89. }
  90. return mk_vect(p);
  91. }
  92. scm heap_alloc_strn(char *str, int i) {
  93. scm w;
  94. scm *p;
  95. unsigned char *s;
  96. w = (i + 8 + 1)/8;
  97. p = heap_alloc(2 + w);
  98. p[0] = make_header(color_white, 1 + w, 0);
  99. p[1] = i;
  100. s = (void*)(p+2);
  101. strncpy((char*)s, str, i);
  102. return mk_strn(p);
  103. }
  104. //#define DEBUG
  105. void mark() {
  106. int i;
  107. scm gc_stack_ptr;
  108. scm gc_stack_base_ptr;
  109. scm tmp;
  110. #ifdef DEBUG
  111. puts("MARK REG");
  112. #endif
  113. mark_object(vm_reg_ret);
  114. mark_object(vm_reg_env);
  115. #ifdef DEBUG
  116. puts("MARK GLO");
  117. #endif
  118. for(i = 0; i < VM_GLOBALS_SIZE; i++) {
  119. mark_object(vm_globals[i]);
  120. }
  121. #ifdef DEBUG
  122. puts("MARK STK");
  123. #endif
  124. gc_stack_ptr = vm_stack_ptr;
  125. gc_stack_base_ptr = vm_stack_base_ptr;
  126. while(gc_stack_ptr > gc_stack_base_ptr) {
  127. mark_object(vm_stack[--gc_stack_ptr]);
  128. }
  129. while(gc_stack_ptr > 0) {
  130. tmp = vm_stack[--gc_stack_ptr];
  131. assert(tmp == 0xC0FFEEEEEEEEEEEE);
  132. --gc_stack_ptr;
  133. mark_object(vm_stack[--gc_stack_ptr]);
  134. gc_stack_base_ptr = vm_stack[--gc_stack_ptr];
  135. tmp = vm_stack[--gc_stack_ptr];
  136. assert(tmp == 0xC0DEDBADC0DEDBAD);
  137. #ifdef DEBUG
  138. puts(" FRAME");
  139. #endif
  140. while(gc_stack_ptr > gc_stack_base_ptr) {
  141. mark_object(vm_stack[--gc_stack_ptr]);
  142. }
  143. }
  144. #ifdef DEBUG
  145. puts("MARK ARGS");
  146. #endif
  147. for(i = 0; i < bytecode_args_num; i++) {
  148. mark_object(bytecode_args[i]);
  149. }
  150. #ifdef DEBUG
  151. puts("MARK.");
  152. #endif
  153. }
  154. void mark_object(scm obj) {
  155. scm *p;
  156. scm hdr;
  157. scm raw_size, scm_size;
  158. int i;
  159. //printf("MARK %ld\n", scm_get_tag(obj));
  160. switch(scm_get_tag(obj)) {
  161. case atom_tag_fals:
  162. case atom_tag_true:
  163. case atom_tag_null:
  164. case atom_tag_symb:
  165. case atom_tag_char:
  166. case tag_numb:
  167. break;
  168. case tag_cons:
  169. case tag_clos:
  170. case tag_vect:
  171. case tag_strn:
  172. p = (scm*)(obj & ~0b111);
  173. hdr = *p;
  174. if(header_color(hdr) == color_black)
  175. break;
  176. *p = color_header(hdr, color_black);
  177. raw_size = header_raw_size(hdr);
  178. scm_size = header_scm_size(hdr);
  179. for(i = 0; i < scm_size; i++) {
  180. mark_object(p[1 + raw_size + i]);
  181. }
  182. break;
  183. default:
  184. fprintf(stderr, "Unknown object type");
  185. exit(-1);
  186. }
  187. }
  188. void sweep() {
  189. struct list *link;
  190. struct list *tmp;
  191. scm hdr;
  192. link = gc_objects;
  193. while(link) {
  194. //printf("%p\n", link->data);
  195. hdr = *(link->data);
  196. if(header_color(hdr) == color_white) {
  197. bzero(link->data, (1 + header_raw_size(hdr) + header_scm_size(hdr)) * sizeof(scm));
  198. free(link->data);
  199. tmp = link;
  200. link = link->next;
  201. if(tmp->prev)
  202. tmp->prev->next = tmp->next;
  203. else {
  204. gc_objects = tmp->next;
  205. tmp->next->prev = NULL;
  206. }
  207. if(tmp->next)
  208. tmp->next->prev = tmp->prev;
  209. tmp->data = NULL;
  210. tmp->next = NULL;
  211. tmp->prev = NULL;
  212. free(tmp);
  213. /*
  214. bzero(link->data, (1 + header_raw_size(hdr) + header_scm_size(hdr)) * sizeof(scm));
  215. free(link->data);
  216. if(link->prev) {
  217. link->prev->next = link->next;
  218. }
  219. else {
  220. gc_objects = link;
  221. }
  222. if(link->next) {
  223. link->next->prev = link->prev;
  224. }
  225. tmp = link;
  226. link = link->next;
  227. tmp->data = NULL;
  228. tmp->next = NULL;
  229. tmp->prev = NULL;
  230. free(tmp);
  231. */
  232. }
  233. else {
  234. *(link->data) = color_header(hdr, color_white);
  235. link = link->next;
  236. }
  237. }
  238. }