149 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			149 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
| namespace factor
 | |
| {
 | |
| 
 | |
| /* statistics */
 | |
| struct gc_stats {
 | |
| 	cell collections;
 | |
| 	u64 gc_time;
 | |
| 	u64 max_gc_time;
 | |
| 	cell object_count;
 | |
| 	u64 bytes_copied;
 | |
| };
 | |
| 
 | |
| extern zone *newspace;
 | |
| 
 | |
| extern bool performing_compaction;
 | |
| extern cell collecting_gen;
 | |
| extern bool collecting_aging_again;
 | |
| 
 | |
| extern cell last_code_heap_scan;
 | |
| 
 | |
| void init_data_gc();
 | |
| 
 | |
| void gc();
 | |
| 
 | |
| inline static bool collecting_accumulation_gen_p()
 | |
| {
 | |
| 	return ((data->have_aging_p()
 | |
| 		&& collecting_gen == data->aging()
 | |
| 		&& !collecting_aging_again)
 | |
| 		|| collecting_gen == data->tenured());
 | |
| }
 | |
| 
 | |
| void copy_handle(cell *handle);
 | |
| 
 | |
| void garbage_collection(volatile cell gen,
 | |
| 	bool growing_data_heap_,
 | |
| 	cell requested_bytes);
 | |
| 
 | |
| /* We leave this many bytes free at the top of the nursery so that inline
 | |
| allocation (which does not call GC because of possible roots in volatile
 | |
| registers) does not run out of memory */
 | |
| static const cell allot_buffer_zone = 1024;
 | |
| 
 | |
| inline static object *allot_zone(zone *z, cell a)
 | |
| {
 | |
| 	cell h = z->here;
 | |
| 	z->here = h + align8(a);
 | |
| 	object *obj = (object *)h;
 | |
| 	allot_barrier(obj);
 | |
| 	return obj;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * It is up to the caller to fill in the object's fields in a meaningful
 | |
|  * fashion!
 | |
|  */
 | |
| inline static object *allot_object(header header, cell size)
 | |
| {
 | |
| #ifdef GC_DEBUG
 | |
| 	if(!gc_off)
 | |
| 		gc();
 | |
| #endif
 | |
| 
 | |
| 	object *obj;
 | |
| 
 | |
| 	if(nursery.size - allot_buffer_zone > size)
 | |
| 	{
 | |
| 		/* If there is insufficient room, collect the nursery */
 | |
| 		if(nursery.here + allot_buffer_zone + size > nursery.end)
 | |
| 			garbage_collection(data->nursery(),false,0);
 | |
| 
 | |
| 		cell h = nursery.here;
 | |
| 		nursery.here = h + align8(size);
 | |
| 		obj = (object *)h;
 | |
| 	}
 | |
| 	/* If the object is bigger than the nursery, allocate it in
 | |
| 	tenured space */
 | |
| 	else
 | |
| 	{
 | |
| 		zone *tenured = &data->generations[data->tenured()];
 | |
| 
 | |
| 		/* If tenured space does not have enough room, collect */
 | |
| 		if(tenured->here + size > tenured->end)
 | |
| 		{
 | |
| 			gc();
 | |
| 			tenured = &data->generations[data->tenured()];
 | |
| 		}
 | |
| 
 | |
| 		/* If it still won't fit, grow the heap */
 | |
| 		if(tenured->here + size > tenured->end)
 | |
| 		{
 | |
| 			garbage_collection(data->tenured(),true,size);
 | |
| 			tenured = &data->generations[data->tenured()];
 | |
| 		}
 | |
| 
 | |
| 		obj = allot_zone(tenured,size);
 | |
| 
 | |
| 		/* Allows initialization code to store old->new pointers
 | |
| 		without hitting the write barrier in the common case of
 | |
| 		a nursery allocation */
 | |
| 		write_barrier(obj);
 | |
| 	}
 | |
| 
 | |
| 	obj->h = header;
 | |
| 	return obj;
 | |
| }
 | |
| 
 | |
| template<typename T> T *allot(cell size)
 | |
| {
 | |
| 	return (T *)allot_object(header(T::type_number),size);
 | |
| }
 | |
| 
 | |
| void copy_reachable_objects(cell scan, cell *end);
 | |
| 
 | |
| PRIMITIVE(gc);
 | |
| PRIMITIVE(gc_stats);
 | |
| void clear_gc_stats();
 | |
| PRIMITIVE(clear_gc_stats);
 | |
| PRIMITIVE(become);
 | |
| 
 | |
| extern bool growing_data_heap;
 | |
| 
 | |
| inline static void check_data_pointer(object *pointer)
 | |
| {
 | |
| #ifdef FACTOR_DEBUG
 | |
| 	if(!growing_data_heap)
 | |
| 	{
 | |
| 		assert((cell)pointer >= data->seg->start
 | |
| 		       && (cell)pointer < data->seg->end);
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| 
 | |
| inline static void check_tagged_pointer(cell tagged)
 | |
| {
 | |
| #ifdef FACTOR_DEBUG
 | |
| 	if(!immediate_p(tagged))
 | |
| 	{
 | |
| 		object *obj = untag<object>(tagged);
 | |
| 		check_data_pointer(obj);
 | |
| 		obj->h.hi_tag();
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| 
 | |
| VM_ASM_API void inline_gc(cell *gc_roots_base, cell gc_roots_size);
 | |
| 
 | |
| }
 |