1 /*
2  * Part of Scheme 48 1.9.  See file COPYING for notices and license.
3  *
4  * Authors: David Frese
5  */
6 
7 /* Implements area_roots.h */
8 
9 #include <stdlib.h>
10 
11 #include "scheme48.h"
12 
13 #include "area_roots.h"
14 #include "areas.h"
15 #include "memory.h"
16 #include "memory_map.h"
17 #include "utils.h"
18 #include "data.h"
19 #include "measure.h"
20 #include "generation_gc.h"
21 #include "gc_config.h"
22 
23 #if (S48_USE_REMEMBERED_SETS)
24 #include "remset.h"
25 #endif
26 
27 /* initializes the dirty vector of AREA */
s48_init_dirty_vector(Area * area)28 void s48_init_dirty_vector(Area* area) {
29 
30 #if S48_DIRTY_VECTOR_METHOD==S48_ADDRESS_DIRTY_VECTORS
31   Dirty_vector* dv = &area->dirty_vector;
32   unsigned long area_size = area->end - area->start;
33   unsigned long number_of_cards = area_size >> S48_LOG_CARD_SIZE ;
34   dv->length = number_of_cards;
35   /* A vector of pointers */
36   dv->items = (s48_address*)calloc(sizeof(s48_address), number_of_cards);
37 #endif
38 
39 }
40 
41 /* deinitializes the dirty vector of AREA. (should free the memory
42    allocated in init_dirty_vector */
s48_deinit_dirty_vector(Area * area)43 void s48_deinit_dirty_vector(Area* area) {
44 #if S48_DIRTY_VECTOR_METHOD==S48_ADDRESS_DIRTY_VECTORS
45   free(area->dirty_vector.items);
46 #endif
47 }
48 
49 #if (MEASURE_GC)
50 static unsigned long areas_visited = 0;
51 static unsigned long areas_passed = 0;
52 #endif
53 
call_trace_locationsB(Area * area,s48_address start_address,s48_address end_address)54 inline static void call_trace_locationsB(Area* area,
55 					 s48_address start_address,
56 					 s48_address end_address) {
57 #if (MEASURE_GC)
58   areas_passed += (end_address - start_address);
59 #endif
60 
61   s48_internal_trace_locationsB(area, TRUE, start_address, end_address,
62 				"s48_trace_areas_roots");
63 }
64 
65 /* trace (all possible) pointers to collected generations, in the
66    old/uncollected area AREA */
trace_area_roots(Area * area)67 void trace_area_roots(Area* area)
68 {
69   /* the tracing can always be stopped at the trace pointer, because
70      the part behind that (objects added the the area during the
71      collection) will be traced later anyway. And the cards behind
72      that will not be marked either. */
73 
74 #if (MEASURE_GC)
75   areas_visited += areas->frontier - areas->start;
76 #endif
77 
78 #if S48_DIRTY_VECTOR_METHOD==S48_NO_DIRTY_VECTORS
79   /* Without a dirty vector, we trace everything to be sure to catch
80      all intergenerational pointers. */
81   call_trace_locationsB(area, area->start, area->trace);
82 #endif
83 
84 #if S48_DIRTY_VECTOR_METHOD==S48_ADDRESS_DIRTY_VECTORS
85   /* This method stores the first location of an intergenerational
86      pointer within a card (a fixed-sized part of the area). */
87   Dirty_vector* dirty_vector = &area->dirty_vector;
88   s48_address card_start_address = area->start;
89   int i;
90 
91   for (i = 0;
92        (i < dirty_vector->length) && (card_start_address < area->trace);
93        i++, card_start_address += S48_CARD_SIZE) {
94     s48_address start_address = dirty_vector->items[i];
95     if (start_address != NULL) {
96       s48_address end_address = card_start_address + S48_CARD_SIZE;
97 
98       /* no need to trace behind trace pointer */
99       if (end_address > area->trace) end_address = area->trace;
100 
101       /* checks */
102       if (start_address < card_start_address)
103 	s48_gc_error("s48_trace_areas_roots: dirty address too small.");
104       if (start_address >= end_address)
105 	s48_gc_error("s48_trace_areas_roots: dirty address too big.");
106 
107       /* reset */
108       dirty_vector->items[i] = NULL;
109 
110       /* trace */
111       call_trace_locationsB(area, start_address, end_address);
112     }
113   } // for loop over dirty vector
114 #endif
115 
116 }
117 
118 /* FPage 9 */
119 
120 /* passes all dirty regions in all areas in the linked list starting
121    with AREAS, to trace_locationsB */
s48_trace_areas_roots(Area * areas)122 void s48_trace_areas_roots(Area* areas) {
123   while(areas != NULL) {
124     trace_area_roots(areas);
125     areas = areas->next;
126   }
127 
128 #if (MEASURE_GC)
129   measure_areas_roots(areas_visited, areas_passed);
130   areas_visited = 0;
131   areas_passed = 0;
132 #endif
133 
134 }
135 
s48_set_dirty_vector(Area * area,s48_address addr,long stob,Area * maybe_to_area)136 void s48_set_dirty_vector(Area* area, s48_address addr, long stob,
137 			  Area* maybe_to_area) {
138   s48_set_dirty_vector_inline(area, addr, stob, maybe_to_area);
139 }
140 
s48_write_barrier(long stob,s48_address address,long value)141 void s48_write_barrier(long stob, s48_address address, long value) {
142   s48_write_barrier_inline(stob, address, value);
143 }
144