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