| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_special_object() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 	fixnum n = untag_fixnum(ctx->peek()); | 
					
						
							|  |  |  | 	ctx->replace(special_objects[n]); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_set_special_object() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 	fixnum n = untag_fixnum(ctx->pop()); | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	cell value = ctx->pop(); | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 	special_objects[n] = value; | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 22:06:36 -05:00
										 |  |  | void factor_vm::primitive_identity_hashcode() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	cell tagged = ctx->peek(); | 
					
						
							| 
									
										
										
										
											2009-11-11 01:50:57 -05:00
										 |  |  | 	object *obj = untag<object>(tagged); | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	ctx->replace(tag_fixnum(obj->hashcode())); | 
					
						
							| 
									
										
										
										
											2009-11-11 01:50:57 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::compute_identity_hashcode(object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	object_counter++; | 
					
						
							|  |  |  | 	if(object_counter == 0) object_counter++; | 
					
						
							|  |  |  | 	obj->set_hashcode((cell)obj ^ object_counter); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_compute_identity_hashcode() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	object *obj = untag<object>(ctx->pop()); | 
					
						
							| 
									
										
										
										
											2009-11-11 01:50:57 -05:00
										 |  |  | 	compute_identity_hashcode(obj); | 
					
						
							| 
									
										
										
										
											2009-11-10 22:06:36 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | void factor_vm::primitive_set_slot() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	fixnum slot = untag_fixnum(ctx->pop()); | 
					
						
							|  |  |  | 	object *obj = untag<object>(ctx->pop()); | 
					
						
							|  |  |  | 	cell value = ctx->pop(); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cell *slot_ptr = &obj->slots()[slot]; | 
					
						
							|  |  |  | 	*slot_ptr = value; | 
					
						
							|  |  |  | 	write_barrier(slot_ptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-25 17:05:05 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | cell factor_vm::clone_object(cell obj_) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	data_root<object> obj(obj_,this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(immediate_p(obj.value())) | 
					
						
							|  |  |  | 		return obj.value(); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		cell size = object_size(obj.value()); | 
					
						
							| 
									
										
										
										
											2009-11-10 22:06:36 -05:00
										 |  |  | 		object *new_obj = allot_object(obj.type(),size); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 		memcpy(new_obj,obj.untagged(),size); | 
					
						
							| 
									
										
										
										
											2009-11-10 22:06:36 -05:00
										 |  |  | 		new_obj->set_hashcode(0); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 		return tag_dynamic(new_obj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-25 17:05:05 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | void factor_vm::primitive_clone() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	ctx->replace(clone_object(ctx->peek())); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Size of the object pointed to by a tagged pointer */ | 
					
						
							|  |  |  | cell factor_vm::object_size(cell tagged) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(immediate_p(tagged)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return untag<object>(tagged)->size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-16 00:30:55 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | void factor_vm::primitive_size() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-19 10:09:28 -04:00
										 |  |  | 	ctx->push(from_unsigned_cell(object_size(ctx->pop()))); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | struct slot_become_fixup : no_fixup { | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 	std::map<object *,object *> *become_map; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit slot_become_fixup(std::map<object *,object *> *become_map_) : | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 		become_map(become_map_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	object *fixup_data(object *old) | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		std::map<object *,object *>::const_iterator iter = become_map->find(old); | 
					
						
							|  |  |  | 		if(iter != become_map->end()) | 
					
						
							|  |  |  | 			return iter->second; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			return old; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct object_become_visitor { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	slot_visitor<slot_become_fixup> *workhorse; | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit object_become_visitor(slot_visitor<slot_become_fixup> *workhorse_) : | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 		workhorse(workhorse_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 22:49:03 -05:00
										 |  |  | 	void operator()(object *obj) | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-05 22:49:03 -05:00
										 |  |  | 		workhorse->visit_slots(obj); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | struct code_block_become_visitor { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	slot_visitor<slot_become_fixup> *workhorse; | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit code_block_become_visitor(slot_visitor<slot_become_fixup> *workhorse_) : | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 		workhorse(workhorse_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void operator()(code_block *compiled, cell size) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		workhorse->visit_code_block_objects(compiled); | 
					
						
							|  |  |  | 		workhorse->visit_embedded_literals(compiled); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct code_block_write_barrier_visitor { | 
					
						
							|  |  |  | 	code_heap *code; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	explicit code_block_write_barrier_visitor(code_heap *code_) : | 
					
						
							|  |  |  | 		code(code_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void operator()(code_block *compiled, cell size) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		code->write_barrier(compiled); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | /* classes.tuple uses this to reshape tuples; tools.deploy.shaker uses this
 | 
					
						
							|  |  |  |    to coalesce equal but distinct quotations and wrappers. */ | 
					
						
							|  |  |  | void factor_vm::primitive_become() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	array *new_objects = untag_check<array>(ctx->pop()); | 
					
						
							|  |  |  | 	array *old_objects = untag_check<array>(ctx->pop()); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cell capacity = array_capacity(new_objects); | 
					
						
							|  |  |  | 	if(capacity != array_capacity(old_objects)) | 
					
						
							|  |  |  | 		critical_error("bad parameters to become",0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Build the forwarding map */ | 
					
						
							|  |  |  | 	std::map<object *,object *> become_map; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(cell i = 0; i < capacity; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		tagged<object> old_obj(array_nth(old_objects,i)); | 
					
						
							|  |  |  | 		tagged<object> new_obj(array_nth(new_objects,i)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(old_obj != new_obj) | 
					
						
							|  |  |  | 			become_map[old_obj.untagged()] = new_obj.untagged(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Update all references to old objects to point to new objects */ | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 		slot_visitor<slot_become_fixup> workhorse(this,slot_become_fixup(&become_map)); | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 		workhorse.visit_roots(); | 
					
						
							|  |  |  | 		workhorse.visit_contexts(); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 		object_become_visitor object_visitor(&workhorse); | 
					
						
							|  |  |  | 		each_object(object_visitor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		code_block_become_visitor code_block_visitor(&workhorse); | 
					
						
							|  |  |  | 		each_code_block(code_block_visitor); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Since we may have introduced old->new references, need to revisit
 | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 	all objects and code blocks on a minor GC. */ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | 	data->mark_all_cards(); | 
					
						
							| 
									
										
										
										
											2010-01-27 00:42:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		code_block_write_barrier_visitor code_block_visitor(code); | 
					
						
							|  |  |  | 		each_code_block(code_block_visitor); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-05 20:03:51 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |