<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>vm/objects.cpp</filename>
    </added>
    <added>
      <filename>vm/objects.hpp</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -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 \</diff>
      <filename>Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -15,15 +15,6 @@ struct aging_space : bump_allocator&lt;object&gt; {
 		starts.record_object_start_offset(obj);
 		return obj;
 	}
-
-	cell next_object_after(cell scan)
-	{
-		cell size = ((object *)scan)-&gt;size();
-		if(scan + size &lt; here)
-			return scan + size;
-		else
-			return 0;
-	}
 };
 
 }</diff>
      <filename>vm/aging_space.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -32,6 +32,23 @@ template&lt;typename Block&gt; struct bump_allocator {
 	{
 		return end - here;
 	}
+
+	cell next_object_after(cell scan)
+	{
+		cell size = ((Block *)scan)-&gt;size();
+		if(scan + size &lt; here)
+			return scan + size;
+		else
+			return 0;
+	}
+
+	cell first_object()
+	{
+		if(start != here)
+			return start;
+		else
+			return 0;
+	}
 };
 
 }</diff>
      <filename>vm/bump_allocator.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -118,10 +118,8 @@ struct word_and_literal_code_heap_updater {
 
 void factor_vm::update_code_heap_words_and_literals()
 {
-	current_gc-&gt;event-&gt;started_code_sweep();
 	word_and_literal_code_heap_updater updater(this);
-	code-&gt;allocator-&gt;sweep(updater);
-	current_gc-&gt;event-&gt;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 &lt; count; i++)
+	for(cell i = 0; i &lt; count; i++)
 	{
 		data_root&lt;array&gt; pair(array_nth(alist.untagged(),i),this);
 </diff>
      <filename>vm/code_heap.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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;
+}
+
 }</diff>
      <filename>vm/contexts.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -103,6 +103,12 @@ bool data_heap::low_memory_p()
 	return (tenured-&gt;free_space() &lt;= nursery-&gt;size + aging-&gt;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&lt;object&gt;(tagged)-&gt;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;</diff>
      <filename>vm/data_heap.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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 {</diff>
      <filename>vm/data_heap.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -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 &lt;&lt; &quot;done\n&quot;;</diff>
      <filename>vm/factor.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -116,6 +116,10 @@ void factor_vm::collect_sweep_impl()
 	data-&gt;tenured-&gt;sweep();
 	update_code_roots_for_sweep();
 	current_gc-&gt;event-&gt;ended_data_sweep();
+
+	current_gc-&gt;event-&gt;started_code_sweep();
+	code-&gt;allocator-&gt;sweep();
+	current_gc-&gt;event-&gt;ended_code_sweep();
 }
 
 void factor_vm::collect_full(bool trace_contexts_p)</diff>
      <filename>vm/full_collector.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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&lt;array&gt;(dpop());
-	array *old_objects = untag_check&lt;array&gt;(dpop());
-
-	cell capacity = array_capacity(new_objects);
-	if(capacity != array_capacity(old_objects))
-		critical_error(&quot;bad parameters to become&quot;,0);
-
-	cell i;
-
-	for(i = 0; i &lt; capacity; i++)
-	{
-		tagged&lt;object&gt; old_obj(array_nth(old_objects,i));
-		tagged&lt;object&gt; new_obj(array_nth(new_objects,i));
-
-		if(old_obj != new_obj)
-			old_obj-&gt;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 &lt; data_roots_size; i++)
@@ -290,9 +259,7 @@ object *factor_vm::allot_large_object(header header, cell size)
 	/* Allows initialization code to store old-&gt;new pointers
 	without hitting the write barrier in the common case of
 	a nursery allocation */
-	char *start = (char *)obj;
-	for(cell offset = 0; offset &lt; size; offset += card_size)
-		write_barrier((cell *)(start + offset));
+	write_barrier(obj,size);
 
 	obj-&gt;h = header;
 	return obj;</diff>
      <filename>vm/gc.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -44,6 +44,7 @@ namespace factor
 #include &quot;segments.hpp&quot;
 #include &quot;contexts.hpp&quot;
 #include &quot;run.hpp&quot;
+#include &quot;objects.hpp&quot;
 #include &quot;profiler.hpp&quot;
 #include &quot;errors.hpp&quot;
 #include &quot;bignumint.hpp&quot;</diff>
      <filename>vm/master.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -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,</diff>
      <filename>vm/primitives.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -341,8 +341,6 @@ void factor_vm::compile_all_words()
 		update_word_xt(word.untagged());
 
 	}
-
-	update_code_heap_words();
 }
 
 /* Allocates memory */</diff>
      <filename>vm/quotations.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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&lt;object&gt;(dpop());
-	cell value = dpop();
-
-	cell *slot_ptr = &amp;obj-&gt;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&lt;object&gt; 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()));
-}
-
 }</diff>
      <filename>vm/run.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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 &gt;= OBJ_FIRST_SAVE &amp;&amp; i &lt;= OBJ_LAST_SAVE);
 }
-
-}
-
- </diff>
      <filename>vm/run.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -102,6 +102,7 @@ struct factor_vm
 	void primitive_set_datastack();
 	void primitive_set_retainstack();
 	void primitive_check_datastack();
+	void primitive_load_locals();
 
 	template&lt;typename Iterator&gt; void iterate_active_frames(Iterator &amp;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&lt;typename Iterator&gt; inline void each_object(Iterator &amp;iterator)
+	template&lt;typename Generation, typename Iterator&gt;
+	inline void each_object(Generation *gen, Iterator &amp;iterator)
 	{
-		begin_scan();
-		cell obj;
-		while(to_boolean(obj = next_object()))
+		cell obj = gen-&gt;first_object();
+		while(obj)
+		{
 			iterator(obj);
-		end_scan();
+			obj = gen-&gt;next_object_after(obj);
+		}
+	}
+
+	template&lt;typename Iterator&gt; inline void each_object(Iterator &amp;iterator)
+	{
+		gc_off = true;
+
+		each_object(data-&gt;tenured,iterator);
+		each_object(data-&gt;aging,iterator);
+		each_object(data-&gt;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 &gt;&gt; deck_bits)) = card_mark_mask;
 	}
 
+	inline void write_barrier(object *obj, cell size)
+	{
+		char *start = (char *)obj;
+		for(cell offset = 0; offset &lt; 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();</diff>
      <filename>vm/vm.hpp</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e70f20f5e3eb4dc4c9a5554525f53b42dbf0bc2e</id>
    </parent>
  </parents>
  <author>
    <name>Slava Pestov</name>
    <email>slava@slava-pestovs-macbook-pro.local</email>
  </author>
  <url>http://github.com/slavapestov/factor/commit/9ae5faa14e420a04e8c22bd0ddb403010f557639</url>
  <id>9ae5faa14e420a04e8c22bd0ddb403010f557639</id>
  <committed-date>2009-11-05T17:03:51-08:00</committed-date>
  <authored-date>2009-11-05T17:03:51-08:00</authored-date>
  <message>vm: rewrite 'become' primitive so that it uses a slot visitor instead of GC</message>
  <tree>29df6ac27f190e0b0356da05d1f53250d961fc2e</tree>
  <committer>
    <name>Slava Pestov</name>
    <email>slava@slava-pestovs-macbook-pro.local</email>
  </committer>
</commit>
