vm: rewrite 'become' primitive so that it uses a slot visitor instead of GC
							parent
							
								
									6c87f20286
								
							
						
					
					
						commit
						72ab6ec548
					
				
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -58,6 +58,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
 | 
			
		|||
	vm/math.o \
 | 
			
		||||
	vm/nursery_collector.o \
 | 
			
		||||
	vm/object_start_map.o \
 | 
			
		||||
	vm/objects.o \
 | 
			
		||||
	vm/primitives.o \
 | 
			
		||||
	vm/profiler.o \
 | 
			
		||||
	vm/quotations.o \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,15 +15,6 @@ struct aging_space : bump_allocator<object> {
 | 
			
		|||
		starts.record_object_start_offset(obj);
 | 
			
		||||
		return obj;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cell next_object_after(cell scan)
 | 
			
		||||
	{
 | 
			
		||||
		cell size = ((object *)scan)->size();
 | 
			
		||||
		if(scan + size < here)
 | 
			
		||||
			return scan + size;
 | 
			
		||||
		else
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,23 @@ template<typename Block> struct bump_allocator {
 | 
			
		|||
	{
 | 
			
		||||
		return end - here;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cell next_object_after(cell scan)
 | 
			
		||||
	{
 | 
			
		||||
		cell size = ((Block *)scan)->size();
 | 
			
		||||
		if(scan + size < here)
 | 
			
		||||
			return scan + size;
 | 
			
		||||
		else
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cell first_object()
 | 
			
		||||
	{
 | 
			
		||||
		if(start != here)
 | 
			
		||||
			return start;
 | 
			
		||||
		else
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,10 +118,8 @@ struct word_and_literal_code_heap_updater {
 | 
			
		|||
 | 
			
		||||
void factor_vm::update_code_heap_words_and_literals()
 | 
			
		||||
{
 | 
			
		||||
	current_gc->event->started_code_sweep();
 | 
			
		||||
	word_and_literal_code_heap_updater updater(this);
 | 
			
		||||
	code->allocator->sweep(updater);
 | 
			
		||||
	current_gc->event->ended_code_sweep();
 | 
			
		||||
	iterate_code_heap(updater);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* After growing the heap, we have to perform a full relocation to update
 | 
			
		||||
| 
						 | 
				
			
			@ -152,8 +150,7 @@ void factor_vm::primitive_modify_code_heap()
 | 
			
		|||
	if(count == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	cell i;
 | 
			
		||||
	for(i = 0; i < count; i++)
 | 
			
		||||
	for(cell i = 0; i < count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		data_root<array> pair(array_nth(alist.untagged(),i),this);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -196,4 +196,12 @@ void factor_vm::primitive_check_datastack()
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_load_locals()
 | 
			
		||||
{
 | 
			
		||||
	fixnum count = untag_fixnum(dpop());
 | 
			
		||||
	memcpy((cell *)(rs + sizeof(cell)),(cell *)(ds - sizeof(cell) * (count - 1)),sizeof(cell) * count);
 | 
			
		||||
	ds -= sizeof(cell) * count;
 | 
			
		||||
	rs += sizeof(cell) * count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,12 @@ bool data_heap::low_memory_p()
 | 
			
		|||
	return (tenured->free_space() <= nursery->size + aging->size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void data_heap::mark_all_cards()
 | 
			
		||||
{
 | 
			
		||||
	memset(cards,-1,cards_end - cards);
 | 
			
		||||
	memset(decks,-1,decks_end - decks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::set_data_heap(data_heap *data_)
 | 
			
		||||
{
 | 
			
		||||
	data = data_;
 | 
			
		||||
| 
						 | 
				
			
			@ -115,15 +121,6 @@ void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_si
 | 
			
		|||
	set_data_heap(new data_heap(young_size,aging_size,tenured_size));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Size of the object pointed to by an untagged pointer */
 | 
			
		||||
cell object::size() const
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -201,11 +198,6 @@ cell object::binary_payload_start() const
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_size()
 | 
			
		||||
{
 | 
			
		||||
	box_unsigned_cell(object_size(dpop()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
data_heap_room factor_vm::data_room()
 | 
			
		||||
{
 | 
			
		||||
	data_heap_room room;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ struct data_heap {
 | 
			
		|||
	void reset_generation(aging_space *gen);
 | 
			
		||||
	void reset_generation(tenured_space *gen);
 | 
			
		||||
	bool low_memory_p();
 | 
			
		||||
	void mark_all_cards();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct data_heap_room {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,6 +86,7 @@ void factor_vm::do_stage1_init()
 | 
			
		|||
	fflush(stdout);
 | 
			
		||||
 | 
			
		||||
	compile_all_words();
 | 
			
		||||
	update_code_heap_words();
 | 
			
		||||
	special_objects[OBJ_STAGE2] = true_object;
 | 
			
		||||
 | 
			
		||||
	std::cout << "done\n";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,6 +116,10 @@ void factor_vm::collect_sweep_impl()
 | 
			
		|||
	data->tenured->sweep();
 | 
			
		||||
	update_code_roots_for_sweep();
 | 
			
		||||
	current_gc->event->ended_data_sweep();
 | 
			
		||||
 | 
			
		||||
	current_gc->event->started_code_sweep();
 | 
			
		||||
	code->allocator->sweep();
 | 
			
		||||
	current_gc->event->ended_code_sweep();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::collect_full(bool trace_contexts_p)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								vm/gc.cpp
								
								
								
								
							
							
						
						
									
										35
									
								
								vm/gc.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -218,37 +218,6 @@ void factor_vm::primitive_compact_gc()
 | 
			
		|||
		true /* trace contexts? */);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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()
 | 
			
		||||
{
 | 
			
		||||
	array *new_objects = untag_check<array>(dpop());
 | 
			
		||||
	array *old_objects = untag_check<array>(dpop());
 | 
			
		||||
 | 
			
		||||
	cell capacity = array_capacity(new_objects);
 | 
			
		||||
	if(capacity != array_capacity(old_objects))
 | 
			
		||||
		critical_error("bad parameters to become",0);
 | 
			
		||||
 | 
			
		||||
	cell i;
 | 
			
		||||
 | 
			
		||||
	for(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)
 | 
			
		||||
			old_obj->h.forward_to(new_obj.untagged());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	primitive_full_gc();
 | 
			
		||||
 | 
			
		||||
	/* If a word's definition quotation was in old_objects and the
 | 
			
		||||
	   quotation in new_objects is not compiled, we might leak memory
 | 
			
		||||
	   by referencing the old quotation unless we recompile all
 | 
			
		||||
	   unoptimized words. */
 | 
			
		||||
	compile_all_words();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::inline_gc(cell *data_roots_base, cell data_roots_size)
 | 
			
		||||
{
 | 
			
		||||
	for(cell i = 0; i < data_roots_size; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -290,9 +259,7 @@ object *factor_vm::allot_large_object(header header, cell size)
 | 
			
		|||
	/* Allows initialization code to store old->new pointers
 | 
			
		||||
	without hitting the write barrier in the common case of
 | 
			
		||||
	a nursery allocation */
 | 
			
		||||
	char *start = (char *)obj;
 | 
			
		||||
	for(cell offset = 0; offset < size; offset += card_size)
 | 
			
		||||
		write_barrier((cell *)(start + offset));
 | 
			
		||||
	write_barrier(obj,size);
 | 
			
		||||
 | 
			
		||||
	obj->h = header;
 | 
			
		||||
	return obj;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@ namespace factor
 | 
			
		|||
#include "segments.hpp"
 | 
			
		||||
#include "contexts.hpp"
 | 
			
		||||
#include "run.hpp"
 | 
			
		||||
#include "objects.hpp"
 | 
			
		||||
#include "profiler.hpp"
 | 
			
		||||
#include "errors.hpp"
 | 
			
		||||
#include "bignumint.hpp"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,137 @@
 | 
			
		|||
#include "master.hpp"
 | 
			
		||||
 | 
			
		||||
namespace factor
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_special_object()
 | 
			
		||||
{
 | 
			
		||||
	fixnum e = untag_fixnum(dpeek());
 | 
			
		||||
	drepl(special_objects[e]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_set_special_object()
 | 
			
		||||
{
 | 
			
		||||
	fixnum e = untag_fixnum(dpop());
 | 
			
		||||
	cell value = dpop();
 | 
			
		||||
	special_objects[e] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_set_slot()
 | 
			
		||||
{
 | 
			
		||||
	fixnum slot = untag_fixnum(dpop());
 | 
			
		||||
	object *obj = untag<object>(dpop());
 | 
			
		||||
	cell value = dpop();
 | 
			
		||||
 | 
			
		||||
	cell *slot_ptr = &obj->slots()[slot];
 | 
			
		||||
	*slot_ptr = value;
 | 
			
		||||
	write_barrier(slot_ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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());
 | 
			
		||||
		object *new_obj = allot_object(header(obj.type()),size);
 | 
			
		||||
		memcpy(new_obj,obj.untagged(),size);
 | 
			
		||||
		return tag_dynamic(new_obj);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_clone()
 | 
			
		||||
{
 | 
			
		||||
	drepl(clone_object(dpeek()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_size()
 | 
			
		||||
{
 | 
			
		||||
	box_unsigned_cell(object_size(dpop()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct slot_become_visitor {
 | 
			
		||||
	std::map<object *,object *> *become_map;
 | 
			
		||||
 | 
			
		||||
	explicit slot_become_visitor(std::map<object *,object *> *become_map_) :
 | 
			
		||||
		become_map(become_map_) {}
 | 
			
		||||
 | 
			
		||||
	object *operator()(object *old)
 | 
			
		||||
	{
 | 
			
		||||
		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 {
 | 
			
		||||
	slot_visitor<slot_become_visitor> *workhorse;
 | 
			
		||||
 | 
			
		||||
	explicit object_become_visitor(slot_visitor<slot_become_visitor> *workhorse_) :
 | 
			
		||||
		workhorse(workhorse_) {}
 | 
			
		||||
 | 
			
		||||
	void operator()(cell obj)
 | 
			
		||||
	{
 | 
			
		||||
		workhorse->visit_slots(tagged<object>(obj).untagged());
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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()
 | 
			
		||||
{
 | 
			
		||||
	array *new_objects = untag_check<array>(dpop());
 | 
			
		||||
	array *old_objects = untag_check<array>(dpop());
 | 
			
		||||
 | 
			
		||||
	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 */
 | 
			
		||||
	slot_visitor<slot_become_visitor> workhorse(this,slot_become_visitor(&become_map));
 | 
			
		||||
	workhorse.visit_roots();
 | 
			
		||||
	workhorse.visit_contexts();
 | 
			
		||||
 | 
			
		||||
	object_become_visitor object_visitor(&workhorse);
 | 
			
		||||
	each_object(object_visitor);
 | 
			
		||||
 | 
			
		||||
	/* Since we may have introduced old->new references, need to revisit
 | 
			
		||||
	all objects on a minor GC. */
 | 
			
		||||
	data->mark_all_cards();
 | 
			
		||||
 | 
			
		||||
	/* If a word's definition quotation was in old_objects and the
 | 
			
		||||
	   quotation in new_objects is not compiled, we might leak memory
 | 
			
		||||
	   by referencing the old quotation unless we recompile all
 | 
			
		||||
	   unoptimized words. */
 | 
			
		||||
	compile_all_words();
 | 
			
		||||
 | 
			
		||||
	/* Update references to old objects in the code heap */
 | 
			
		||||
	update_code_heap_words_and_literals();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
namespace factor
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
static const cell special_object_count = 70;
 | 
			
		||||
 | 
			
		||||
enum special_object {
 | 
			
		||||
	OBJ_NAMESTACK,            /* used by library only */
 | 
			
		||||
	OBJ_CATCHSTACK,           /* used by library only, per-callback */
 | 
			
		||||
 | 
			
		||||
	OBJ_CURRENT_CALLBACK = 2, /* used by library only, per-callback */
 | 
			
		||||
	OBJ_WALKER_HOOK,          /* non-local exit hook, used by library only */
 | 
			
		||||
	OBJ_CALLCC_1,             /* used to pass the value in callcc1 */
 | 
			
		||||
 | 
			
		||||
	OBJ_BREAK            = 5, /* quotation called by throw primitive */
 | 
			
		||||
	OBJ_ERROR,                /* a marker consed onto kernel errors */
 | 
			
		||||
 | 
			
		||||
	OBJ_CELL_SIZE        = 7, /* sizeof(cell) */
 | 
			
		||||
	OBJ_CPU,                  /* CPU architecture */
 | 
			
		||||
	OBJ_OS,                   /* operating system name */
 | 
			
		||||
 | 
			
		||||
	OBJ_ARGS            = 10, /* command line arguments */
 | 
			
		||||
	OBJ_STDIN,                /* stdin FILE* handle */
 | 
			
		||||
	OBJ_STDOUT,               /* stdout FILE* handle */
 | 
			
		||||
 | 
			
		||||
	OBJ_IMAGE           = 13, /* image path name */
 | 
			
		||||
	OBJ_EXECUTABLE,		  /* runtime executable path name */
 | 
			
		||||
 | 
			
		||||
	OBJ_EMBEDDED 	    = 15, /* are we embedded in another app? */
 | 
			
		||||
	OBJ_EVAL_CALLBACK,        /* used when Factor is embedded in a C app */
 | 
			
		||||
	OBJ_YIELD_CALLBACK,       /* used when Factor is embedded in a C app */
 | 
			
		||||
	OBJ_SLEEP_CALLBACK,       /* used when Factor is embedded in a C app */
 | 
			
		||||
 | 
			
		||||
	OBJ_COCOA_EXCEPTION = 19, /* Cocoa exception handler quotation */
 | 
			
		||||
 | 
			
		||||
	OBJ_BOOT            = 20, /* boot quotation */
 | 
			
		||||
	OBJ_GLOBAL,               /* global namespace */
 | 
			
		||||
 | 
			
		||||
	/* Quotation compilation in quotations.c */
 | 
			
		||||
	JIT_PROLOG          = 23,
 | 
			
		||||
	JIT_PRIMITIVE_WORD,
 | 
			
		||||
	JIT_PRIMITIVE,
 | 
			
		||||
	JIT_WORD_JUMP,
 | 
			
		||||
	JIT_WORD_CALL,
 | 
			
		||||
	JIT_WORD_SPECIAL,
 | 
			
		||||
	JIT_IF_WORD,
 | 
			
		||||
	JIT_IF,
 | 
			
		||||
	JIT_EPILOG,
 | 
			
		||||
	JIT_RETURN,
 | 
			
		||||
	JIT_PROFILING,
 | 
			
		||||
	JIT_PUSH_IMMEDIATE,
 | 
			
		||||
	JIT_DIP_WORD,
 | 
			
		||||
	JIT_DIP,
 | 
			
		||||
	JIT_2DIP_WORD,
 | 
			
		||||
	JIT_2DIP,
 | 
			
		||||
	JIT_3DIP_WORD,
 | 
			
		||||
	JIT_3DIP,
 | 
			
		||||
	JIT_EXECUTE_WORD,
 | 
			
		||||
	JIT_EXECUTE_JUMP,
 | 
			
		||||
	JIT_EXECUTE_CALL,
 | 
			
		||||
	JIT_DECLARE_WORD,
 | 
			
		||||
 | 
			
		||||
	/* Callback stub generation in callbacks.c */
 | 
			
		||||
	CALLBACK_STUB       = 45,
 | 
			
		||||
 | 
			
		||||
	/* Polymorphic inline cache generation in inline_cache.c */
 | 
			
		||||
	PIC_LOAD            = 47,
 | 
			
		||||
	PIC_TAG,
 | 
			
		||||
	PIC_TUPLE,
 | 
			
		||||
	PIC_CHECK_TAG,
 | 
			
		||||
	PIC_CHECK_TUPLE,
 | 
			
		||||
	PIC_HIT,
 | 
			
		||||
	PIC_MISS_WORD,
 | 
			
		||||
	PIC_MISS_TAIL_WORD,
 | 
			
		||||
 | 
			
		||||
	/* Megamorphic cache generation in dispatch.c */
 | 
			
		||||
	MEGA_LOOKUP         = 57,
 | 
			
		||||
	MEGA_LOOKUP_WORD,
 | 
			
		||||
	MEGA_MISS_WORD,
 | 
			
		||||
 | 
			
		||||
	OBJ_UNDEFINED       = 60, /* default quotation for undefined words */
 | 
			
		||||
 | 
			
		||||
	OBJ_STDERR          = 61, /* stderr FILE* handle */
 | 
			
		||||
 | 
			
		||||
	OBJ_STAGE2          = 62, /* have we bootstrapped? */
 | 
			
		||||
 | 
			
		||||
	OBJ_CURRENT_THREAD  = 63,
 | 
			
		||||
 | 
			
		||||
	OBJ_THREADS         = 64,
 | 
			
		||||
	OBJ_RUN_QUEUE       = 65,
 | 
			
		||||
	OBJ_SLEEP_QUEUE     = 66,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define OBJ_FIRST_SAVE OBJ_BOOT
 | 
			
		||||
#define OBJ_LAST_SAVE OBJ_STAGE2
 | 
			
		||||
 | 
			
		||||
inline static bool save_env_p(cell i)
 | 
			
		||||
{
 | 
			
		||||
	return (i >= OBJ_FIRST_SAVE && i <= OBJ_LAST_SAVE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -49,8 +49,8 @@ PRIMITIVE_FORWARD(float_greater)
 | 
			
		|||
PRIMITIVE_FORWARD(float_greatereq)
 | 
			
		||||
PRIMITIVE_FORWARD(word)
 | 
			
		||||
PRIMITIVE_FORWARD(word_xt)
 | 
			
		||||
PRIMITIVE_FORWARD(getenv)
 | 
			
		||||
PRIMITIVE_FORWARD(setenv)
 | 
			
		||||
PRIMITIVE_FORWARD(special_object)
 | 
			
		||||
PRIMITIVE_FORWARD(set_special_object)
 | 
			
		||||
PRIMITIVE_FORWARD(existsp)
 | 
			
		||||
PRIMITIVE_FORWARD(minor_gc)
 | 
			
		||||
PRIMITIVE_FORWARD(full_gc)
 | 
			
		||||
| 
						 | 
				
			
			@ -185,8 +185,8 @@ const primitive_type primitives[] = {
 | 
			
		|||
	primitive_float_greatereq,
 | 
			
		||||
	primitive_word,
 | 
			
		||||
	primitive_word_xt,
 | 
			
		||||
	primitive_getenv,
 | 
			
		||||
	primitive_setenv,
 | 
			
		||||
	primitive_special_object,
 | 
			
		||||
	primitive_set_special_object,
 | 
			
		||||
	primitive_existsp,
 | 
			
		||||
	primitive_minor_gc,
 | 
			
		||||
	primitive_full_gc,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -341,8 +341,6 @@ void factor_vm::compile_all_words()
 | 
			
		|||
		update_word_xt(word.untagged());
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	update_code_heap_words();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Allocates memory */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										52
									
								
								vm/run.cpp
								
								
								
								
							
							
						
						
									
										52
									
								
								vm/run.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -3,19 +3,6 @@
 | 
			
		|||
namespace factor
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_getenv()
 | 
			
		||||
{
 | 
			
		||||
	fixnum e = untag_fixnum(dpeek());
 | 
			
		||||
	drepl(special_objects[e]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_setenv()
 | 
			
		||||
{
 | 
			
		||||
	fixnum e = untag_fixnum(dpop());
 | 
			
		||||
	cell value = dpop();
 | 
			
		||||
	special_objects[e] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_exit()
 | 
			
		||||
{
 | 
			
		||||
	exit(to_fixnum(dpop()));
 | 
			
		||||
| 
						 | 
				
			
			@ -31,43 +18,4 @@ void factor_vm::primitive_sleep()
 | 
			
		|||
	sleep_micros(to_cell(dpop()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_set_slot()
 | 
			
		||||
{
 | 
			
		||||
	fixnum slot = untag_fixnum(dpop());
 | 
			
		||||
	object *obj = untag<object>(dpop());
 | 
			
		||||
	cell value = dpop();
 | 
			
		||||
 | 
			
		||||
	cell *slot_ptr = &obj->slots()[slot];
 | 
			
		||||
	*slot_ptr = value;
 | 
			
		||||
	write_barrier(slot_ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_load_locals()
 | 
			
		||||
{
 | 
			
		||||
	fixnum count = untag_fixnum(dpop());
 | 
			
		||||
	memcpy((cell *)(rs + sizeof(cell)),(cell *)(ds - sizeof(cell) * (count - 1)),sizeof(cell) * count);
 | 
			
		||||
	ds -= sizeof(cell) * count;
 | 
			
		||||
	rs += sizeof(cell) * count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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());
 | 
			
		||||
		object *new_obj = allot_object(header(obj.type()),size);
 | 
			
		||||
		memcpy(new_obj,obj.untagged(),size);
 | 
			
		||||
		return tag_dynamic(new_obj);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::primitive_clone()
 | 
			
		||||
{
 | 
			
		||||
	drepl(clone_object(dpeek()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										99
									
								
								vm/run.hpp
								
								
								
								
							
							
						
						
									
										99
									
								
								vm/run.hpp
								
								
								
								
							| 
						 | 
				
			
			@ -1,103 +1,4 @@
 | 
			
		|||
namespace factor
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
static const cell special_object_count = 70;
 | 
			
		||||
 | 
			
		||||
enum special_object {
 | 
			
		||||
	OBJ_NAMESTACK,            /* used by library only */
 | 
			
		||||
	OBJ_CATCHSTACK,           /* used by library only, per-callback */
 | 
			
		||||
 | 
			
		||||
	OBJ_CURRENT_CALLBACK = 2, /* used by library only, per-callback */
 | 
			
		||||
	OBJ_WALKER_HOOK,          /* non-local exit hook, used by library only */
 | 
			
		||||
	OBJ_CALLCC_1,             /* used to pass the value in callcc1 */
 | 
			
		||||
 | 
			
		||||
	OBJ_BREAK            = 5, /* quotation called by throw primitive */
 | 
			
		||||
	OBJ_ERROR,                /* a marker consed onto kernel errors */
 | 
			
		||||
 | 
			
		||||
	OBJ_CELL_SIZE        = 7, /* sizeof(cell) */
 | 
			
		||||
	OBJ_CPU,                  /* CPU architecture */
 | 
			
		||||
	OBJ_OS,                   /* operating system name */
 | 
			
		||||
 | 
			
		||||
	OBJ_ARGS            = 10, /* command line arguments */
 | 
			
		||||
	OBJ_STDIN,                /* stdin FILE* handle */
 | 
			
		||||
	OBJ_STDOUT,               /* stdout FILE* handle */
 | 
			
		||||
 | 
			
		||||
	OBJ_IMAGE           = 13, /* image path name */
 | 
			
		||||
	OBJ_EXECUTABLE,		  /* runtime executable path name */
 | 
			
		||||
 | 
			
		||||
	OBJ_EMBEDDED 	    = 15, /* are we embedded in another app? */
 | 
			
		||||
	OBJ_EVAL_CALLBACK,        /* used when Factor is embedded in a C app */
 | 
			
		||||
	OBJ_YIELD_CALLBACK,       /* used when Factor is embedded in a C app */
 | 
			
		||||
	OBJ_SLEEP_CALLBACK,       /* used when Factor is embedded in a C app */
 | 
			
		||||
 | 
			
		||||
	OBJ_COCOA_EXCEPTION = 19, /* Cocoa exception handler quotation */
 | 
			
		||||
 | 
			
		||||
	OBJ_BOOT            = 20, /* boot quotation */
 | 
			
		||||
	OBJ_GLOBAL,               /* global namespace */
 | 
			
		||||
 | 
			
		||||
	/* Quotation compilation in quotations.c */
 | 
			
		||||
	JIT_PROLOG          = 23,
 | 
			
		||||
	JIT_PRIMITIVE_WORD,
 | 
			
		||||
	JIT_PRIMITIVE,
 | 
			
		||||
	JIT_WORD_JUMP,
 | 
			
		||||
	JIT_WORD_CALL,
 | 
			
		||||
	JIT_WORD_SPECIAL,
 | 
			
		||||
	JIT_IF_WORD,
 | 
			
		||||
	JIT_IF,
 | 
			
		||||
	JIT_EPILOG,
 | 
			
		||||
	JIT_RETURN,
 | 
			
		||||
	JIT_PROFILING,
 | 
			
		||||
	JIT_PUSH_IMMEDIATE,
 | 
			
		||||
	JIT_DIP_WORD,
 | 
			
		||||
	JIT_DIP,
 | 
			
		||||
	JIT_2DIP_WORD,
 | 
			
		||||
	JIT_2DIP,
 | 
			
		||||
	JIT_3DIP_WORD,
 | 
			
		||||
	JIT_3DIP,
 | 
			
		||||
	JIT_EXECUTE_WORD,
 | 
			
		||||
	JIT_EXECUTE_JUMP,
 | 
			
		||||
	JIT_EXECUTE_CALL,
 | 
			
		||||
	JIT_DECLARE_WORD,
 | 
			
		||||
 | 
			
		||||
	/* Callback stub generation in callbacks.c */
 | 
			
		||||
	CALLBACK_STUB       = 45,
 | 
			
		||||
 | 
			
		||||
	/* Polymorphic inline cache generation in inline_cache.c */
 | 
			
		||||
	PIC_LOAD            = 47,
 | 
			
		||||
	PIC_TAG,
 | 
			
		||||
	PIC_TUPLE,
 | 
			
		||||
	PIC_CHECK_TAG,
 | 
			
		||||
	PIC_CHECK_TUPLE,
 | 
			
		||||
	PIC_HIT,
 | 
			
		||||
	PIC_MISS_WORD,
 | 
			
		||||
	PIC_MISS_TAIL_WORD,
 | 
			
		||||
 | 
			
		||||
	/* Megamorphic cache generation in dispatch.c */
 | 
			
		||||
	MEGA_LOOKUP         = 57,
 | 
			
		||||
	MEGA_LOOKUP_WORD,
 | 
			
		||||
	MEGA_MISS_WORD,
 | 
			
		||||
 | 
			
		||||
	OBJ_UNDEFINED       = 60, /* default quotation for undefined words */
 | 
			
		||||
 | 
			
		||||
	OBJ_STDERR          = 61, /* stderr FILE* handle */
 | 
			
		||||
 | 
			
		||||
	OBJ_STAGE2          = 62, /* have we bootstrapped? */
 | 
			
		||||
 | 
			
		||||
	OBJ_CURRENT_THREAD  = 63,
 | 
			
		||||
 | 
			
		||||
	OBJ_THREADS         = 64,
 | 
			
		||||
	OBJ_RUN_QUEUE       = 65,
 | 
			
		||||
	OBJ_SLEEP_QUEUE     = 66,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define OBJ_FIRST_SAVE OBJ_BOOT
 | 
			
		||||
#define OBJ_LAST_SAVE OBJ_STAGE2
 | 
			
		||||
 | 
			
		||||
inline static bool save_env_p(cell i)
 | 
			
		||||
{
 | 
			
		||||
	return (i >= OBJ_FIRST_SAVE && i <= OBJ_LAST_SAVE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								vm/vm.hpp
								
								
								
								
							
							
						
						
									
										42
									
								
								vm/vm.hpp
								
								
								
								
							| 
						 | 
				
			
			@ -102,6 +102,7 @@ struct factor_vm
 | 
			
		|||
	void primitive_set_datastack();
 | 
			
		||||
	void primitive_set_retainstack();
 | 
			
		||||
	void primitive_check_datastack();
 | 
			
		||||
	void primitive_load_locals();
 | 
			
		||||
 | 
			
		||||
	template<typename Iterator> void iterate_active_frames(Iterator &iter)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -116,15 +117,18 @@ struct factor_vm
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// run
 | 
			
		||||
	void primitive_getenv();
 | 
			
		||||
	void primitive_setenv();
 | 
			
		||||
	void primitive_exit();
 | 
			
		||||
	void primitive_micros();
 | 
			
		||||
	void primitive_sleep();
 | 
			
		||||
	void primitive_set_slot();
 | 
			
		||||
	void primitive_load_locals();
 | 
			
		||||
 | 
			
		||||
	// objects
 | 
			
		||||
	void primitive_special_object();
 | 
			
		||||
	void primitive_set_special_object();
 | 
			
		||||
	cell object_size(cell tagged);
 | 
			
		||||
	cell clone_object(cell obj_);
 | 
			
		||||
	void primitive_clone();
 | 
			
		||||
	void primitive_become();
 | 
			
		||||
 | 
			
		||||
	// profiler
 | 
			
		||||
	void init_profiler();
 | 
			
		||||
| 
						 | 
				
			
			@ -225,15 +229,27 @@ struct factor_vm
 | 
			
		|||
	void primitive_next_object();
 | 
			
		||||
	void primitive_end_scan();
 | 
			
		||||
	cell find_all_words();
 | 
			
		||||
	cell object_size(cell tagged);
 | 
			
		||||
 | 
			
		||||
	template<typename Generation, typename Iterator>
 | 
			
		||||
	inline void each_object(Generation *gen, Iterator &iterator)
 | 
			
		||||
	{
 | 
			
		||||
		cell obj = gen->first_object();
 | 
			
		||||
		while(obj)
 | 
			
		||||
		{
 | 
			
		||||
			iterator(obj);
 | 
			
		||||
			obj = gen->next_object_after(obj);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Iterator> inline void each_object(Iterator &iterator)
 | 
			
		||||
	{
 | 
			
		||||
		begin_scan();
 | 
			
		||||
		cell obj;
 | 
			
		||||
		while(to_boolean(obj = next_object()))
 | 
			
		||||
			iterator(obj);
 | 
			
		||||
		end_scan();
 | 
			
		||||
		gc_off = true;
 | 
			
		||||
 | 
			
		||||
		each_object(data->tenured,iterator);
 | 
			
		||||
		each_object(data->aging,iterator);
 | 
			
		||||
		each_object(data->nursery,iterator);
 | 
			
		||||
 | 
			
		||||
		gc_off = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* the write barrier must be called any time we are potentially storing a
 | 
			
		||||
| 
						 | 
				
			
			@ -244,6 +260,13 @@ struct factor_vm
 | 
			
		|||
		*(char *)(decks_offset + ((cell)slot_ptr >> deck_bits)) = card_mark_mask;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void write_barrier(object *obj, cell size)
 | 
			
		||||
	{
 | 
			
		||||
		char *start = (char *)obj;
 | 
			
		||||
		for(cell offset = 0; offset < size; offset += card_size)
 | 
			
		||||
			write_barrier((cell *)(start + offset));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// gc
 | 
			
		||||
	void end_gc();
 | 
			
		||||
	void start_gc_again();
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +287,6 @@ struct factor_vm
 | 
			
		|||
	void primitive_minor_gc();
 | 
			
		||||
	void primitive_full_gc();
 | 
			
		||||
	void primitive_compact_gc();
 | 
			
		||||
	void primitive_become();
 | 
			
		||||
	void inline_gc(cell *data_roots_base, cell data_roots_size);
 | 
			
		||||
	void primitive_enable_gc_events();
 | 
			
		||||
	void primitive_disable_gc_events();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue