| 
									
										
										
										
											2009-10-07 16:48:09 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  | namespace factor { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  | struct full_collection_copier : no_fixup { | 
					
						
							| 
									
										
										
										
											2015-08-03 18:06:57 -04:00
										 |  |  |   tenured_space* tenured; | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  |   code_heap* code; | 
					
						
							|  |  |  |   std::vector<cell> *mark_stack; | 
					
						
							| 
									
										
										
										
											2015-08-03 18:06:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  |   full_collection_copier(tenured_space* tenured, | 
					
						
							|  |  |  |                          code_heap* code, | 
					
						
							|  |  |  |                          std::vector<cell> *mark_stack) | 
					
						
							|  |  |  |       : tenured(tenured), code(code), mark_stack(mark_stack) { } | 
					
						
							| 
									
										
										
										
											2015-08-03 18:06:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  |   object* fixup_data(object* obj) { | 
					
						
							|  |  |  |     if (tenured->contains_p(obj)) { | 
					
						
							|  |  |  |       if (!tenured->state.marked_p((cell)obj)) { | 
					
						
							|  |  |  |         tenured->state.set_marked_p((cell)obj, obj->size()); | 
					
						
							|  |  |  |         mark_stack->push_back((cell)obj); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return obj; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Is there another forwarding pointer?
 | 
					
						
							|  |  |  |     while (obj->forwarding_pointer_p()) { | 
					
						
							|  |  |  |       object* dest = obj->forwarding_pointer(); | 
					
						
							|  |  |  |       obj = dest; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (tenured->contains_p(obj)) { | 
					
						
							|  |  |  |       if (!tenured->state.marked_p((cell)obj)) { | 
					
						
							|  |  |  |         tenured->state.set_marked_p((cell)obj, obj->size()); | 
					
						
							|  |  |  |         mark_stack->push_back((cell)obj); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return obj; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cell size = obj->size(); | 
					
						
							|  |  |  |     object* newpointer = tenured->allot(size); | 
					
						
							|  |  |  |     if (!newpointer) | 
					
						
							|  |  |  |       throw must_start_gc_again(); | 
					
						
							|  |  |  |     memcpy(newpointer, obj, size); | 
					
						
							|  |  |  |     obj->forward_to(newpointer); | 
					
						
							| 
									
										
										
										
											2015-08-03 18:06:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  |     tenured->state.set_marked_p((cell)newpointer, newpointer->size()); | 
					
						
							|  |  |  |     mark_stack->push_back((cell)newpointer); | 
					
						
							|  |  |  |     return newpointer; | 
					
						
							| 
									
										
										
										
											2015-08-03 18:06:57 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  |   code_block* fixup_code(code_block* compiled) { | 
					
						
							|  |  |  |     if (!code->allocator->state.marked_p((cell)compiled)) { | 
					
						
							|  |  |  |       code->allocator->state.set_marked_p((cell)compiled, compiled->size()); | 
					
						
							|  |  |  |       mark_stack->push_back((cell)compiled + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return compiled; | 
					
						
							| 
									
										
										
										
											2015-08-03 18:06:57 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 01:19:06 -05:00
										 |  |  | void factor_vm::collect_mark_impl() { | 
					
						
							| 
									
										
										
										
											2016-10-20 01:46:21 -04:00
										 |  |  |   gc_event* event = current_gc->event; | 
					
						
							|  |  |  |   if (event) | 
					
						
							|  |  |  |     event->reset_timer(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 06:35:38 -04:00
										 |  |  |   slot_visitor<full_collection_copier> | 
					
						
							|  |  |  |       visitor(this, full_collection_copier(data->tenured, code, &mark_stack)); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   mark_stack.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-09 16:28:16 -05:00
										 |  |  |   code->allocator->state.clear_mark_bits(); | 
					
						
							|  |  |  |   data->tenured->state.clear_mark_bits(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-18 23:43:53 -05:00
										 |  |  |   visitor.visit_all_roots(); | 
					
						
							| 
									
										
										
										
											2015-01-12 01:19:06 -05:00
										 |  |  |   visitor.visit_context_code_blocks(); | 
					
						
							|  |  |  |   visitor.visit_uninitialized_code_blocks(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-19 08:43:54 -05:00
										 |  |  |   visitor.visit_mark_stack(&mark_stack); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-10 10:14:54 -05:00
										 |  |  |   data->reset_tenured(); | 
					
						
							|  |  |  |   data->reset_aging(); | 
					
						
							|  |  |  |   data->reset_nursery(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   code->clear_remembered_set(); | 
					
						
							| 
									
										
										
										
											2016-10-20 01:46:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (event) | 
					
						
							|  |  |  |     event->ended_phase(PHASE_MARKING); | 
					
						
							| 
									
										
										
										
											2009-10-14 03:06:01 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-08 03:10:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  | void factor_vm::collect_sweep_impl() { | 
					
						
							|  |  |  |   gc_event* event = current_gc->event; | 
					
						
							|  |  |  |   if (event) | 
					
						
							| 
									
										
										
										
											2016-04-24 09:21:17 -04:00
										 |  |  |     event->reset_timer(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   data->tenured->sweep(); | 
					
						
							|  |  |  |   if (event) | 
					
						
							| 
									
										
										
										
											2016-10-19 04:31:53 -04:00
										 |  |  |     event->ended_phase(PHASE_DATA_SWEEP); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 02:12:40 -04:00
										 |  |  |   // After a sweep, invalidate any code heap roots which are not
 | 
					
						
							|  |  |  |   // marked, so that if a block makes a tail call to a generic word,
 | 
					
						
							|  |  |  |   // and the PIC compiler triggers a GC, and the caller block gets GCd
 | 
					
						
							|  |  |  |   // as a result, the PIC code won't try to overwrite the call site
 | 
					
						
							|  |  |  |   mark_bits* state = &code->allocator->state; | 
					
						
							|  |  |  |   FACTOR_FOR_EACH(code_roots) { | 
					
						
							|  |  |  |     code_root* root = *iter; | 
					
						
							|  |  |  |     cell block = root->value & (~data_alignment - 1); | 
					
						
							|  |  |  |     if (root->valid && !state->marked_p(block)) | 
					
						
							|  |  |  |       root->valid = false; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   if (event) | 
					
						
							| 
									
										
										
										
											2016-04-24 09:21:17 -04:00
										 |  |  |     event->reset_timer(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   code->sweep(); | 
					
						
							|  |  |  |   if (event) | 
					
						
							| 
									
										
										
										
											2016-10-19 04:31:53 -04:00
										 |  |  |     event->ended_phase(PHASE_CODE_SWEEP); | 
					
						
							| 
									
										
										
										
											2009-10-25 09:07:21 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 01:19:06 -05:00
										 |  |  | void factor_vm::collect_full() { | 
					
						
							|  |  |  |   collect_mark_impl(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   collect_sweep_impl(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (data->low_memory_p()) { | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |     // Full GC did not free up enough memory. Grow the heap.
 | 
					
						
							| 
									
										
										
										
											2016-10-19 03:05:15 -04:00
										 |  |  |     set_current_gc_op(COLLECT_GROWING_DATA_HEAP_OP); | 
					
						
							| 
									
										
										
										
											2016-10-12 19:46:52 -04:00
										 |  |  |     collect_growing_data_heap(0); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   } else if (data->high_fragmentation_p()) { | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |     // Enough free memory, but it is not contiguous. Perform a
 | 
					
						
							|  |  |  |     // compaction.
 | 
					
						
							| 
									
										
										
										
											2016-10-19 03:05:15 -04:00
										 |  |  |     set_current_gc_op(COLLECT_COMPACT_OP); | 
					
						
							| 
									
										
										
										
											2015-01-12 01:19:06 -05:00
										 |  |  |     collect_compact_impl(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:02:39 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   code->flush_icache(); | 
					
						
							| 
									
										
										
										
											2009-10-07 16:48:09 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |