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