garbagecollector.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <limits.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include "sans.h"
  7. #include "garbagecollector.h"
  8. #define MAX_SPACE (1<<23)
  9. u space_used = 0;
  10. sdata from_space[MAX_SPACE];
  11. sdata to_space[MAX_SPACE];
  12. sdata *cur_space = from_space;
  13. sdata heap_ref(u ref) {
  14. if (ref < space_used) {
  15. return cur_space[ref];
  16. }
  17. else {
  18. log_err("garbagecollector/heap_ref: %ld out of bounds %ld\n", ref, space_used);
  19. }
  20. }
  21. void heap_set(u ref, sdata x) {
  22. if (ref < space_used) {
  23. cur_space[ref] = x;
  24. }
  25. else {
  26. log_err("garbagecollector/heap_set: %ld out of bounds %ld\n", ref, space_used);
  27. }
  28. }
  29. sdata cons(sdata x, sdata y) {
  30. u place;
  31. // BUGFIX: This used to check space_used < MAX_SPACE
  32. // which was wrong
  33. if (space_used + 2 <= MAX_SPACE) {
  34. place = space_used;
  35. cur_space[space_used++] = x;
  36. cur_space[space_used++] = y;
  37. return (sdata){.tag = tcons, .data.value = place};
  38. }
  39. else {
  40. // TODO: gc
  41. log_err("garbagecollector/cons: ran out of memory\n");
  42. }
  43. }
  44. u allocate_string_buff(u len) {
  45. u place;
  46. // https://www.securecoding.cert.org/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data
  47. if (len > LONG_MAX) {
  48. log_err("garbagecollector/allocate_string: %lu is larger than s can hold\n", len);
  49. }
  50. // we want to reserve 1 + len contiguous cells for our vector
  51. if (space_used + 1 + len <= MAX_SPACE) {
  52. place = space_used;
  53. space_used += 1 + len;
  54. cur_space[place] = (sdata){.tag = tnumb, .data.ivalue = len};
  55. return place;
  56. }
  57. else {
  58. // TODO: gc
  59. log_err("garbagecollector/allocate_string: ran out of memory\n");
  60. }
  61. }
  62. sdata allocate_string(char* string) {
  63. u i;
  64. u len = strlen(string);
  65. u place = allocate_string_buff(len);
  66. for (i = 0; i < len; i++) {
  67. cur_space[place + 1 + i] = SDCHAR(string[i]);
  68. }
  69. return (sdata){.tag = tstrn, .data.value = place};
  70. }
  71. sdata allocate_vector(u len) {
  72. u place;
  73. u i;
  74. // https://www.securecoding.cert.org/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data
  75. if (len > LONG_MAX) {
  76. log_err("garbagecollector/allocate_vector: %lu is larger than s can hold\n", len);
  77. }
  78. // we want to reserve 1 + len contiguous cells for our vector
  79. if (space_used + 1 + len <= MAX_SPACE) {
  80. place = space_used;
  81. space_used += 1 + len;
  82. cur_space[place] = (sdata){.tag = tnumb, .data.ivalue = len};
  83. // prefill the vector with #f to avoid nondeterminism/uninitialized values
  84. for (i = 0; i < len; i++) {
  85. cur_space[place + 1 + i] = (sdata){.tag = tbool, .data.value = 0};
  86. }
  87. return (sdata){.tag = tvect, .data.value = place};
  88. }
  89. else {
  90. // TODO: gc
  91. log_err("garbagecollector/allocate_vector: ran out of memory\n");
  92. }
  93. }
  94. sdata allocate_closure(u len, u label) {
  95. // [label][vec -->][len,vector elements]
  96. sdata vec = allocate_vector(len+2);
  97. sdata vec_len;
  98. u place;
  99. place = vec.data.value;
  100. // make the vector 2 smaller
  101. // move the length tag up 2
  102. vec_len = cur_space[place];
  103. vec_len.data.ivalue -= 2;
  104. cur_space[place+2] = vec_len;
  105. // put a scheme vector down into the heap
  106. vec.data.value+=2;
  107. cur_space[place+1] = vec;
  108. // put the label down
  109. cur_space[place] = (sdata){.tag = tlabl, .data.ivalue = label };
  110. return (sdata){.tag = tclos, .data.value = place};
  111. }
  112. #include <assert.h>
  113. void bltn_vector_set_bang(sdata ob, sdata idx, sdata val);
  114. void closure_set(sdata cl, u i, sdata v) {
  115. assert(cl.tag == tclos);
  116. sdata vec = cur_space[cl.data.value+1];
  117. bltn_vector_set_bang(vec, SDNUMB(i), v);
  118. }
  119. sdata bltn_closure_env_set_bang(sdata clo, sdata idx, sdata v) {
  120. closure_set(clo, idx.data.value, v);
  121. return clo;
  122. }