3 struct must_start_gc_again {
6 template <typename TargetGeneration, typename Policy>
7 struct gc_workhorse : no_fixup {
8 static const bool translated_code_block_map = false;
11 TargetGeneration* target;
15 gc_workhorse(factor_vm* parent, TargetGeneration* target, Policy policy)
16 : parent(parent), target(target), policy(policy), code(parent->code) {}
18 object* fixup_data(object* obj) {
19 FACTOR_ASSERT((parent->current_gc &&
20 parent->current_gc->op == collect_growing_heap_op) ||
21 parent->data->seg->in_segment_p((cell)obj));
23 if (!policy.should_copy_p(obj)) {
24 policy.visited_object(obj);
28 /* is there another forwarding pointer? */
29 while (obj->forwarding_pointer_p()) {
30 object* dest = obj->forwarding_pointer();
34 if (!policy.should_copy_p(obj)) {
35 policy.visited_object(obj);
39 cell size = obj->size();
40 object* newpointer = target->allot(size);
42 throw must_start_gc_again();
44 memcpy(newpointer, obj, size);
45 obj->forward_to(newpointer);
47 policy.promoted_object(newpointer);
52 code_block* fixup_code(code_block* compiled) {
53 if (!code->allocator->state.marked_p((cell)compiled)) {
54 code->allocator->state.set_marked_p((cell)compiled, compiled->size());
55 parent->mark_stack.push_back((cell)compiled + 1);
62 template <typename TargetGeneration, typename Policy> struct collector {
66 TargetGeneration* target;
67 gc_workhorse<TargetGeneration, Policy> workhorse;
68 slot_visitor<gc_workhorse<TargetGeneration, Policy> > visitor;
71 cell code_blocks_scanned;
74 collector(factor_vm* parent, TargetGeneration* target, Policy policy)
79 workhorse(parent, target, policy),
80 visitor(parent, workhorse),
83 code_blocks_scanned(0) {
84 scan = target->start + target->occupied_space();
87 void trace_code_heap_roots(std::set<code_block*>* remembered_set) {
88 std::set<code_block*>::const_iterator iter = remembered_set->begin();
89 std::set<code_block*>::const_iterator end = remembered_set->end();
91 for (; iter != end; iter++) {
92 code_block* compiled = *iter;
93 visitor.visit_code_block_objects(compiled);
94 visitor.visit_embedded_literals(compiled);
95 compiled->flush_icache();
96 code_blocks_scanned++;
100 void trace_partial_objects(cell start, cell card_start, cell card_end) {
101 object* obj = (object*)start;
102 cell end = start + obj->binary_payload_start();
103 if (card_start < end) {
104 start += sizeof(cell);
106 start = std::max(start, card_start);
107 end = std::min(end, card_end);
109 cell* slot_ptr = (cell*)start;
110 cell* end_ptr = (cell*)end;
112 for (; slot_ptr < end_ptr; slot_ptr++)
113 visitor.visit_handle(slot_ptr);
117 template <typename SourceGeneration>
118 cell trace_card(SourceGeneration* gen, cell index, cell start) {
120 cell start_addr = data->start + index * card_size;
121 cell end_addr = start_addr + card_size;
123 if (!start || (start + ((object*)start)->size()) < start_addr) {
124 /* Optimization because finding the objects in a memory range is
125 expensive. It helps a lot when tracing consecutive cards. */
126 cell gen_start_card = (gen->start - data->start) / card_size;
128 .find_object_containing_card(index - gen_start_card);
131 while (start && start < end_addr) {
132 trace_partial_objects(start, start_addr, end_addr);
133 if ((start + ((object*)start)->size()) >= end_addr) {
134 /* The object can overlap the card boundary, then the
135 remainder of it will be handled in the next card
136 tracing if that card is marked. */
139 start = gen->next_object_after(start);
144 template <typename SourceGeneration>
145 void trace_cards(SourceGeneration* gen, card mask, card unmask) {
146 card_deck* decks = data->decks;
147 card_deck* cards = data->cards;
149 cell first_deck = (gen->start - data->start) / deck_size;
150 cell last_deck = (gen->end - data->start) / deck_size;
152 /* Address of last traced object. */
155 for (cell deck_index = first_deck; deck_index < last_deck; deck_index++) {
156 if (decks[deck_index] & mask) {
157 decks[deck_index] &= ~unmask;
160 cell first_card = cards_per_deck * deck_index;
161 cell last_card = first_card + cards_per_deck;
163 for (cell card_index = first_card; card_index < last_card;
165 if (cards[card_index] & mask) {
166 cards[card_index] &= ~unmask;
169 start = trace_card(gen, card_index, start);
171 /* At end of generation, no need to scan more cards. */
180 void cheneys_algorithm() {
181 while (scan && scan < this->target->here) {
182 this->visitor.visit_object((object*)scan);
183 scan = this->target->next_object_after(scan);