increased the object's proc bits to 2 - MOO_OBJ_FLAGS_PROC_BITS.

added BlockContext>>newSystemProcess for internal use
This commit is contained in:
hyunghwan.chung 2019-11-04 14:53:33 +00:00
parent 546c766a39
commit ed9bd1918d
7 changed files with 83 additions and 27 deletions

View File

@ -121,6 +121,7 @@ class(#pointer,#final,#limited) BlockContext(Context)
// create a new process in the suspended state // create a new process in the suspended state
method(#variadic,#primitive) newProcess(). method(#variadic,#primitive) newProcess().
method(#variadic,#primitive) newSystemProcess(). // this method is for internal use only. never call this.
// evaluate the block // evaluate the block
method(#variadic,#primitive) value(). method(#variadic,#primitive) value().

View File

@ -13,8 +13,7 @@ class System(Apex)
var(#class) asyncsg. var(#class) asyncsg.
var(#class) gcfin_sem. var(#class) gcfin_sem.
var(#class) gcfin_should_exit := false. var(#class) gcfin_should_exit := false.
var(#class) gcfin_proc. var(#class) ossig_pid.
var(#class) ossig_proc.
var(#class) shr. // signal handler registry var(#class) shr. // signal handler registry
pooldic Log pooldic Log
@ -64,7 +63,7 @@ class System(Apex)
method(#class) startup(class_name, method_name) method(#class) startup(class_name, method_name)
{ {
| class ret | | class ret gcfin_proc ossig_proc |
System gc. System gc.
@ -79,11 +78,13 @@ class System(Apex)
// start the gc finalizer process and os signal handler process // start the gc finalizer process and os signal handler process
//[ self __gc_finalizer ] fork. //[ self __gc_finalizer ] fork.
//[ self __os_sig_handler ] fork. //[ self __os_sig_handler ] fork.
self.gcfin_proc := [ self __gc_finalizer ] newProcess. gcfin_proc := [ self __gc_finalizer ] newSystemProcess.
self.ossig_proc := [ :caller | self __os_sig_handler: caller ] newProcess(thisProcess). ossig_proc := [ :caller | self __os_sig_handler: caller ] newSystemProcess(thisProcess).
self.gcfin_proc resume. self.ossig_pid := ossig_proc id.
self.ossig_proc resume.
gcfin_proc resume.
ossig_proc resume.
[ [
// TODO: change the method signature to variadic and pass extra arguments to perform??? // TODO: change the method signature to variadic and pass extra arguments to perform???
@ -147,7 +148,6 @@ class System(Apex)
self.gcfin_sem signal. // in case the process is stuck in wait. self.gcfin_sem signal. // in case the process is stuck in wait.
self.gcfin_sem unsignal. self.gcfin_sem unsignal.
System logNl: 'End of GC finalization process ' & (thisProcess id) asString. System logNl: 'End of GC finalization process ' & (thisProcess id) asString.
self.gcfin_proc := nil.
]. ].
} }
@ -207,7 +207,8 @@ class System(Apex)
3 .. -> other processes started by application. 3 .. -> other processes started by application.
*/ */
/* TODO: this loop is error-prone as it can't handle when the processs id wraps back and the id of gcfin_proc and ossig_proc gets bigger than normal child processes */ /* TODO: this loop is error-prone as it can't handle when the processs id wraps back and the id of gcfin_proc and ossig_proc gets bigger than normal child processes */
proc := System _findProcessByIdGreaterThan: (self.ossig_proc id). //proc := System _findProcessByIdGreaterThan: self.ossig_pid.
proc := System _findProcessByIdGreaterThan: -1.
while (proc notError) while (proc notError)
{ {
pid := proc id. pid := proc id.
@ -225,7 +226,6 @@ class System(Apex)
self.gcfin_should_exit := true. self.gcfin_should_exit := true.
self.gcfin_sem signal. // wake the gcfin process. self.gcfin_sem signal. // wake the gcfin process.
self.ossig_proc := nil.
self _halting. // inform VM that it should get ready for halting. self _halting. // inform VM that it should get ready for halting.
]. ].
} }

View File

@ -282,6 +282,7 @@ static MOO_INLINE void alloc_pid (moo_t* moo, moo_oop_process_t proc)
moo->proc_map_free_first = MOO_OOP_TO_SMOOI(moo->proc_map[pid]); moo->proc_map_free_first = MOO_OOP_TO_SMOOI(moo->proc_map[pid]);
if (moo->proc_map_free_first <= -1) moo->proc_map_free_last = -1; if (moo->proc_map_free_first <= -1) moo->proc_map_free_last = -1;
moo->proc_map[pid] = (moo_oop_t)proc; moo->proc_map[pid] = (moo_oop_t)proc;
moo->proc_map_used++;
} }
static MOO_INLINE void free_pid (moo_t* moo, moo_oop_process_t proc) static MOO_INLINE void free_pid (moo_t* moo, moo_oop_process_t proc)
@ -290,7 +291,9 @@ static MOO_INLINE void free_pid (moo_t* moo, moo_oop_process_t proc)
pid = MOO_OOP_TO_SMOOI(proc->id); pid = MOO_OOP_TO_SMOOI(proc->id);
MOO_ASSERT (moo, pid < moo->proc_map_capa); MOO_ASSERT (moo, pid < moo->proc_map_capa);
MOO_ASSERT (moo, moo->proc_map_used > 0);
/* chain the freed slot at the end of the free list */
moo->proc_map[pid] = MOO_SMOOI_TO_OOP(-1); moo->proc_map[pid] = MOO_SMOOI_TO_OOP(-1);
if (moo->proc_map_free_last <= -1) if (moo->proc_map_free_last <= -1)
{ {
@ -302,9 +305,10 @@ static MOO_INLINE void free_pid (moo_t* moo, moo_oop_process_t proc)
moo->proc_map[moo->proc_map_free_last] = MOO_SMOOI_TO_OOP(pid); moo->proc_map[moo->proc_map_free_last] = MOO_SMOOI_TO_OOP(pid);
} }
moo->proc_map_free_last = pid; moo->proc_map_free_last = pid;
moo->proc_map_used--;
} }
static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c) static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c, int proc_flags)
{ {
moo_oop_process_t proc; moo_oop_process_t proc;
moo_ooi_t total_count; moo_ooi_t total_count;
@ -327,7 +331,7 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c)
moo_popvolat (moo); moo_popvolat (moo);
if (!proc) return MOO_NULL; if (!proc) return MOO_NULL;
MOO_OBJ_SET_FLAGS_PROC (proc, 1); /* a special flag to indicate an object is a process instance */ MOO_OBJ_SET_FLAGS_PROC (proc, proc_flags); /* a special flag to indicate an object is a process instance */
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED);
/* assign a process id to the process */ /* assign a process id to the process */
@ -1624,7 +1628,7 @@ static moo_oop_process_t start_initial_process (moo_t* moo, moo_oop_context_t c)
MOO_ASSERT (moo, moo->processor->runnable.count == MOO_SMOOI_TO_OOP(0)); MOO_ASSERT (moo, moo->processor->runnable.count == MOO_SMOOI_TO_OOP(0));
MOO_ASSERT (moo, moo->processor->active == moo->nil_process); MOO_ASSERT (moo, moo->processor->active == moo->nil_process);
proc = make_process(moo, c); proc = make_process(moo, c, 2);
if (!proc) return MOO_NULL; if (!proc) return MOO_NULL;
chain_into_processor (moo, proc, PROC_STATE_RUNNING); chain_into_processor (moo, proc, PROC_STATE_RUNNING);
@ -2256,6 +2260,11 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
case MOO_OBJ_FLAGS_HASH_STORED: case MOO_OBJ_FLAGS_HASH_STORED:
hv = *(moo_oow_t*)((moo_uint8_t*)rcv + MOO_SIZEOF(moo_obj_t) + moo_getobjpayloadbytes(moo, rcv) - MOO_SIZEOF(moo_oow_t)); hv = *(moo_oow_t*)((moo_uint8_t*)rcv + MOO_SIZEOF(moo_obj_t) + moo_getobjpayloadbytes(moo, rcv) - MOO_SIZEOF(moo_oow_t));
break; break;
default:
/* this must not happend. internal error */
moo_seterrbfmt (moo, MOO_EINTERN, "internal error - unknown hash flags %d in %O", (int)MOO_OBJ_GET_FLAGS_HASH(rcv), rcv);
return MOO_PF_HARD_FAILURE;
} }
} }
} }
@ -2642,7 +2651,7 @@ static moo_pfrc_t pf_block_value (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) static MOO_INLINE moo_pfrc_t __block_new_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs, int proc_flags)
{ {
/* create a new process from a block context. /* create a new process from a block context.
* the receiver must be be a block. * the receiver must be be a block.
@ -2693,7 +2702,7 @@ static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t na
* context of a process. */ * context of a process. */
blkctx->sender = (moo_oop_context_t)moo->_nil; blkctx->sender = (moo_oop_context_t)moo->_nil;
proc = make_process(moo, blkctx); proc = make_process(moo, blkctx, proc_flags);
if (!proc) return MOO_PF_FAILURE; /* hard failure */ /* TOOD: can't this be treated as a soft failure? throw an exception instead?? */ if (!proc) return MOO_PF_FAILURE; /* hard failure */ /* TOOD: can't this be treated as a soft failure? throw an exception instead?? */
/* __block_value() has popped all arguments and the receiver. /* __block_value() has popped all arguments and the receiver.
@ -2702,6 +2711,16 @@ static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t na
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
{
return __block_new_process(moo, mod, nargs, 1);
}
static moo_pfrc_t pf_block_new_system_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
{
return __block_new_process(moo, mod, nargs, 2);
}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static moo_pfrc_t pf_process_sp (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) static moo_pfrc_t pf_process_sp (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
@ -3296,10 +3315,9 @@ static moo_pfrc_t pf_system_halting (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs
static moo_pfrc_t pf_system_find_process_by_id (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) static moo_pfrc_t pf_system_find_process_by_id (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
{ {
moo_oop_t rcv, id; moo_oop_t /*rcv,*/ id;
moo_oop_process_t proc;
rcv = MOO_STACK_GETRCV(moo, nargs); /*rcv = MOO_STACK_GETRCV(moo, nargs);*/
id = MOO_STACK_GETARG(moo, nargs, 0); id = MOO_STACK_GETARG(moo, nargs, 0);
/*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/
@ -3326,10 +3344,9 @@ static moo_pfrc_t pf_system_find_process_by_id (moo_t* moo, moo_mod_t* mod, moo_
static moo_pfrc_t pf_system_find_process_by_id_gt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) static moo_pfrc_t pf_system_find_process_by_id_gt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
{ {
moo_oop_t rcv, id; moo_oop_t /*rcv,*/ id;
moo_oop_process_t proc;
rcv = MOO_STACK_GETRCV(moo, nargs); /*rcv = MOO_STACK_GETRCV(moo, nargs);*/
id = MOO_STACK_GETARG(moo, nargs, 0); id = MOO_STACK_GETARG(moo, nargs, 0);
/*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/
@ -3337,14 +3354,19 @@ static moo_pfrc_t pf_system_find_process_by_id_gt (moo_t* moo, moo_mod_t* mod, m
if (MOO_OOP_IS_SMOOI(id)) if (MOO_OOP_IS_SMOOI(id))
{ {
moo_ooi_t index = MOO_OOP_TO_SMOOI(id); moo_ooi_t index = MOO_OOP_TO_SMOOI(id);
if (index >= 0) if (index >= -1) /* allow -1 to be able to return pid 0. */
{ {
/* TOOD: enhance alloc_pid() and free_pid() to maintain the hightest pid number so that this loop can stop before reaching proc_map_capa */ /* TOOD: enhance alloc_pid() and free_pid() to maintain the hightest pid number so that this loop can stop before reaching proc_map_capa */
for (++index; index < moo->proc_map_capa; index++) for (++index; index < moo->proc_map_capa; index++)
{ {
if (MOO_CLASSOF(moo, moo->proc_map[index]) == moo->_process) /* note the free slot contains a small integer which indicate the next slot index in proc_map.
* if the slot it taken, it should point to a process object. read the comment at end of this loop. */
moo_oop_t tmp;
tmp = moo->proc_map[index];
if (MOO_CLASSOF(moo, tmp) == moo->_process && MOO_OBJ_GET_FLAGS_PROC(tmp) == 1) /* normal process only. skip a system process */
{ {
MOO_STACK_SETRET (moo, nargs, moo->proc_map[index]); MOO_STACK_SETRET (moo, nargs, tmp);
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
@ -4378,6 +4400,7 @@ static pf_t pftab[] =
{ "Apex_~~", { moo_pf_not_identical, 1, 1 } }, { "Apex_~~", { moo_pf_not_identical, 1, 1 } },
{ "BlockContext_newProcess", { pf_block_new_process, 0, MA } }, { "BlockContext_newProcess", { pf_block_new_process, 0, MA } },
{ "BlockContext_newSystemProcess", { pf_block_new_system_process, 0, MA } },
{ "BlockContext_value", { pf_block_value, 0, MA } }, { "BlockContext_value", { pf_block_value, 0, MA } },
{ "Character_<", { pf_character_lt, 1, 1 } }, { "Character_<", { pf_character_lt, 1, 1 } },
@ -6472,6 +6495,7 @@ int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname
MOO_ASSERT (moo, moo->active_context == MOO_NULL); MOO_ASSERT (moo, moo->active_context == MOO_NULL);
MOO_ASSERT (moo, moo->active_method == MOO_NULL); MOO_ASSERT (moo, moo->active_method == MOO_NULL);
#if defined(MOO_PROFILE_VM) #if defined(MOO_PROFILE_VM)
moo->stat.inst_counter = 0; moo->stat.inst_counter = 0;
moo->stat.method_cache_hits = 0; moo->stat.method_cache_hits = 0;
@ -6481,6 +6505,31 @@ int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname
moo_clearmethodcache (moo); moo_clearmethodcache (moo);
#if 0
/* unless the system is buggy, moo->proc_map_used should be 0.
* the standard library terminates all processes before halting.
*
* [EXPERIMENTAL]
* if you like the process allocation to start from 0, uncomment
* the following 'if' block */
if (moo->proc_map_capa > 0 && moo->proc_map_used == 0)
{
/* rechain the process map. it must be compatible with prepare_to_alloc_pid().
* by placing the low indiced slot at the beginning of the free list,
* the special processes (main_proc, gcfin_proc, ossig_proc) are allocated
* with low process IDs. */
moo_ooi_t i, j;
moo->proc_map_free_first = 0;
for (i = 0, j = 1; j < moo->proc_map_capa; i++, j++)
{
moo->proc_map[i] = MOO_SMOOI_TO_OOP(j);
}
moo->proc_map[i] = MOO_SMOOI_TO_OOP(-1);
moo->proc_map_free_last = i;
}
#endif
if (start_initial_process_and_context(moo, objname, mthname) <= -1) return -1; if (start_initial_process_and_context(moo, objname, mthname) <= -1) return -1;
moo->initial_context = moo->processor->active->initial_context; moo->initial_context = moo->processor->active->initial_context;
@ -6491,6 +6540,7 @@ int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname
moo->active_context = MOO_NULL; moo->active_context = MOO_NULL;
moo->active_method = MOO_NULL; moo->active_method = MOO_NULL;
#if defined(MOO_PROFILE_VM) #if defined(MOO_PROFILE_VM)
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_INFO, "Total message sends: %zu\n", moo->stat.message_sends); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_INFO, "Total message sends: %zu\n", moo->stat.message_sends);
MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_INFO, "Method cache - hits: %zu, misses: %zu\n", moo->stat.method_cache_hits, moo->stat.method_cache_misses); MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_INFO, "Method cache - hits: %zu, misses: %zu\n", moo->stat.method_cache_hits, moo->stat.method_cache_misses);

View File

@ -405,7 +405,7 @@ static kernel_class_info_t kernel_classes[] =
{ 6, { 6,
{ 'S','y','s','t','e','m' }, { 'S','y','s','t','e','m' },
0, 0,
6, /* asyncsg, gcfin_sem, gcfin_should_exit, gcfin_proc, ossig_proc, shr */ 5, /* asyncsg, gcfin_sem, gcfin_should_exit, ossig_pid, shr */
0, 0,
0, 0,
MOO_OBJ_TYPE_OOP, MOO_OBJ_TYPE_OOP,

View File

@ -239,6 +239,7 @@ void moo_fini (moo_t* moo)
{ {
moo_freemem (moo, moo->proc_map); moo_freemem (moo, moo->proc_map);
moo->proc_map_capa = 0; moo->proc_map_capa = 0;
moo->proc_map_used = 0;
moo->proc_map_free_first = -1; moo->proc_map_free_first = -1;
moo->proc_map_free_last = -1; moo->proc_map_free_last = -1;
} }

View File

@ -290,7 +290,7 @@ typedef enum moo_gcfin_t moo_gcfin_t;
#define MOO_OBJ_FLAGS_KERNEL_BITS 2 #define MOO_OBJ_FLAGS_KERNEL_BITS 2
#define MOO_OBJ_FLAGS_PERM_BITS 1 #define MOO_OBJ_FLAGS_PERM_BITS 1
#define MOO_OBJ_FLAGS_MOVED_BITS 1 #define MOO_OBJ_FLAGS_MOVED_BITS 1
#define MOO_OBJ_FLAGS_PROC_BITS 1 #define MOO_OBJ_FLAGS_PROC_BITS 2
#define MOO_OBJ_FLAGS_RDONLY_BITS 1 #define MOO_OBJ_FLAGS_RDONLY_BITS 1
#define MOO_OBJ_FLAGS_GCFIN_BITS 4 #define MOO_OBJ_FLAGS_GCFIN_BITS 4
#define MOO_OBJ_FLAGS_TRAILER_BITS 1 #define MOO_OBJ_FLAGS_TRAILER_BITS 1
@ -1674,6 +1674,7 @@ struct moo_t
moo_oop_t* proc_map; moo_oop_t* proc_map;
moo_oow_t proc_map_capa; moo_oow_t proc_map_capa;
moo_oow_t proc_map_used;
moo_ooi_t proc_map_free_first; moo_ooi_t proc_map_free_first;
moo_ooi_t proc_map_free_last; moo_ooi_t proc_map_free_last;

View File

@ -11,12 +11,15 @@ emcc -Wall -O2 -g \
-DMOO_HAVE_CFG_H \ -DMOO_HAVE_CFG_H \
-I${blddir}/lib \ -I${blddir}/lib \
-I${topdir}/lib\ -I${topdir}/lib\
-s WASM=1 -s LINKABLE=1 \ -s WASM=1 \
-s LINKABLE=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall','cwrap']" \ -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall','cwrap']" \
-o libmoo.js \ -o libmoo.js \
--embed-file ${topdir}/kernel/ \ --embed-file ${topdir}/kernel/ \
--pre-js ${topdir}/wasm/moo.cb.js --pre-js ${topdir}/wasm/moo.cb.js
##-s USE_PTHREADS=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
##cp -pf ${topdir}/wasm/moo.html . ##cp -pf ${topdir}/wasm/moo.html .
##cp -pf ${topdir}/wasm/moo.worker.js . ##cp -pf ${topdir}/wasm/moo.worker.js .
ln -sf ${topdir}/wasm/moo.html moo.html ln -sf ${topdir}/wasm/moo.html moo.html