| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | code_heap::code_heap(cell size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-13 21:00:02 -05:00
										 |  |  | 	if(size > ((u64)1 << (sizeof(cell) * 8 - 6))) fatal_error("Heap too large",size); | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | 	seg = new segment(align_page(size),true); | 
					
						
							| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | 	if(!seg) fatal_error("Out of memory in code_heap constructor",size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cell start = seg->start + seh_area_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allocator = new free_list_allocator<code_block>(seg->end - start,start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* See os-windows-nt-x86.64.cpp for seh_area usage */ | 
					
						
							|  |  |  | 	seh_area = (char *)seg->start; | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | code_heap::~code_heap() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	delete allocator; | 
					
						
							|  |  |  | 	allocator = NULL; | 
					
						
							|  |  |  | 	delete seg; | 
					
						
							|  |  |  | 	seg = NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-06 02:42:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 05:36:34 -04:00
										 |  |  | void code_heap::write_barrier(code_block *compiled) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-09 00:10:32 -04:00
										 |  |  | 	points_to_nursery.insert(compiled); | 
					
						
							|  |  |  | 	points_to_aging.insert(compiled); | 
					
						
							| 
									
										
										
										
											2009-10-06 05:36:34 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 03:55:02 -04:00
										 |  |  | void code_heap::clear_remembered_set() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	points_to_nursery.clear(); | 
					
						
							|  |  |  | 	points_to_aging.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | bool code_heap::uninitialized_p(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-10-06 06:52:45 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	return uninitialized_blocks.count(compiled) > 0; | 
					
						
							| 
									
										
										
										
											2009-10-06 06:52:45 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-24 22:24:06 -04:00
										 |  |  | bool code_heap::marked_p(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	return allocator->state.marked_p(compiled); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void code_heap::set_marked_p(code_block *compiled) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	allocator->state.set_marked_p(compiled); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void code_heap::clear_mark_bits() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	allocator->state.clear_mark_bits(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 06:27:48 -05:00
										 |  |  | void code_heap::free(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-10-06 05:36:34 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-02 06:27:48 -05:00
										 |  |  | 	assert(!uninitialized_p(compiled)); | 
					
						
							| 
									
										
										
										
											2009-10-09 00:10:32 -04:00
										 |  |  | 	points_to_nursery.erase(compiled); | 
					
						
							|  |  |  | 	points_to_aging.erase(compiled); | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | 	allocator->free(compiled); | 
					
						
							| 
									
										
										
										
											2009-10-06 05:36:34 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | void code_heap::flush_icache() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	factor::flush_icache(seg->start,seg->size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Allocate a code heap during startup */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void factor_vm::init_code_heap(cell size) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | 	code = new code_heap(size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | bool factor_vm::in_code_heap_p(cell ptr) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 21:32:00 -04:00
										 |  |  | 	return (ptr >= code->seg->start && ptr <= code->seg->end); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 02:42:17 -04:00
										 |  |  | struct word_updater { | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	bool reset_inline_caches; | 
					
						
							| 
									
										
										
										
											2009-10-06 02:42:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	word_updater(factor_vm *parent_, bool reset_inline_caches_) : | 
					
						
							|  |  |  | 		parent(parent_), reset_inline_caches(reset_inline_caches_) {} | 
					
						
							| 
									
										
										
										
											2009-10-25 00:02:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 04:05:20 -04:00
										 |  |  | 	void operator()(code_block *compiled, cell size) | 
					
						
							| 
									
										
										
										
											2009-10-06 02:42:17 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 		parent->update_word_references(compiled,reset_inline_caches); | 
					
						
							| 
									
										
										
										
											2009-10-06 02:42:17 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | /* Update pointers to words referenced from all code blocks.
 | 
					
						
							|  |  |  | Only needed after redefining an existing word. | 
					
						
							|  |  |  | If generic words were redefined, inline caches need to be reset. */ | 
					
						
							|  |  |  | void factor_vm::update_code_heap_words(bool reset_inline_caches) | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:08 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	word_updater updater(this,reset_inline_caches); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	each_code_block(updater); | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | /* Fix up new words only.
 | 
					
						
							|  |  |  | Fast path for compilation units that only define new words. */ | 
					
						
							|  |  |  | void factor_vm::initialize_code_blocks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::map<code_block *, cell>::const_iterator iter = code->uninitialized_blocks.begin(); | 
					
						
							|  |  |  | 	std::map<code_block *, cell>::const_iterator end = code->uninitialized_blocks.end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(; iter != end; iter++) | 
					
						
							|  |  |  | 		initialize_code_block(iter->first,iter->second); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	code->uninitialized_blocks.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_modify_code_heap() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	bool reset_inline_caches = to_boolean(ctx->pop()); | 
					
						
							|  |  |  | 	bool update_existing_words = to_boolean(ctx->pop()); | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	data_root<array> alist(ctx->pop(),this); | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell count = array_capacity(alist.untagged()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(count == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 	for(cell i = 0; i < count; i++) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-02 19:10:34 -05:00
										 |  |  | 		data_root<array> pair(array_nth(alist.untagged(),i),this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 19:10:34 -05:00
										 |  |  | 		data_root<word> word(array_nth(pair.untagged(),0),this); | 
					
						
							|  |  |  | 		data_root<object> data(array_nth(pair.untagged(),1),this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 		switch(data.type()) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 		case QUOTATION_TYPE: | 
					
						
							|  |  |  | 			jit_compile_word(word.value(),data.value(),false); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case ARRAY_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				array *compiled_data = data.as<array>().untagged(); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 				cell parameters = array_nth(compiled_data,0); | 
					
						
							|  |  |  | 				cell literals = array_nth(compiled_data,1); | 
					
						
							|  |  |  | 				cell relocation = array_nth(compiled_data,2); | 
					
						
							|  |  |  | 				cell labels = array_nth(compiled_data,3); | 
					
						
							|  |  |  | 				cell code = array_nth(compiled_data,4); | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				code_block *compiled = add_code_block( | 
					
						
							| 
									
										
										
										
											2009-10-20 10:37:24 -04:00
										 |  |  | 					code_block_optimized, | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 					code, | 
					
						
							|  |  |  | 					labels, | 
					
						
							| 
									
										
										
										
											2009-11-25 20:12:09 -05:00
										 |  |  | 					word.value(), | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 					relocation, | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 					parameters, | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 					literals); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				word->code = compiled; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			critical_error("Expected a quotation or an array",data.value()); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		update_word_entry_point(word.untagged()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	if(update_existing_words) | 
					
						
							|  |  |  | 		update_code_heap_words(reset_inline_caches); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		initialize_code_blocks(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-27 22:31:28 -04:00
										 |  |  | code_heap_room factor_vm::code_room() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-27 04:32:28 -04:00
										 |  |  | 	code_heap_room room; | 
					
						
							| 
									
										
										
										
											2009-10-25 14:18:06 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-27 04:32:28 -04:00
										 |  |  | 	room.size             = code->allocator->size; | 
					
						
							|  |  |  | 	room.occupied_space   = code->allocator->occupied_space(); | 
					
						
							|  |  |  | 	room.total_free       = code->allocator->free_space(); | 
					
						
							| 
									
										
										
										
											2009-10-30 03:26:57 -04:00
										 |  |  | 	room.contiguous_free  = code->allocator->largest_free_block(); | 
					
						
							|  |  |  | 	room.free_block_count = code->allocator->free_block_count(); | 
					
						
							| 
									
										
										
										
											2009-10-25 14:18:06 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-27 22:31:28 -04:00
										 |  |  | 	return room; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_code_room() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	code_heap_room room = code_room(); | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	ctx->push(tag<byte_array>(byte_array_from_value(&room))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 07:25:07 -04:00
										 |  |  | struct stack_trace_stripper { | 
					
						
							|  |  |  | 	explicit stack_trace_stripper() {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 04:05:20 -04:00
										 |  |  | 	void operator()(code_block *compiled, cell size) | 
					
						
							| 
									
										
										
										
											2009-10-06 07:25:07 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 		compiled->owner = false_object; | 
					
						
							| 
									
										
										
										
											2009-10-06 07:25:07 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_strip_stack_traces() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	stack_trace_stripper stripper; | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	each_code_block(stripper); | 
					
						
							| 
									
										
										
										
											2009-10-06 07:25:07 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 07:46:17 -05:00
										 |  |  | struct code_block_accumulator { | 
					
						
							|  |  |  | 	std::vector<cell> objects; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void operator()(code_block *compiled, cell size) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		objects.push_back(compiled->owner); | 
					
						
							|  |  |  | 		objects.push_back(compiled->parameters); | 
					
						
							|  |  |  | 		objects.push_back(compiled->relocation); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		objects.push_back(tag_fixnum(compiled->type())); | 
					
						
							|  |  |  | 		objects.push_back(tag_fixnum(compiled->size())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Note: the entry point is always a multiple of the heap
 | 
					
						
							|  |  |  | 		alignment (16 bytes). We cannot allocate while iterating | 
					
						
							|  |  |  | 		through the code heap, so it is not possible to call allot_cell() | 
					
						
							|  |  |  | 		here. It is OK, however, to add it as if it were a fixnum, and | 
					
						
							|  |  |  | 		have library code shift it to the left by 4. */ | 
					
						
							|  |  |  | 		cell entry_point = (cell)compiled->entry_point(); | 
					
						
							|  |  |  | 		assert((entry_point & (data_alignment - 1)) == 0); | 
					
						
							|  |  |  | 		assert((entry_point & TAG_MASK) == FIXNUM_TYPE); | 
					
						
							|  |  |  | 		objects.push_back(entry_point); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cell factor_vm::code_blocks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	code_block_accumulator accum; | 
					
						
							|  |  |  | 	each_code_block(accum); | 
					
						
							|  |  |  | 	return std_vector_to_array(accum.objects); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_code_blocks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ctx->push(code_blocks()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } |