gc.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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 "objects.h"
  11. #include "vm.h"
  12. #include "glovars.h"
  13. #include "interpreter.h"
  14. //#include "bytecode.h"
  15. typedef struct list {
  16. scm *data;
  17. struct list *next;
  18. struct list *prev;
  19. } list;
  20. struct list *gc_objects = NULL;
  21. scm gc_timer = 0;
  22. scm gc_fib = 1;
  23. scm gc_timeout = 1;
  24. void gc_list_push(scm *p) {
  25. struct list *link;
  26. link = malloc(sizeof(list));
  27. link->data = p;
  28. link->next = gc_objects;
  29. if(link->next) {
  30. link->next->prev = link;
  31. }
  32. link->prev = NULL;
  33. gc_objects = link;
  34. }
  35. #ifdef TIME_GC
  36. FILE *fptr;
  37. #endif
  38. scm *heap_alloc(scm n) {
  39. scm *p;
  40. scm tmp;
  41. gc_timer++;
  42. if( (gc_timer > gc_timeout)) {
  43. gc_timer = 0;
  44. tmp = gc_timeout;
  45. gc_timeout += gc_fib;
  46. gc_fib = tmp;
  47. #ifdef TIME_GC
  48. if(!fptr) {
  49. fptr = fopen("gc-log.txt", "w");
  50. }
  51. struct timeval time;
  52. long microsec;
  53. gettimeofday(&time, NULL);
  54. microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
  55. fprintf(fptr, "%ld 0\n", microsec);
  56. #endif
  57. mark();
  58. sweep();
  59. #ifdef TIME_GC
  60. gettimeofday(&time, NULL);
  61. microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
  62. fprintf(fptr, "%ld 1\n", microsec);
  63. #endif
  64. }
  65. p = calloc(n, sizeof(scm));
  66. gc_list_push(p);
  67. return p;
  68. }
  69. /*
  70. scm heap_alloc_port(FILE *a, FILE *b) {
  71. scm *p;
  72. p = heap_alloc(3);
  73. p[0] = make_hdr(HDR_WHITE, 2, 0);
  74. p[1] = SCM_PTR(a);
  75. p[2] = SCM_PTR(b);
  76. return mk_port(p);
  77. }
  78. */
  79. //#define DEBUG
  80. void mark() {
  81. // int i;
  82. scm gc_stack_ptr;
  83. scm gc_stack_base_ptr;
  84. scm tmp;
  85. struct global *g;
  86. #ifdef DEBUG
  87. puts("MARK REG");
  88. #endif
  89. mark_object(reg_acc);
  90. mark_object(reg_clo);
  91. if (reg_env)
  92. mark_object(scm_puttag(reg_env-2, TAG_CLOS));
  93. #ifdef DEBUG
  94. puts("MARK GLO");
  95. #endif
  96. if(glovars) {
  97. for(g = glovars; g; g = g->next) {
  98. mark_object(g->val);
  99. }
  100. }
  101. #ifdef DEBUG
  102. puts("MARK STK");
  103. #endif
  104. gc_stack_ptr = reg_rsp;
  105. gc_stack_base_ptr = reg_rbp;
  106. while(gc_stack_ptr > gc_stack_base_ptr) {
  107. mark_object(stack[gc_stack_ptr--]);
  108. }
  109. while(gc_stack_ptr > 0) {
  110. tmp = stack[gc_stack_ptr--];
  111. assert(tmp == 0xDEADBEEFDEADBEEF);
  112. // rbp
  113. gc_stack_base_ptr = stack[gc_stack_ptr--];
  114. // reg env
  115. if(stack[gc_stack_ptr])
  116. mark_object(scm_puttag(((scm*)PTR_SCM(stack[gc_stack_ptr]))-2, TAG_CLOS));
  117. gc_stack_ptr--;
  118. // ret addr
  119. gc_stack_ptr--;
  120. tmp = stack[gc_stack_ptr--];
  121. assert(tmp == 0xC0FFEEEEEEEEEEEE);
  122. #ifdef DEBUG
  123. puts(" FRAME");
  124. #endif
  125. while(gc_stack_ptr > gc_stack_base_ptr) {
  126. mark_object(stack[gc_stack_ptr--]);
  127. }
  128. }
  129. #ifdef DEBUG
  130. puts("MARK ARGS");
  131. #endif
  132. /*
  133. for(i = 0; i < bytecode_args_num; i++) {
  134. mark_object(bytecode_args[i]);
  135. }
  136. */
  137. #ifdef DEBUG
  138. puts("MARK.");
  139. #endif
  140. }
  141. void mark_object(scm obj) {
  142. scm *p;
  143. scm hdr;
  144. scm raw_size, scm_size;
  145. int i;
  146. if (scm_isptr(obj)) {
  147. p = (scm*)(obj & ~0b111);
  148. hdr = *p;
  149. if(get_hdr_color(hdr) == HDR_BLACK)
  150. return;
  151. *p = set_hdr_color(hdr, HDR_BLACK);
  152. raw_size = get_hdr_raw_size(hdr);
  153. scm_size = get_hdr_scm_size(hdr);
  154. for(i = 0; i < scm_size; i++) {
  155. mark_object(p[1 + raw_size + i]);
  156. }
  157. }
  158. }
  159. void sweep() {
  160. struct list *link;
  161. struct list *tmp;
  162. scm hdr;
  163. link = gc_objects;
  164. while(link) {
  165. //printf("%p\n", link->data);
  166. hdr = *(link->data);
  167. if(get_hdr_color(hdr) == HDR_WHITE) {
  168. bzero(link->data, (1 + get_hdr_raw_size(hdr) + get_hdr_scm_size(hdr)) * sizeof(scm));
  169. free(link->data);
  170. tmp = link;
  171. link = link->next;
  172. if(tmp->prev)
  173. tmp->prev->next = tmp->next;
  174. else {
  175. gc_objects = tmp->next;
  176. tmp->next->prev = NULL;
  177. }
  178. if(tmp->next)
  179. tmp->next->prev = tmp->prev;
  180. tmp->data = NULL;
  181. tmp->next = NULL;
  182. tmp->prev = NULL;
  183. free(tmp);
  184. /*
  185. bzero(link->data, (1 + get_hdr_raw_size(hdr) + get_hdr_scm_size(hdr)) * sizeof(scm));
  186. free(link->data);
  187. if(link->prev) {
  188. link->prev->next = link->next;
  189. }
  190. else {
  191. gc_objects = link;
  192. }
  193. if(link->next) {
  194. link->next->prev = link->prev;
  195. }
  196. tmp = link;
  197. link = link->next;
  198. tmp->data = NULL;
  199. tmp->next = NULL;
  200. tmp->prev = NULL;
  201. free(tmp);
  202. */
  203. }
  204. else {
  205. *(link->data) = set_hdr_color(hdr, HDR_WHITE);
  206. link = link->next;
  207. }
  208. }
  209. }