]> gitweb.factorcode.org Git - factor.git/blob - vm/data_gc.hpp
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / vm / data_gc.hpp
1 namespace factor
2 {
3
4 /* statistics */
5 struct gc_stats {
6         cell collections;
7         u64 gc_time;
8         u64 max_gc_time;
9         cell object_count;
10         u64 bytes_copied;
11 };
12
13 extern zone *newspace;
14
15 extern bool performing_compaction;
16 extern cell collecting_gen;
17 extern bool collecting_aging_again;
18
19 extern cell last_code_heap_scan;
20
21 void init_data_gc();
22
23 void gc();
24
25 inline static bool collecting_accumulation_gen_p()
26 {
27         return ((data->have_aging_p()
28                 && collecting_gen == data->aging()
29                 && !collecting_aging_again)
30                 || collecting_gen == data->tenured());
31 }
32
33 void copy_handle(cell *handle);
34
35 void garbage_collection(volatile cell gen,
36         bool growing_data_heap_,
37         cell requested_bytes);
38
39 /* We leave this many bytes free at the top of the nursery so that inline
40 allocation (which does not call GC because of possible roots in volatile
41 registers) does not run out of memory */
42 static const cell allot_buffer_zone = 1024;
43
44 inline static object *allot_zone(zone *z, cell a)
45 {
46         cell h = z->here;
47         z->here = h + align8(a);
48         object *obj = (object *)h;
49         allot_barrier(obj);
50         return obj;
51 }
52
53 /*
54  * It is up to the caller to fill in the object's fields in a meaningful
55  * fashion!
56  */
57 inline static object *allot_object(header header, cell size)
58 {
59 #ifdef GC_DEBUG
60         if(!gc_off)
61                 gc();
62 #endif
63
64         object *obj;
65
66         if(nursery.size - allot_buffer_zone > size)
67         {
68                 /* If there is insufficient room, collect the nursery */
69                 if(nursery.here + allot_buffer_zone + size > nursery.end)
70                         garbage_collection(data->nursery(),false,0);
71
72                 cell h = nursery.here;
73                 nursery.here = h + align8(size);
74                 obj = (object *)h;
75         }
76         /* If the object is bigger than the nursery, allocate it in
77         tenured space */
78         else
79         {
80                 zone *tenured = &data->generations[data->tenured()];
81
82                 /* If tenured space does not have enough room, collect */
83                 if(tenured->here + size > tenured->end)
84                 {
85                         gc();
86                         tenured = &data->generations[data->tenured()];
87                 }
88
89                 /* If it still won't fit, grow the heap */
90                 if(tenured->here + size > tenured->end)
91                 {
92                         garbage_collection(data->tenured(),true,size);
93                         tenured = &data->generations[data->tenured()];
94                 }
95
96                 obj = allot_zone(tenured,size);
97
98                 /* Allows initialization code to store old->new pointers
99                 without hitting the write barrier in the common case of
100                 a nursery allocation */
101                 write_barrier(obj);
102         }
103
104         obj->h = header;
105         return obj;
106 }
107
108 template<typename T> T *allot(cell size)
109 {
110         return (T *)allot_object(header(T::type_number),size);
111 }
112
113 void copy_reachable_objects(cell scan, cell *end);
114
115 PRIMITIVE(gc);
116 PRIMITIVE(gc_stats);
117 void clear_gc_stats();
118 PRIMITIVE(clear_gc_stats);
119 PRIMITIVE(become);
120
121 extern bool growing_data_heap;
122
123 inline static void check_data_pointer(object *pointer)
124 {
125 #ifdef FACTOR_DEBUG
126         if(!growing_data_heap)
127         {
128                 assert((cell)pointer >= data->seg->start
129                        && (cell)pointer < data->seg->end);
130         }
131 #endif
132 }
133
134 inline static void check_tagged_pointer(cell tagged)
135 {
136 #ifdef FACTOR_DEBUG
137         if(!immediate_p(tagged))
138         {
139                 object *obj = untag<object>(tagged);
140                 check_data_pointer(obj);
141                 obj->h.hi_tag();
142         }
143 #endif
144 }
145
146 VM_ASM_API void inline_gc(cell *gc_roots_base, cell gc_roots_size);
147
148 }