area_roots.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. *
  4. * Authors: David Frese
  5. */
  6. #ifndef __S48_AREA_ROOTS
  7. #define __S48_AREA_ROOTS
  8. #include "data.h"
  9. #include "areas.h"
  10. #include "memory.h"
  11. #include "memory_map.h"
  12. #include "scheme48.h"
  13. #include "measure.h"
  14. /* Cards & Dirty Vector */
  15. #define S48_CARD_SIZE (1 << S48_LOG_CARD_SIZE)
  16. void s48_init_dirty_vector(Area* area);
  17. void s48_deinit_dirty_vector(Area* area);
  18. void s48_trace_areas_roots(Area* areas);
  19. /* implementation of the write-barrier */
  20. void s48_set_dirty_vector(Area* area, s48_address addr, long stob,
  21. Area* maybe_to_area);
  22. /* Marks the card containing addr as dirty. called from
  23. s48_write_barrier and s48_internal_write_barrier */
  24. inline static void s48_set_dirty_vector_inline(Area* area, s48_address addr,
  25. long stob, Area* maybe_to_area)
  26. {
  27. #if S48_DIRTY_VECTOR_METHOD==S48_ADDRESS_DIRTY_VECTORS
  28. unsigned long area_offset = addr - area->start;
  29. unsigned int card_number = area_offset >> S48_LOG_CARD_SIZE ;
  30. s48_address current_dirty_address = area->dirty_vector.items[card_number];
  31. assert(card_number < area->dirty_vector.length);
  32. /* Only update if Nullpointer or smaller than current_dirty_address */
  33. if ((current_dirty_address == NULL) || (addr < current_dirty_address))
  34. area->dirty_vector.items[card_number] = addr;
  35. #endif
  36. }
  37. S48_EXTERN void s48_write_barrier(long stob, s48_address address, long value);
  38. S48_EXTERN char s48_stob_in_heapP(s48_value);
  39. /* the value VALUE will be written at location ADDRESS which is within the stob STOB */
  40. inline static void s48_write_barrier_inline(long stob, s48_address address,
  41. long value) {
  42. /* The area of the stob */
  43. Area* area = s48_memory_map_ref(address);
  44. #if (MEASURE_GC)
  45. if (S48_STOB_P(value)) {
  46. Area* meas_to_area = s48_memory_map_ref(S48_ADDRESS_AT_HEADER(value));
  47. if (area->generation_index > meas_to_area->generation_index) {
  48. measure_write_barrier(1);
  49. } else {
  50. measure_write_barrier(0);
  51. }
  52. }
  53. #endif
  54. /* Detect errors early... */
  55. if (S48_STOB_P(value)) {
  56. assert(s48_stob_in_heapP(value));
  57. }
  58. /* somehow the write_barrier gets called from some strange places --
  59. e.g. in read_image, that's why area can get NULL. */
  60. if (area == NULL)
  61. return;
  62. assert(address < area->frontier);
  63. if (area->generation_index == 0)
  64. return;
  65. #if S48_WRITE_BARRIER_COMPLEXITY == S48_MUTATED_LOCATION
  66. s48_set_dirty_vector(area, address, value, NULL);
  67. #else
  68. if (S48_STOB_P(value)) {
  69. #if S48_WRITE_BARRIER_COMPLEXITY == S48_STOB_LOCATION
  70. s48_set_dirty_vector(area, address, value, NULL);
  71. #elif S48_WRITE_BARRIER_COMPLEXITY == S48_INTERGEN_STOB_LOCATION
  72. Area* to_area = s48_memory_map_ref(S48_ADDRESS_AT_HEADER(value));
  73. if (area->generation_index > to_area->generation_index)
  74. s48_set_dirty_vector_inline(area, address, value, to_area);
  75. #endif
  76. }
  77. #endif
  78. }
  79. /* called after a stob in AREA, stored at ADDR pointing into TO_AREA, has
  80. been updated, either because the object has been copied to a new
  81. area, a large area has been linked into a new list, or the object
  82. has been traced but ignored. */
  83. inline static void s48_internal_write_barrier(Area* area, s48_address addr,
  84. long value, Area* to_area) {
  85. /* we're not interested in locations in an other-space area. This
  86. test should be sufficient. This happens because of root-set
  87. functions, that trace a stob inside an area that is beeing
  88. collected (other-space). */
  89. if (area->action != GC_ACTION_IGNORE)
  90. return;
  91. #if (S48_HAVE_TRANSPORT_LINK_CELLS)
  92. /* We could ignore the key field here for optimization, but maybe
  93. it's not worth the test. */
  94. #endif
  95. /* We're only interested in pointers from old to young */
  96. if (area->generation_index > to_area->generation_index) {
  97. #if (MEASURE_GC)
  98. measure_gc_write_barrier();
  99. #endif
  100. #if (S48_USE_REMEMBERED_SETS)
  101. /* if the rememberd-set can store this pointer, then we're done,
  102. otherwise mark the card anyway */
  103. if (s48_remset_add(addr, to_area->remset))
  104. return;
  105. #endif
  106. s48_set_dirty_vector_inline(area, addr, value, to_area);
  107. }
  108. }
  109. #endif