remset.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. *
  4. * Authors: David Frese
  5. */
  6. /* Remembered Sets */
  7. #include <stdlib.h>
  8. #include "scheme48.h"
  9. #include "remset.h"
  10. #include "memory.h"
  11. #include "utils.h"
  12. #include "data.h"
  13. #include "generation_gc.h"
  14. #include "memory_map.h"
  15. #include "gc_config.h"
  16. #if (S48_USE_REMEMBERED_SETS)
  17. static int s48_remset_member(s48_address ip, RemSet* remset);
  18. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  19. /* Construction of a Rem_ip */
  20. static Rem_ip* allocate_Rem_ip(){
  21. Rem_ip* rem_ip = (Rem_ip*)calloc(1,sizeof(Rem_ip));
  22. if (!rem_ip){
  23. s48_gc_error("allocate_Rem_ip: out of memory");
  24. }
  25. return rem_ip;
  26. }
  27. static void initialize_Rem_ip(Rem_ip* rem_ip){
  28. rem_ip->ip = 0;
  29. rem_ip->next_ip = 0;
  30. }
  31. static Rem_ip* make_Rem_ip(){
  32. Rem_ip* rem_ip = (Rem_ip*)allocate_Rem_ip();
  33. initialize_Rem_ip(rem_ip);
  34. return rem_ip;
  35. }
  36. #endif
  37. /* Construction of a Rem_set */
  38. static RemSet* allocate_RemSet(){
  39. RemSet* remset = (RemSet*)calloc(1, (sizeof(RemSet)));
  40. if (!remset){
  41. s48_gc_error("allocate_RemSet: out of memory");
  42. }
  43. return remset;
  44. }
  45. static void initialize_RemSet(RemSet* remset){
  46. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  47. Rem_ip* el = (Rem_ip*)make_Rem_ip();
  48. remset->first_el = el;
  49. remset->last_el = el;
  50. #elif S48_REMEMBERED_SET_TYPE==S48_STATIC_REMEMBERED_SETS
  51. remset->free_index = 0;
  52. #elif S48_REMEMBERED_SET_TYPE==S48_EXTENSIBLE_REMEMBERED_SETS
  53. remset->free_index = 0;
  54. remset->next_remset = NULL;
  55. #endif
  56. }
  57. RemSet* s48_make_remset(){
  58. RemSet* remset = allocate_RemSet();
  59. initialize_RemSet(remset);
  60. return remset;
  61. }
  62. int s48_remset_size(RemSet* remset){
  63. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  64. Rem_ip* next = remset->first_el;
  65. Rem_ip* empty = remset->last_el;
  66. int size = 0;
  67. while(next != empty){
  68. size++;
  69. next = next->next_ip;
  70. }
  71. return size;
  72. #elif S48_REMEMBERED_SET_TYPE==S48_STATIC_REMEMBERED_SETS
  73. return remset->free_index;
  74. #elif S48_REMEMBERED_SET_TYPE==S48_EXTENSIBLE_REMEMBERED_SETS
  75. int size=0;
  76. while(remset != NULL){
  77. size += remset->free_index;
  78. remset = remset->next_remset;
  79. }
  80. return size;
  81. #endif
  82. }
  83. /* Adds an IP to a RS and returns a boolean */
  84. int s48_remset_add(s48_address ip, RemSet* remset){
  85. #if S48_UNIQUE_REMEMBERED_SET==TRUE /* no duplicates */
  86. if (s48_remset_member(ip, remset))
  87. return TRUE;
  88. #endif
  89. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  90. {
  91. Rem_ip* last = remset->last_el;
  92. Rem_ip* new_el = make_Rem_ip();
  93. last->ip = ip;
  94. last->next_ip = new_el;
  95. remset->last_el = new_el;
  96. return TRUE;
  97. }
  98. #elif S48_REMEMBERED_SET_TYPE==S48_STATIC_REMEMBERED_SETS
  99. if (remset->free_index == S48_REMEMBERED_SET_SIZE){
  100. return FALSE;
  101. }
  102. else{
  103. remset->elements[remset->free_index] = ip;
  104. remset->free_index++;
  105. return TRUE;
  106. }
  107. #elif S48_REMEMBERED_SET_TYPE==S48_EXTENSIBLE_REMEMBERED_SETS
  108. /* search or create a free remset */
  109. while (remset->free_index == S48_REMEMBERED_SET_SIZE){
  110. if (remset->next_remset == NULL)
  111. remset->next_remset= s48_make_remset();
  112. remset = remset->next_remset;
  113. }
  114. remset->elements[remset->free_index] = ip;
  115. remset->free_index++;
  116. return TRUE;
  117. #endif /* S48_REMEMBERED_SET_TYPE */
  118. }
  119. static int s48_remset_member(s48_address ip, RemSet* remset){
  120. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  121. Rem_ip* next = remset->first_el;
  122. Rem_ip* empty = remset->last_el;
  123. /* if both pointers point to the same rem_ip -> not a member */
  124. while(next != empty){
  125. if ((s48_address)next->ip == ip){
  126. return TRUE;
  127. }
  128. next = next->next_ip;
  129. }
  130. return FALSE;
  131. #elif S48_REMEMBERED_SET_TYPE==S48_STATIC_REMEMBERED_SETS
  132. int i;
  133. for (i = 0; i < remset->free_index; i++){
  134. if (remset->elements[i] == ip)
  135. return TRUE;
  136. }
  137. return FALSE;
  138. #elif S48_REMEMBERED_SET_TYPE==S48_EXTENSIBLE_REMEMBERED_SETS
  139. int i;
  140. while (remset != NULL){
  141. for (i = 0; i < remset->free_index; i++){
  142. if (remset->elements[i] == ip)
  143. return TRUE;
  144. }
  145. remset = remset->next_remset;
  146. }
  147. return FALSE;
  148. #endif /* S48_REMEMBERED_SET_TYPE */
  149. }
  150. static inline void call_trace_locationsB(s48_address addr) {
  151. Area* area = (Area*)s48_memory_map_ref(addr);
  152. /* we only want to trace locations, that are not currently
  153. collected. This test should be sufficient */
  154. if (area->action == GC_ACTION_IGNORE)
  155. s48_internal_trace_locationsB(area, TRUE, addr, S48_ADDRESS_INC(addr), "call_trace_locationsB");
  156. }
  157. void s48_trace_remset(RemSet* remset){
  158. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  159. Rem_ip* next = remset->first_el;
  160. Rem_ip* empty = remset->last_el;
  161. /* if both pointers point to the same rem_ip -> done*/
  162. while(next != empty){
  163. call_trace_locationsB(next->ip);
  164. next = next->next_ip;
  165. }
  166. #elif S48_REMEMBERED_SET_TYPE==S48_STATIC_REMEMBERED_SETS
  167. int i;
  168. for (i = 0; i < remset->free_index; i++)
  169. call_trace_locationsB(remset->elements[i]);
  170. #elif S48_REMEMBERED_SET_TYPE==S48_EXTENSIBLE_REMEMBERED_SETS
  171. int i;
  172. while (remset != NULL){
  173. for (i = 0; i < remset->free_index; i++)
  174. call_trace_locationsB(remset->elements[i]);
  175. remset = remset->next_remset;
  176. }
  177. #endif
  178. }
  179. void s48_free_remset(RemSet* remset){
  180. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  181. Rem_ip* next_ip;
  182. Rem_ip* rem_ip = remset->first_el;
  183. while(rem_ip != NULL){
  184. next_ip = rem_ip->next_ip;
  185. free(rem_ip);
  186. rem_ip = next_ip;
  187. }
  188. free(remset);
  189. #elif S48_REMEMBERED_SET_TYPE==S48_STATIC_REMEMBERED_SETS
  190. free(remset);
  191. #elif S48_REMEMBERED_SET_TYPE==S48_EXTENSIBLE_REMEMBERED_SETS
  192. RemSet* next_remset;
  193. while(remset != NULL){
  194. next_remset = remset->next_remset;
  195. free(remset);
  196. remset = next_remset;
  197. }
  198. #endif
  199. }
  200. void s48_check_remset(RemSet* remset) {
  201. /* only implemented for dynamic remsets, for now */
  202. #if S48_REMEMBERED_SET_TYPE==S48_DYNAMIC_REMEMBERED_SETS
  203. Rem_ip* next = remset->first_el;
  204. Rem_ip* empty = remset->last_el;
  205. while(next != empty) {
  206. Area* a = (Area*)s48_memory_map_ref(next->ip);
  207. if ((a == NULL) || (next->ip >= a->frontier)) {
  208. s48_gc_error("remembered-set currupted! Location 0x%X outside the heap.",
  209. next->ip);
  210. }
  211. next = next->next_ip;
  212. }
  213. #endif
  214. }
  215. #endif