| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  | namespace factor { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct must_start_gc_again { | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename TargetGeneration, typename Policy> | 
					
						
							|  |  |  | struct gc_workhorse : no_fixup { | 
					
						
							|  |  |  |   static const bool translated_code_block_map = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   factor_vm* parent; | 
					
						
							|  |  |  |   TargetGeneration* target; | 
					
						
							|  |  |  |   Policy policy; | 
					
						
							|  |  |  |   code_heap* code; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-12 23:20:43 -04:00
										 |  |  |   gc_workhorse(factor_vm* parent, TargetGeneration* target, Policy policy) | 
					
						
							|  |  |  |       : parent(parent), target(target), policy(policy), code(parent->code) {} | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   object* resolve_forwarding(object* untagged) { | 
					
						
							|  |  |  |     parent->check_data_pointer(untagged); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* is there another forwarding pointer? */ | 
					
						
							|  |  |  |     while (untagged->forwarding_pointer_p()) | 
					
						
							|  |  |  |       untagged = untagged->forwarding_pointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* we've found the destination */ | 
					
						
							|  |  |  |     return untagged; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   object* promote_object(object* untagged) { | 
					
						
							|  |  |  |     cell size = untagged->size(); | 
					
						
							|  |  |  |     object* newpointer = target->allot(size); | 
					
						
							|  |  |  |     if (!newpointer) | 
					
						
							|  |  |  |       throw must_start_gc_again(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memcpy(newpointer, untagged, size); | 
					
						
							|  |  |  |     untagged->forward_to(newpointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy.promoted_object(newpointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return newpointer; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   object* fixup_data(object* obj) { | 
					
						
							|  |  |  |     parent->check_data_pointer(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!policy.should_copy_p(obj)) { | 
					
						
							|  |  |  |       policy.visited_object(obj); | 
					
						
							|  |  |  |       return obj; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     object* forwarding = resolve_forwarding(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (forwarding == obj) | 
					
						
							|  |  |  |       return promote_object(obj); | 
					
						
							|  |  |  |     else if (policy.should_copy_p(forwarding)) | 
					
						
							|  |  |  |       return promote_object(forwarding); | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       policy.visited_object(forwarding); | 
					
						
							|  |  |  |       return forwarding; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   code_block* fixup_code(code_block* compiled) { | 
					
						
							|  |  |  |     if (!code->marked_p(compiled)) { | 
					
						
							|  |  |  |       code->set_marked_p(compiled); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |       parent->mark_stack.push_back((cell)compiled + 1); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return compiled; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-10-07 16:48:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-30 04:15:50 -04:00
										 |  |  | struct dummy_unmarker { | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  |   void operator()(card* ptr) {} | 
					
						
							| 
									
										
										
										
											2009-10-30 04:15:50 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct simple_unmarker { | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  |   card unmask; | 
					
						
							| 
									
										
										
										
											2013-05-12 23:20:43 -04:00
										 |  |  |   explicit simple_unmarker(card unmask) : unmask(unmask) {} | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  |   void operator()(card* ptr) { *ptr &= ~unmask; } | 
					
						
							| 
									
										
										
										
											2009-10-30 04:15:50 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct full_unmarker { | 
					
						
							| 
									
										
										
										
											2013-05-12 21:48:38 -04:00
										 |  |  |   full_unmarker() {} | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  |   void operator()(card* ptr) { *ptr = 0; } | 
					
						
							| 
									
										
										
										
											2009-10-30 04:15:50 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  | template <typename TargetGeneration, typename Policy> struct collector { | 
					
						
							|  |  |  |   factor_vm* parent; | 
					
						
							|  |  |  |   data_heap* data; | 
					
						
							|  |  |  |   code_heap* code; | 
					
						
							|  |  |  |   TargetGeneration* target; | 
					
						
							|  |  |  |   gc_workhorse<TargetGeneration, Policy> workhorse; | 
					
						
							|  |  |  |   slot_visitor<gc_workhorse<TargetGeneration, Policy> > data_visitor; | 
					
						
							|  |  |  |   cell cards_scanned; | 
					
						
							|  |  |  |   cell decks_scanned; | 
					
						
							|  |  |  |   cell code_blocks_scanned; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-12 23:20:43 -04:00
										 |  |  |   collector(factor_vm* parent, TargetGeneration* target, Policy policy) | 
					
						
							|  |  |  |       : parent(parent), | 
					
						
							|  |  |  |         data(parent->data), | 
					
						
							|  |  |  |         code(parent->code), | 
					
						
							|  |  |  |         target(target), | 
					
						
							|  |  |  |         workhorse(parent, target, policy), | 
					
						
							| 
									
										
										
										
											2013-05-11 21:52:27 -04:00
										 |  |  |         data_visitor(parent, workhorse), | 
					
						
							|  |  |  |         cards_scanned(0), | 
					
						
							|  |  |  |         decks_scanned(0), | 
					
						
							|  |  |  |         code_blocks_scanned(0) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_handle(cell* handle) { data_visitor.visit_handle(handle); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_object(object* ptr) { | 
					
						
							|  |  |  |     data_visitor.visit_slots(ptr); | 
					
						
							|  |  |  |     if (ptr->type() == ALIEN_TYPE) | 
					
						
							|  |  |  |       ((alien*)ptr)->update_address(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_roots() { data_visitor.visit_roots(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_contexts() { data_visitor.visit_contexts(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_code_block_objects(code_block* compiled) { | 
					
						
							|  |  |  |     data_visitor.visit_code_block_objects(compiled); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_embedded_literals(code_block* compiled) { | 
					
						
							|  |  |  |     data_visitor.visit_embedded_literals(compiled); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_code_heap_roots(std::set<code_block*>* remembered_set) { | 
					
						
							|  |  |  |     std::set<code_block*>::const_iterator iter = remembered_set->begin(); | 
					
						
							|  |  |  |     std::set<code_block*>::const_iterator end = remembered_set->end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (; iter != end; iter++) { | 
					
						
							|  |  |  |       code_block* compiled = *iter; | 
					
						
							|  |  |  |       trace_code_block_objects(compiled); | 
					
						
							|  |  |  |       trace_embedded_literals(compiled); | 
					
						
							|  |  |  |       compiled->flush_icache(); | 
					
						
							|  |  |  |       code_blocks_scanned++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   inline cell first_card_in_deck(cell deck) { | 
					
						
							|  |  |  |     return deck << (deck_bits - card_bits); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   inline cell last_card_in_deck(cell deck) { | 
					
						
							|  |  |  |     return first_card_in_deck(deck + 1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   inline cell card_deck_for_address(cell a) { | 
					
						
							|  |  |  |     return addr_to_deck(a - data->start); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   inline cell card_start_address(cell card) { | 
					
						
							|  |  |  |     return (card << card_bits) + data->start; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   inline cell card_end_address(cell card) { | 
					
						
							|  |  |  |     return ((card + 1) << card_bits) + data->start; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void trace_partial_objects(cell start, cell end, cell card_start, | 
					
						
							|  |  |  |                              cell card_end) { | 
					
						
							|  |  |  |     if (card_start < end) { | 
					
						
							|  |  |  |       start += sizeof(cell); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (start < card_start) | 
					
						
							|  |  |  |         start = card_start; | 
					
						
							|  |  |  |       if (end > card_end) | 
					
						
							|  |  |  |         end = card_end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       cell* slot_ptr = (cell*)start; | 
					
						
							|  |  |  |       cell* end_ptr = (cell*)end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (; slot_ptr < end_ptr; slot_ptr++) | 
					
						
							|  |  |  |         data_visitor.visit_handle(slot_ptr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template <typename SourceGeneration, typename Unmarker> | 
					
						
							|  |  |  |   void trace_cards(SourceGeneration* gen, card mask, Unmarker unmarker) { | 
					
						
							|  |  |  |     card_deck* decks = data->decks; | 
					
						
							|  |  |  |     card_deck* cards = data->cards; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cell gen_start_card = addr_to_card(gen->start - data->start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cell first_deck = card_deck_for_address(gen->start); | 
					
						
							|  |  |  |     cell last_deck = card_deck_for_address(gen->end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cell start = 0, binary_start = 0, end = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (cell deck_index = first_deck; deck_index < last_deck; deck_index++) { | 
					
						
							|  |  |  |       if (decks[deck_index] & mask) { | 
					
						
							|  |  |  |         decks_scanned++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cell first_card = first_card_in_deck(deck_index); | 
					
						
							|  |  |  |         cell last_card = last_card_in_deck(deck_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (cell card_index = first_card; card_index < last_card; | 
					
						
							|  |  |  |              card_index++) { | 
					
						
							|  |  |  |           if (cards[card_index] & mask) { | 
					
						
							|  |  |  |             cards_scanned++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (end < card_start_address(card_index)) { | 
					
						
							|  |  |  |               start = gen->starts | 
					
						
							|  |  |  |                   .find_object_containing_card(card_index - gen_start_card); | 
					
						
							|  |  |  |               binary_start = start + ((object*)start)->binary_payload_start(); | 
					
						
							|  |  |  |               end = start + ((object*)start)->size(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           scan_next_object: | 
					
						
							|  |  |  |             if (start < card_end_address(card_index)) { | 
					
						
							|  |  |  |               trace_partial_objects(start, binary_start, | 
					
						
							|  |  |  |                                     card_start_address(card_index), | 
					
						
							|  |  |  |                                     card_end_address(card_index)); | 
					
						
							|  |  |  |               if (end < card_end_address(card_index)) { | 
					
						
							|  |  |  |                 start = gen->next_object_after(start); | 
					
						
							|  |  |  |                 if (start) { | 
					
						
							|  |  |  |                   binary_start = | 
					
						
							|  |  |  |                       start + ((object*)start)->binary_payload_start(); | 
					
						
							|  |  |  |                   end = start + ((object*)start)->size(); | 
					
						
							|  |  |  |                   goto scan_next_object; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             unmarker(&cards[card_index]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!start) | 
					
						
							|  |  |  |               return; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         unmarker(&decks[deck_index]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-10-07 16:48:09 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |