From 2c8eb874087711823780f488ee2d710b28fee26f Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sat, 11 Feb 2017 05:48:30 +0000 Subject: [PATCH] refactored moo_execute() by taking process switcher out to a separate inline function --- moo/configure | 42 +++++++-- moo/configure.ac | 16 +++- moo/kernel/Mill.moo | 17 ++++ moo/lib/exec.c | 214 +++++++++++++++++++++++-------------------- moo/lib/main.c | 16 +++- moo/lib/moo-cfg.h.in | 3 + moo/lib/moo-cmn.h | 5 +- moo/lib/moo-prv.h | 24 ++--- 8 files changed, 208 insertions(+), 129 deletions(-) diff --git a/moo/configure b/moo/configure index 37e6f08..85d27a1 100755 --- a/moo/configure +++ b/moo/configure @@ -18566,8 +18566,8 @@ esac LIBM=$LIBM -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memset" >&5 -$as_echo_n "checking __builtin_memset... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memset" >&5 +$as_echo_n "checking for __builtin_memset... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18592,8 +18592,8 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memcpy" >&5 -$as_echo_n "checking __builtin_memcpy... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memcpy" >&5 +$as_echo_n "checking for __builtin_memcpy... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18618,8 +18618,8 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memmove" >&5 -$as_echo_n "checking __builtin_memmove... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memmove" >&5 +$as_echo_n "checking for __builtin_memmove... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18644,8 +18644,8 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memcmp" >&5 -$as_echo_n "checking __builtin_memcmp... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memcmp" >&5 +$as_echo_n "checking for __builtin_memcmp... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18670,6 +18670,32 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking computed goto usability" >&5 +$as_echo_n "checking computed goto usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +void *jp = &&jpt; goto *jp; 1; jpt: 2; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_COMPUTED_GOTO 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : diff --git a/moo/configure.ac b/moo/configure.ac index 0101258..e35b1cf 100644 --- a/moo/configure.ac +++ b/moo/configure.ac @@ -108,7 +108,7 @@ LT_LIB_M AC_SUBST(LIBM, $LIBM) dnl check some compiler builtins -AC_MSG_CHECKING([__builtin_memset]) +AC_MSG_CHECKING([for __builtin_memset]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([], [__builtin_memset ((void*)1, ' ', 10);])], [AC_MSG_RESULT(yes) @@ -116,7 +116,7 @@ AC_COMPILE_IFELSE( [AC_MSG_RESULT(no)] ) -AC_MSG_CHECKING([__builtin_memcpy]) +AC_MSG_CHECKING([for __builtin_memcpy]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([], [__builtin_memcpy ((void*)1, (void*)2, 10);])], [AC_MSG_RESULT(yes) @@ -124,7 +124,7 @@ AC_COMPILE_IFELSE( [AC_MSG_RESULT(no)] ) -AC_MSG_CHECKING([__builtin_memmove]) +AC_MSG_CHECKING([for __builtin_memmove]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([], [__builtin_memmove ((void*)1, (void*)2, 10);])], [AC_MSG_RESULT(yes) @@ -132,7 +132,7 @@ AC_COMPILE_IFELSE( [AC_MSG_RESULT(no)] ) -AC_MSG_CHECKING([__builtin_memcmp]) +AC_MSG_CHECKING([for __builtin_memcmp]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([], [int a = __builtin_memcmp ((void*)1, (void*)2, 10);])], [AC_MSG_RESULT(yes) @@ -140,6 +140,14 @@ AC_COMPILE_IFELSE( [AC_MSG_RESULT(no)] ) +AC_MSG_CHECKING([computed goto usability]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( [], [[void *jp = &&jpt; goto *jp; 1; jpt: 2; ]])], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_COMPUTED_GOTO, 1, [computed gotos])], + [AC_MSG_RESULT(no)] +) + dnl check header files. AC_HEADER_STDC AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h]) diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index 37903b8..d561363 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -329,6 +329,23 @@ class MyObject(Object) Processor sleepFor: 20. } + + (* + #method(#class) main + { + | event | + + Timer fire: [ 'Timer job' dump. ] in: 3000. + + GUI on: #XXX do: [:evt | ... ]. + GUI on: #YYYY do: [:evt | ... ]. + + while (true) + { + event := GUI waitForEvent. + GUI dispatchEvent: event. + } + }*) } (* diff --git a/moo/lib/exec.c b/moo/lib/exec.c index dff140e..90143c9 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -2914,6 +2914,106 @@ static int send_private_message (moo_t* moo, const moo_ooch_t* nameptr, moo_oow_ } /* ------------------------------------------------------------------------- */ +static MOO_INLINE int switch_process_if_needed (moo_t* moo) +{ + if (moo->sem_heap_count > 0) + { + moo_ntime_t ft, now; + vm_gettime (moo, &now); + + do + { + MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_sec)); + MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_nsec)); + + MOO_INITNTIME (&ft, + MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_sec), + MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_nsec) + ); + + if (MOO_CMPNTIME(&ft, (moo_ntime_t*)&now) <= 0) + { + moo_oop_process_t proc; + + /* waited long enough. signal the semaphore */ + + proc = signal_semaphore (moo, moo->sem_heap[0]); + /* [NOTE] no moo_pushtmp() on proc. no GC must occur + * in the following line until it's used for + * wake_new_process() below. */ + delete_from_sem_heap (moo, 0); + + /* if no process is waiting on the semaphore, + * signal_semaphore() returns moo->_nil. */ + + if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil) + { + /* this is the only runnable process. + * switch the process to the running state. + * it uses wake_new_process() instead of + * switch_to_process() as there is no running + * process at this moment */ + MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); + MOO_ASSERT (moo, proc == moo->processor->runnable_head); + + wake_new_process (moo, proc); + moo->proc_switched = 1; + } + } + else if (moo->processor->active == moo->nil_process) + { + MOO_SUBNTIME (&ft, &ft, (moo_ntime_t*)&now); + vm_sleep (moo, &ft); /* TODO: change this to i/o multiplexer??? */ + vm_gettime (moo, &now); + } + else + { + break; + } + } + while (moo->sem_heap_count > 0); + } + + if (moo->processor->active == moo->nil_process) + { + /* no more waiting semaphore and no more process */ + MOO_ASSERT (moo, moo->processor->tally = MOO_SMOOI_TO_OOP(0)); + MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No more runnable process\n"); + + #if 0 + if (there is semaphore awaited.... ) + { + /* DO SOMETHING */ + } + #endif + + return 0; + } + + while (moo->sem_list_count > 0) + { + /* handle async signals */ + --moo->sem_list_count; + signal_semaphore (moo, moo->sem_list[moo->sem_list_count]); + } + /* + if (semaphore heap has pending request) + { + signal them... + }*/ + + /* TODO: implement different process switching scheme - time-slice or clock based??? */ +#if defined(MOO_EXTERNAL_PROCESS_SWITCH) + if (!moo->proc_switched && moo->switch_proc) { switch_to_next_runnable_process (moo); } + moo->switch_proc = 0; +#else + if (!moo->proc_switched) { switch_to_next_runnable_process (moo); } +#endif + + moo->proc_switched = 0; + return 1; +} + int moo_execute (moo_t* moo) { moo_oob_t bcode; @@ -2922,6 +3022,7 @@ int moo_execute (moo_t* moo) int unwind_protect; moo_oop_context_t unwind_start; moo_oop_context_t unwind_stop; + int vm_startup_called = 0; #if defined(MOO_PROFILE_VM) moo_uintmax_t inst_counter = 0; @@ -2934,105 +3035,12 @@ int moo_execute (moo_t* moo) MOO_ASSERT (moo, moo->active_context != MOO_NULL); vm_startup (moo); + vm_startup_called = 1; moo->proc_switched = 0; while (1) { - if (moo->sem_heap_count > 0) - { - moo_ntime_t ft, now; - vm_gettime (moo, &now); - - do - { - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_sec)); - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_nsec)); - - MOO_INITNTIME (&ft, - MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_sec), - MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_nsec) - ); - - if (MOO_CMPNTIME(&ft, (moo_ntime_t*)&now) <= 0) - { - moo_oop_process_t proc; - - /* waited long enough. signal the semaphore */ - - proc = signal_semaphore (moo, moo->sem_heap[0]); - /* [NOTE] no moo_pushtmp() on proc. no GC must occur - * in the following line until it's used for - * wake_new_process() below. */ - delete_from_sem_heap (moo, 0); - - /* if no process is waiting on the semaphore, - * signal_semaphore() returns moo->_nil. */ - - if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil) - { - /* this is the only runnable process. - * switch the process to the running state. - * it uses wake_new_process() instead of - * switch_to_process() as there is no running - * process at this moment */ - MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); - MOO_ASSERT (moo, proc == moo->processor->runnable_head); - - wake_new_process (moo, proc); - moo->proc_switched = 1; - } - } - else if (moo->processor->active == moo->nil_process) - { - MOO_SUBNTIME (&ft, &ft, (moo_ntime_t*)&now); - vm_sleep (moo, &ft); /* TODO: change this to i/o multiplexer??? */ - vm_gettime (moo, &now); - } - else - { - break; - } - } - while (moo->sem_heap_count > 0); - } - - if (moo->processor->active == moo->nil_process) - { - /* no more waiting semaphore and no more process */ - MOO_ASSERT (moo, moo->processor->tally = MOO_SMOOI_TO_OOP(0)); - MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No more runnable process\n"); - - #if 0 - if (there is semaphore awaited.... ) - { - /* DO SOMETHING */ - } - #endif - - break; - } - - while (moo->sem_list_count > 0) - { - /* handle async signals */ - --moo->sem_list_count; - signal_semaphore (moo, moo->sem_list[moo->sem_list_count]); - } - /* - if (semaphore heap has pending request) - { - signal them... - }*/ - - /* TODO: implement different process switching scheme - time-slice or clock based??? */ -#if defined(MOO_EXTERNAL_PROCESS_SWITCH) - if (!moo->proc_switched && moo->switch_proc) { switch_to_next_runnable_process (moo); } - moo->switch_proc = 0; -#else - if (!moo->proc_switched) { switch_to_next_runnable_process (moo); } -#endif - - moo->proc_switched = 0; + if (switch_process_if_needed(moo) == 0) break; /* no more runnable process */ #if defined(MOO_DEBUG_VM_EXEC) fetched_instruction_pointer = moo->ip; @@ -3804,7 +3812,7 @@ int moo_execute (moo_t* moo) */ moo->ip--; #else - if (moo->active_context->origin == moo->processor->active->initial_context->origin) + if (MOO_UNLIKELY(moo->active_context->origin == moo->processor->active->initial_context->origin)) { /* method return from a processified block * @@ -4141,7 +4149,6 @@ int moo_execute (moo_t* moo) LOG_INST_0 (moo, "noop"); break; - default: MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Fatal error - unknown byte code 0x%zx\n", bcode); moo->errnum = MOO_EINTERN; @@ -4158,7 +4165,7 @@ done: return 0; oops: - /* TODO: anything to do here? */ + if (vm_startup_called) vm_cleanup (moo); return -1; } @@ -4182,3 +4189,14 @@ int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname return n; } +#if 0 +int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname) +{ +/* TODO: .... */ + /* call + * System initializeClasses + * and invoke + * objname mthname + */ +} +#endif diff --git a/moo/lib/main.c b/moo/lib/main.c index a2adf4a..a3b6187 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -116,6 +116,9 @@ typedef struct xtn_t xtn_t; struct xtn_t { const char* source_path; /* main source file */ +#if defined(_WIN32) + HANDLE waitable_timer; +#endif }; /* ========================================================================= */ @@ -675,7 +678,8 @@ static void vm_gettime (moo_t* moo, moo_ntime_t* now) static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) { #if defined(_WIN32) - if (moo->waitable_timer) + xtn_t* xtn = moo_getxtn(moo); + if (xtn->waitable_timer) { LARGE_INTEGER li; li.QuadPart = -MOO_SECNSEC_TO_NSEC(dur->sec, dur->nsec); @@ -735,17 +739,19 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) static void vm_startup (moo_t* moo) { #if defined(_WIN32) - moo->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + xtn->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); #endif } static void vm_cleanup (moo_t* moo) { #if defined(_WIN32) - if (moo->waitable_timer) + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + if (xtn->waitable_timer) { - CloseHandle (moo->waitable_timer); - moo->waitable_timer = MOO_NULL; + CloseHandle (xtn->waitable_timer); + xtn->waitable_timer = MOO_NULL; } #endif } diff --git a/moo/lib/moo-cfg.h.in b/moo/lib/moo-cfg.h.in index 68778bb..533ebe5 100644 --- a/moo/lib/moo-cfg.h.in +++ b/moo/lib/moo-cfg.h.in @@ -57,6 +57,9 @@ /* Define to 1 if you have the `closedir' function. */ #undef HAVE_CLOSEDIR +/* computed gotos */ +#undef HAVE_COMPUTED_GOTO + /* Define to 1 if you have the `coshq' function. */ #undef HAVE_COSHQ diff --git a/moo/lib/moo-cmn.h b/moo/lib/moo-cmn.h index ac2c433..af9bcba 100644 --- a/moo/lib/moo-cmn.h +++ b/moo/lib/moo-cmn.h @@ -720,11 +720,12 @@ typedef struct moo_t moo_t; #endif #if defined(MOO_HAVE_BUILTIN_EXPECT) -# define MOO_LIKELY(x) (__builtin_expect(!!x,1)) -# define MOO_UNLIKELY(x) (__builtin_expect(!!x,0)) +# define MOO_LIKELY(x) (__builtin_expect(!!(x),1)) +# define MOO_UNLIKELY(x) (__builtin_expect(!!(x),0)) #else # define MOO_LIKELY(x) (x) # define MOO_UNLIKELY(x) (x) #endif + #endif diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index b64e607..43114c6 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -873,17 +873,17 @@ enum moo_bcode_t /* -------------------------------------- */ - BCODE_MAKE_ARRAY = 0xF5, /* 245 */ - BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */ - BCODE_DUP_STACKTOP = 0xF7, - BCODE_POP_STACKTOP = 0xF8, - BCODE_RETURN_STACKTOP = 0xF9, /* ^something */ - BCODE_RETURN_RECEIVER = 0xFA, /* ^self */ - BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */ - BCODE_LOCAL_RETURN = 0xFC, - BCODE_MAKE_BLOCK = 0xFD, - BCODE_SEND_BLOCK_COPY = 0xFE, - BCODE_NOOP = 0xFF + BCODE_MAKE_ARRAY = 0xF5, /* 245 */ + BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */ + BCODE_DUP_STACKTOP = 0xF7, + BCODE_POP_STACKTOP = 0xF8, + BCODE_RETURN_STACKTOP = 0xF9, /* ^something */ + BCODE_RETURN_RECEIVER = 0xFA, /* ^self */ + BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */ + BCODE_LOCAL_RETURN = 0xFC, + BCODE_MAKE_BLOCK = 0xFD, + BCODE_SEND_BLOCK_COPY = 0xFE, + BCODE_NOOP = 0xFF }; #if defined(__cplusplus) @@ -1181,7 +1181,7 @@ moo_oop_t moo_strtoint ( moo_oop_t moo_inttostr ( moo_t* moo, moo_oop_t num, - int radix + int radix ); /* ========================================================================= */