]> gitweb.factorcode.org Git - factor.git/blob - vm/data_gc.h
Fix conflict from master
[factor.git] / vm / data_gc.h
1 void gc(void);
2 DLLEXPORT void minor_gc(void);
3
4 /* used during garbage collection only */
5
6 F_ZONE *newspace;
7 bool performing_gc;
8 bool performing_compaction;
9 CELL collecting_gen;
10
11 /* if true, we collecting AGING space for the second time, so if it is still
12 full, we go on to collect TENURED */
13 bool collecting_aging_again;
14
15 /* in case a generation fills up in the middle of a gc, we jump back
16 up to try collecting the next generation. */
17 jmp_buf gc_jmp;
18
19 /* statistics */
20 typedef struct {
21         CELL collections;
22         u64 gc_time;
23         u64 max_gc_time;
24         CELL object_count;
25         u64 bytes_copied;
26 } F_GC_STATS;
27
28 F_GC_STATS gc_stats[MAX_GEN_COUNT];
29 u64 cards_scanned;
30 u64 decks_scanned;
31 u64 card_scan_time;
32 CELL code_heap_scans;
33
34 /* What generation was being collected when copy_code_heap_roots() was last
35 called? Until the next call to add_code_block(), future
36 collections of younger generations don't have to touch the code
37 heap. */
38 CELL last_code_heap_scan;
39
40 /* sometimes we grow the heap */
41 bool growing_data_heap;
42 F_DATA_HEAP *old_data_heap;
43
44 INLINE bool collecting_accumulation_gen_p(void)
45 {
46         return ((HAVE_AGING_P
47                 && collecting_gen == AGING
48                 && !collecting_aging_again)
49                 || collecting_gen == TENURED);
50 }
51
52 /* test if the pointer is in generation being collected, or a younger one. */
53 INLINE bool should_copy(CELL untagged)
54 {
55         if(in_zone(newspace,untagged))
56                 return false;
57         if(collecting_gen == TENURED)
58                 return true;
59         else if(HAVE_AGING_P && collecting_gen == AGING)
60                 return !in_zone(&data_heap->generations[TENURED],untagged);
61         else if(collecting_gen == NURSERY)
62                 return in_zone(&nursery,untagged);
63         else
64         {
65                 critical_error("Bug in should_copy",untagged);
66                 return false;
67         }
68 }
69
70 void copy_handle(CELL *handle);
71
72 void garbage_collection(volatile CELL gen,
73         bool growing_data_heap_,
74         CELL requested_bytes);
75
76 /* We leave this many bytes free at the top of the nursery so that inline
77 allocation (which does not call GC because of possible roots in volatile
78 registers) does not run out of memory */
79 #define ALLOT_BUFFER_ZONE 1024
80
81 /* If this is defined, we GC every 100 allocations. This catches missing local roots */
82 #ifdef GC_DEBUG
83 int gc_count;
84 #endif
85
86 /*
87  * It is up to the caller to fill in the object's fields in a meaningful
88  * fashion!
89  */
90 int count;
91 INLINE void *allot_object(CELL type, CELL a)
92 {
93 #ifdef GC_DEBUG
94         if(!gc_off)
95         {
96                 if(gc_count++ % 1000 == 0)
97                         gc();
98
99         }
100 #endif
101
102         CELL *object;
103
104         if(nursery.size - ALLOT_BUFFER_ZONE > a)
105         {
106                 /* If there is insufficient room, collect the nursery */
107                 if(nursery.here + ALLOT_BUFFER_ZONE + a > nursery.end)
108                         garbage_collection(NURSERY,false,0);
109
110                 CELL h = nursery.here;
111                 nursery.here = h + align8(a);
112                 object = (void*)h;
113         }
114         /* If the object is bigger than the nursery, allocate it in
115         tenured space */
116         else
117         {
118                 F_ZONE *tenured = &data_heap->generations[TENURED];
119
120                 /* If tenured space does not have enough room, collect */
121                 if(tenured->here + a > tenured->end)
122                 {
123                         gc();
124                         tenured = &data_heap->generations[TENURED];
125                 }
126
127                 /* If it still won't fit, grow the heap */
128                 if(tenured->here + a > tenured->end)
129                 {
130                         garbage_collection(TENURED,true,a);
131                         tenured = &data_heap->generations[TENURED];
132                 }
133
134                 object = allot_zone(tenured,a);
135
136                 /* We have to do this */
137                 allot_barrier((CELL)object);
138
139                 /* Allows initialization code to store old->new pointers
140                 without hitting the write barrier in the common case of
141                 a nursery allocation */
142                 write_barrier((CELL)object);
143         }
144
145         *object = tag_header(type);
146         return object;
147 }
148
149 void copy_reachable_objects(CELL scan, CELL *end);
150
151 void primitive_gc(void);
152 void primitive_gc_stats(void);
153 void clear_gc_stats(void);
154 void primitive_clear_gc_stats(void);
155 void primitive_become(void);