vm/math.o \
vm/nursery_collector.o \
vm/object_start_map.o \
+ vm/objects.o \
vm/primitives.o \
vm/profiler.o \
vm/quotations.o \
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;
- }
};
}
{
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;
+ }
};
}
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
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);
}
}
+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;
+}
+
}
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_;
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
{
}
}
-void factor_vm::primitive_size()
-{
- box_unsigned_cell(object_size(dpop()));
-}
-
data_heap_room factor_vm::data_room()
{
data_heap_room room;
void reset_generation(aging_space *gen);
void reset_generation(tenured_space *gen);
bool low_memory_p();
+ void mark_all_cards();
};
struct data_heap_room {
fflush(stdout);
compile_all_words();
+ update_code_heap_words();
special_objects[OBJ_STAGE2] = true_object;
std::cout << "done\n";
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)
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++)
/* 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;
#include "segments.hpp"
#include "contexts.hpp"
#include "run.hpp"
+#include "objects.hpp"
#include "profiler.hpp"
#include "errors.hpp"
#include "bignumint.hpp"
--- /dev/null
+#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();
+}
+
+}
--- /dev/null
+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);
+}
+
+}
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)
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,
update_word_xt(word.untagged());
}
-
- update_code_heap_words();
}
/* Allocates memory */
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()));
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()));
-}
-
}
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);
}
-
-}
-
-
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)
{
}
// 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();
void primitive_next_object();
void primitive_end_scan();
cell find_all_words();
- cell object_size(cell tagged);
- template<typename Iterator> inline void each_object(Iterator &iterator)
+ template<typename Generation, typename Iterator>
+ inline void each_object(Generation *gen, Iterator &iterator)
{
- begin_scan();
- cell obj;
- while(to_boolean(obj = next_object()))
+ cell obj = gen->first_object();
+ while(obj)
+ {
iterator(obj);
- end_scan();
+ obj = gen->next_object_after(obj);
+ }
+ }
+
+ template<typename Iterator> inline void each_object(Iterator &iterator)
+ {
+ 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
*(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();
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();