]> gitweb.factorcode.org Git - factor.git/blob - vm/full_collector.cpp
VM: refactor gc_event so that the phase times are stored in an array
[factor.git] / vm / full_collector.cpp
1 #include "master.hpp"
2
3 namespace factor {
4
5 struct full_collection_copier : no_fixup {
6   tenured_space* tenured;
7   code_heap* code;
8   std::vector<cell> *mark_stack;
9
10   full_collection_copier(tenured_space* tenured,
11                          code_heap* code,
12                          std::vector<cell> *mark_stack)
13       : tenured(tenured), code(code), mark_stack(mark_stack) { }
14
15   object* fixup_data(object* obj) {
16     if (tenured->contains_p(obj)) {
17       if (!tenured->state.marked_p((cell)obj)) {
18         tenured->state.set_marked_p((cell)obj, obj->size());
19         mark_stack->push_back((cell)obj);
20       }
21       return obj;
22     }
23
24     // Is there another forwarding pointer?
25     while (obj->forwarding_pointer_p()) {
26       object* dest = obj->forwarding_pointer();
27       obj = dest;
28     }
29
30     if (tenured->contains_p(obj)) {
31       if (!tenured->state.marked_p((cell)obj)) {
32         tenured->state.set_marked_p((cell)obj, obj->size());
33         mark_stack->push_back((cell)obj);
34       }
35       return obj;
36     }
37
38     cell size = obj->size();
39     object* newpointer = tenured->allot(size);
40     if (!newpointer)
41       throw must_start_gc_again();
42     memcpy(newpointer, obj, size);
43     obj->forward_to(newpointer);
44
45     tenured->state.set_marked_p((cell)newpointer, newpointer->size());
46     mark_stack->push_back((cell)newpointer);
47     return newpointer;
48   }
49
50   code_block* fixup_code(code_block* compiled) {
51     if (!code->allocator->state.marked_p((cell)compiled)) {
52       code->allocator->state.set_marked_p((cell)compiled, compiled->size());
53       mark_stack->push_back((cell)compiled + 1);
54     }
55     return compiled;
56   }
57 };
58
59 void factor_vm::collect_mark_impl() {
60   slot_visitor<full_collection_copier>
61       visitor(this, full_collection_copier(data->tenured, code, &mark_stack));
62
63   mark_stack.clear();
64
65   code->allocator->state.clear_mark_bits();
66   data->tenured->state.clear_mark_bits();
67
68   visitor.visit_all_roots();
69   visitor.visit_context_code_blocks();
70   visitor.visit_uninitialized_code_blocks();
71
72   visitor.visit_mark_stack(&mark_stack);
73
74   data->reset_tenured();
75   data->reset_aging();
76   data->reset_nursery();
77   code->clear_remembered_set();
78 }
79
80 void factor_vm::collect_sweep_impl() {
81   gc_event* event = current_gc->event;
82
83   if (event)
84     event->reset_timer();
85   data->tenured->sweep();
86   if (event)
87     event->ended_phase(PHASE_DATA_SWEEP);
88
89   // After a sweep, invalidate any code heap roots which are not
90   // marked, so that if a block makes a tail call to a generic word,
91   // and the PIC compiler triggers a GC, and the caller block gets GCd
92   // as a result, the PIC code won't try to overwrite the call site
93   mark_bits* state = &code->allocator->state;
94   FACTOR_FOR_EACH(code_roots) {
95     code_root* root = *iter;
96     cell block = root->value & (~data_alignment - 1);
97     if (root->valid && !state->marked_p(block))
98       root->valid = false;
99   }
100
101   if (event)
102     event->reset_timer();
103   code->sweep();
104   if (event)
105     event->ended_phase(PHASE_CODE_SWEEP);
106 }
107
108 void factor_vm::collect_full() {
109   collect_mark_impl();
110   collect_sweep_impl();
111
112   if (data->low_memory_p()) {
113     // Full GC did not free up enough memory. Grow the heap.
114     set_current_gc_op(COLLECT_GROWING_DATA_HEAP_OP);
115     collect_growing_data_heap(0);
116   } else if (data->high_fragmentation_p()) {
117     // Enough free memory, but it is not contiguous. Perform a
118     // compaction.
119     set_current_gc_op(COLLECT_COMPACT_OP);
120     collect_compact_impl();
121   }
122
123   code->flush_icache();
124 }
125
126 }