| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | factor::zone nursery; | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Set by the -securegc command line argument */ | 
					
						
							|  |  |  | bool secure_gc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* new objects are allocated here */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | VM_C_API zone nursery; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* GC is off during heap walking */ | 
					
						
							|  |  |  | bool gc_off; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | data_heap *data; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | cell init_zone(zone *z, cell size, cell start) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	z->size = size; | 
					
						
							|  |  |  | 	z->start = z->here = start; | 
					
						
							|  |  |  | 	z->end = start + size; | 
					
						
							|  |  |  | 	return z->end; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | void init_card_decks() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	cell start = align(data->seg->start,deck_size); | 
					
						
							|  |  |  | 	allot_markers_offset = (cell)data->allot_markers - (start >> card_bits); | 
					
						
							|  |  |  | 	cards_offset = (cell)data->cards - (start >> card_bits); | 
					
						
							|  |  |  | 	decks_offset = (cell)data->decks - (start >> deck_bits); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | data_heap *alloc_data_heap(cell gens, | 
					
						
							|  |  |  | 	cell young_size, | 
					
						
							|  |  |  | 	cell aging_size, | 
					
						
							|  |  |  | 	cell tenured_size) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	young_size = align(young_size,deck_size); | 
					
						
							|  |  |  | 	aging_size = align(aging_size,deck_size); | 
					
						
							|  |  |  | 	tenured_size = align(tenured_size,deck_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data_heap *data = (data_heap *)safe_malloc(sizeof(data_heap)); | 
					
						
							|  |  |  | 	data->young_size = young_size; | 
					
						
							|  |  |  | 	data->aging_size = aging_size; | 
					
						
							|  |  |  | 	data->tenured_size = tenured_size; | 
					
						
							|  |  |  | 	data->gen_count = gens; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell total_size; | 
					
						
							|  |  |  | 	if(data->gen_count == 2) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		total_size = young_size + 2 * tenured_size; | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	else if(data->gen_count == 3) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		total_size = young_size + 2 * aging_size + 2 * tenured_size; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		fatal_error("Invalid number of generations",data->gen_count); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		return NULL; /* can't happen */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	total_size += deck_size; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data->seg = alloc_segment(total_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data->generations = (zone *)safe_malloc(sizeof(zone) * data->gen_count); | 
					
						
							|  |  |  | 	data->semispaces = (zone *)safe_malloc(sizeof(zone) * data->gen_count); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	cell cards_size = total_size >> card_bits; | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data->allot_markers = (cell *)safe_malloc(cards_size); | 
					
						
							|  |  |  | 	data->allot_markers_end = data->allot_markers + cards_size; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data->cards = (cell *)safe_malloc(cards_size); | 
					
						
							|  |  |  | 	data->cards_end = data->cards + cards_size; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	cell decks_size = total_size >> deck_bits; | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data->decks = (cell *)safe_malloc(decks_size); | 
					
						
							|  |  |  | 	data->decks_end = data->decks + decks_size; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	cell alloter = align(data->seg->start,deck_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	alloter = init_zone(&data->generations[data->tenured()],tenured_size,alloter); | 
					
						
							|  |  |  | 	alloter = init_zone(&data->semispaces[data->tenured()],tenured_size,alloter); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	if(data->gen_count == 3) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 		alloter = init_zone(&data->generations[data->aging()],aging_size,alloter); | 
					
						
							|  |  |  | 		alloter = init_zone(&data->semispaces[data->aging()],aging_size,alloter); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	if(data->gen_count >= 2) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 		alloter = init_zone(&data->generations[data->nursery()],young_size,alloter); | 
					
						
							|  |  |  | 		alloter = init_zone(&data->semispaces[data->nursery()],0,alloter); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	if(data->seg->end - alloter > deck_size) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		critical_error("Bug in alloc_data_heap",alloter); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	return data; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | data_heap *grow_data_heap(data_heap *data, cell requested_bytes) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell new_tenured_size = (data->tenured_size * 2) + requested_bytes; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	return alloc_data_heap(data->gen_count, | 
					
						
							|  |  |  | 		data->young_size, | 
					
						
							|  |  |  | 		data->aging_size, | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		new_tenured_size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void dealloc_data_heap(data_heap *data) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	dealloc_segment(data->seg); | 
					
						
							|  |  |  | 	free(data->generations); | 
					
						
							|  |  |  | 	free(data->semispaces); | 
					
						
							|  |  |  | 	free(data->allot_markers); | 
					
						
							|  |  |  | 	free(data->cards); | 
					
						
							|  |  |  | 	free(data->decks); | 
					
						
							|  |  |  | 	free(data); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void clear_cards(cell from, cell to) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* NOTE: reverse order due to heap layout. */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	card *first_card = addr_to_card(data->generations[to].start); | 
					
						
							|  |  |  | 	card *last_card = addr_to_card(data->generations[from].end); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	memset(first_card,0,last_card - first_card); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void clear_decks(cell from, cell to) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* NOTE: reverse order due to heap layout. */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	card_deck *first_deck = addr_to_deck(data->generations[to].start); | 
					
						
							|  |  |  | 	card_deck *last_deck = addr_to_deck(data->generations[from].end); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	memset(first_deck,0,last_deck - first_deck); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void clear_allot_markers(cell from, cell to) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* NOTE: reverse order due to heap layout. */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	card *first_card = addr_to_allot_marker((object *)data->generations[to].start); | 
					
						
							|  |  |  | 	card *last_card = addr_to_allot_marker((object *)data->generations[from].end); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	memset(first_card,invalid_allot_marker,last_card - first_card); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void reset_generation(cell i) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	zone *z = (i == data->nursery() ? &nursery : &data->generations[i]); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	z->here = z->start; | 
					
						
							|  |  |  | 	if(secure_gc) | 
					
						
							|  |  |  | 		memset((void*)z->start,69,z->size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* After garbage collection, any generations which are now empty need to have
 | 
					
						
							|  |  |  | their allocation pointers and cards reset. */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void reset_generations(cell from, cell to) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell i; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	for(i = from; i <= to; i++) | 
					
						
							|  |  |  | 		reset_generation(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	clear_cards(from,to); | 
					
						
							|  |  |  | 	clear_decks(from,to); | 
					
						
							|  |  |  | 	clear_allot_markers(from,to); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void set_data_heap(data_heap *data_) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	data = data_; | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	nursery = data->generations[data->nursery()]; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	init_card_decks(); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	clear_cards(data->nursery(),data->tenured()); | 
					
						
							|  |  |  | 	clear_decks(data->nursery(),data->tenured()); | 
					
						
							|  |  |  | 	clear_allot_markers(data->nursery(),data->tenured()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | void init_data_heap(cell gens, | 
					
						
							|  |  |  | 	cell young_size, | 
					
						
							|  |  |  | 	cell aging_size, | 
					
						
							|  |  |  | 	cell tenured_size, | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	bool secure_gc_) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	set_data_heap(alloc_data_heap(gens,young_size,aging_size,tenured_size)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gc_locals_region = alloc_segment(getpagesize()); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	gc_locals = gc_locals_region->start - sizeof(cell); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 21:47:29 -04:00
										 |  |  | 	gc_bignums_region = alloc_segment(getpagesize()); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	gc_bignums = gc_bignums_region->start - sizeof(cell); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	secure_gc = secure_gc_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_data_gc(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Size of the object pointed to by a tagged pointer */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | cell object_size(cell tagged) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	if(immediate_p(tagged)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return untagged_object_size(untag<object>(tagged)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Size of the object pointed to by an untagged pointer */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | cell untagged_object_size(object *pointer) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	return align8(unaligned_object_size(pointer)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Size of the data area of an object pointed to by an untagged pointer */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | cell unaligned_object_size(object *pointer) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	switch(pointer->h.hi_tag()) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	case ARRAY_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return array_size((array*)pointer); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case BIGNUM_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return array_size((bignum*)pointer); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case BYTE_ARRAY_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return array_size((byte_array*)pointer); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case STRING_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return string_size(string_capacity((string*)pointer)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case TUPLE_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return tuple_size(untag<tuple_layout>(((tuple *)pointer)->layout)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case QUOTATION_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(quotation); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case WORD_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(word); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case FLOAT_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(boxed_float); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case DLL_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(dll); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case ALIEN_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(alien); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case WRAPPER_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(wrapper); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case CALLSTACK_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return callstack_size(untag_fixnum(((callstack *)pointer)->length)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		critical_error("Invalid header",(cell)pointer); | 
					
						
							| 
									
										
										
										
											2009-05-05 15:17:02 -04:00
										 |  |  | 		return 0; /* can't happen */ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(size) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	box_unsigned_cell(object_size(dpop())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The number of cells from the start of the object which should be scanned by
 | 
					
						
							|  |  |  | the GC. Some types have a binary payload at the end (string, word, DLL) which | 
					
						
							|  |  |  | we ignore. */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | cell binary_payload_start(object *pointer) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	switch(pointer->h.hi_tag()) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	/* these objects do not refer to other objects at all */ | 
					
						
							|  |  |  | 	case FLOAT_TYPE: | 
					
						
							|  |  |  | 	case BYTE_ARRAY_TYPE: | 
					
						
							|  |  |  | 	case BIGNUM_TYPE: | 
					
						
							|  |  |  | 	case CALLSTACK_TYPE: | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	/* these objects have some binary data at the end */ | 
					
						
							|  |  |  | 	case WORD_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(word) - sizeof(cell) * 3; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case ALIEN_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(cell) * 3; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case DLL_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(cell) * 2; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case QUOTATION_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(quotation) - sizeof(cell) * 2; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case STRING_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(string); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	/* everything else consists entirely of pointers */ | 
					
						
							|  |  |  | 	case ARRAY_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return array_size<array>(array_capacity((array*)pointer)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case TUPLE_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return tuple_size(untag<tuple_layout>(((tuple *)pointer)->layout)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case WRAPPER_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return sizeof(wrapper); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		critical_error("Invalid header",(cell)pointer); | 
					
						
							| 
									
										
										
										
											2009-05-05 15:17:02 -04:00
										 |  |  |                 return 0; /* can't happen */ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Push memory usage statistics in data heap */ | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(data_room) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	dpush(tag_fixnum((data->cards_end - data->cards) >> 10)); | 
					
						
							|  |  |  | 	dpush(tag_fixnum((data->decks_end - data->decks) >> 10)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 	growable_array a; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell gen; | 
					
						
							|  |  |  | 	for(gen = 0; gen < data->gen_count; gen++) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 		zone *z = (gen == data->nursery() ? &nursery : &data->generations[gen]); | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 		a.add(tag_fixnum((z->end - z->here) >> 10)); | 
					
						
							|  |  |  | 		a.add(tag_fixnum((z->size) >> 10)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 	a.trim(); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	dpush(a.elements.value()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A heap walk allows useful things to be done, like finding all
 | 
					
						
							|  |  |  | references to an object for debugging purposes. */ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | cell heap_scan_ptr; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Disables GC and activates next-object ( -- obj ) primitive */ | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | void begin_scan() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	heap_scan_ptr = data->generations[data->tenured()].start; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	gc_off = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | void end_scan() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	gc_off = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(begin_scan) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	begin_scan(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | cell next_object() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	if(!gc_off) | 
					
						
							|  |  |  | 		general_error(ERROR_HEAP_SCAN,F,F,NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	if(heap_scan_ptr >= data->generations[data->tenured()].here) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		return F; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	object *obj = (object *)heap_scan_ptr; | 
					
						
							|  |  |  | 	heap_scan_ptr += untagged_object_size(obj); | 
					
						
							|  |  |  | 	return tag_dynamic(obj); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Push object at heap scan cursor and advance; pushes f when done */ | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(next_object) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	dpush(next_object()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Re-enables GC */ | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(end_scan) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	gc_off = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | template<typename T> void each_object(T &functor) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	begin_scan(); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell obj; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	while((obj = next_object()) != F) | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | 		functor(tagged<object>(obj)); | 
					
						
							|  |  |  | 	end_scan(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | namespace | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct word_counter { | 
					
						
							|  |  |  | 	cell count; | 
					
						
							|  |  |  | 	word_counter() : count(0) {} | 
					
						
							|  |  |  | 	void operator()(tagged<object> obj) { if(obj.type_p(WORD_TYPE)) count++; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct word_accumulator { | 
					
						
							|  |  |  | 	growable_array words; | 
					
						
							|  |  |  | 	word_accumulator(int count) : words(count) {} | 
					
						
							|  |  |  | 	void operator()(tagged<object> obj) { if(obj.type_p(WORD_TYPE)) words.add(obj.value()); } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | cell find_all_words() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	word_counter counter; | 
					
						
							|  |  |  | 	each_object(counter); | 
					
						
							|  |  |  | 	word_accumulator accum(counter.count); | 
					
						
							|  |  |  | 	each_object(accum); | 
					
						
							|  |  |  | 	accum.words.trim(); | 
					
						
							|  |  |  | 	return accum.words.elements.value(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |