refactored moo_execute() by taking process switcher out to a separate inline function

This commit is contained in:
hyunghwan.chung 2017-02-11 05:48:30 +00:00
parent 7384777b59
commit 2c8eb87408
8 changed files with 208 additions and 129 deletions

42
moo/configure vendored
View File

@ -18566,8 +18566,8 @@ esac
LIBM=$LIBM LIBM=$LIBM
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memset" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memset" >&5
$as_echo_n "checking __builtin_memset... " >&6; } $as_echo_n "checking for __builtin_memset... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
@ -18592,8 +18592,8 @@ $as_echo "no" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memcpy" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memcpy" >&5
$as_echo_n "checking __builtin_memcpy... " >&6; } $as_echo_n "checking for __builtin_memcpy... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
@ -18618,8 +18618,8 @@ $as_echo "no" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memmove" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memmove" >&5
$as_echo_n "checking __builtin_memmove... " >&6; } $as_echo_n "checking for __builtin_memmove... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
@ -18644,8 +18644,8 @@ $as_echo "no" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memcmp" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_memcmp" >&5
$as_echo_n "checking __builtin_memcmp... " >&6; } $as_echo_n "checking for __builtin_memcmp... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
@ -18670,6 +18670,32 @@ $as_echo "no" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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 "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; } $as_echo_n "checking for ANSI C header files... " >&6; }
if ${ac_cv_header_stdc+:} false; then : if ${ac_cv_header_stdc+:} false; then :

View File

@ -108,7 +108,7 @@ LT_LIB_M
AC_SUBST(LIBM, $LIBM) AC_SUBST(LIBM, $LIBM)
dnl check some compiler builtins dnl check some compiler builtins
AC_MSG_CHECKING([__builtin_memset]) AC_MSG_CHECKING([for __builtin_memset])
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([], [__builtin_memset ((void*)1, ' ', 10);])], [AC_LANG_PROGRAM([], [__builtin_memset ((void*)1, ' ', 10);])],
[AC_MSG_RESULT(yes) [AC_MSG_RESULT(yes)
@ -116,7 +116,7 @@ AC_COMPILE_IFELSE(
[AC_MSG_RESULT(no)] [AC_MSG_RESULT(no)]
) )
AC_MSG_CHECKING([__builtin_memcpy]) AC_MSG_CHECKING([for __builtin_memcpy])
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([], [__builtin_memcpy ((void*)1, (void*)2, 10);])], [AC_LANG_PROGRAM([], [__builtin_memcpy ((void*)1, (void*)2, 10);])],
[AC_MSG_RESULT(yes) [AC_MSG_RESULT(yes)
@ -124,7 +124,7 @@ AC_COMPILE_IFELSE(
[AC_MSG_RESULT(no)] [AC_MSG_RESULT(no)]
) )
AC_MSG_CHECKING([__builtin_memmove]) AC_MSG_CHECKING([for __builtin_memmove])
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([], [__builtin_memmove ((void*)1, (void*)2, 10);])], [AC_LANG_PROGRAM([], [__builtin_memmove ((void*)1, (void*)2, 10);])],
[AC_MSG_RESULT(yes) [AC_MSG_RESULT(yes)
@ -132,7 +132,7 @@ AC_COMPILE_IFELSE(
[AC_MSG_RESULT(no)] [AC_MSG_RESULT(no)]
) )
AC_MSG_CHECKING([__builtin_memcmp]) AC_MSG_CHECKING([for __builtin_memcmp])
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([], [int a = __builtin_memcmp ((void*)1, (void*)2, 10);])], [AC_LANG_PROGRAM([], [int a = __builtin_memcmp ((void*)1, (void*)2, 10);])],
[AC_MSG_RESULT(yes) [AC_MSG_RESULT(yes)
@ -140,6 +140,14 @@ AC_COMPILE_IFELSE(
[AC_MSG_RESULT(no)] [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. dnl check header files.
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h]) AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h])

View File

@ -329,6 +329,23 @@ class MyObject(Object)
Processor sleepFor: 20. 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.
}
}*)
} }
(* (*

View File

@ -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) int moo_execute (moo_t* moo)
{ {
moo_oob_t bcode; moo_oob_t bcode;
@ -2922,6 +3022,7 @@ int moo_execute (moo_t* moo)
int unwind_protect; int unwind_protect;
moo_oop_context_t unwind_start; moo_oop_context_t unwind_start;
moo_oop_context_t unwind_stop; moo_oop_context_t unwind_stop;
int vm_startup_called = 0;
#if defined(MOO_PROFILE_VM) #if defined(MOO_PROFILE_VM)
moo_uintmax_t inst_counter = 0; moo_uintmax_t inst_counter = 0;
@ -2934,105 +3035,12 @@ int moo_execute (moo_t* moo)
MOO_ASSERT (moo, moo->active_context != MOO_NULL); MOO_ASSERT (moo, moo->active_context != MOO_NULL);
vm_startup (moo); vm_startup (moo);
vm_startup_called = 1;
moo->proc_switched = 0; moo->proc_switched = 0;
while (1) while (1)
{ {
if (moo->sem_heap_count > 0) if (switch_process_if_needed(moo) == 0) break; /* no more runnable process */
{
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 defined(MOO_DEBUG_VM_EXEC) #if defined(MOO_DEBUG_VM_EXEC)
fetched_instruction_pointer = moo->ip; fetched_instruction_pointer = moo->ip;
@ -3804,7 +3812,7 @@ int moo_execute (moo_t* moo)
*/ */
moo->ip--; moo->ip--;
#else #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 /* method return from a processified block
* *
@ -4141,7 +4149,6 @@ int moo_execute (moo_t* moo)
LOG_INST_0 (moo, "noop"); LOG_INST_0 (moo, "noop");
break; break;
default: default:
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Fatal error - unknown byte code 0x%zx\n", bcode); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Fatal error - unknown byte code 0x%zx\n", bcode);
moo->errnum = MOO_EINTERN; moo->errnum = MOO_EINTERN;
@ -4158,7 +4165,7 @@ done:
return 0; return 0;
oops: oops:
/* TODO: anything to do here? */ if (vm_startup_called) vm_cleanup (moo);
return -1; return -1;
} }
@ -4182,3 +4189,14 @@ int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname
return n; 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

View File

@ -116,6 +116,9 @@ typedef struct xtn_t xtn_t;
struct xtn_t struct xtn_t
{ {
const char* source_path; /* main source file */ 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) static void vm_sleep (moo_t* moo, const moo_ntime_t* dur)
{ {
#if defined(_WIN32) #if defined(_WIN32)
if (moo->waitable_timer) xtn_t* xtn = moo_getxtn(moo);
if (xtn->waitable_timer)
{ {
LARGE_INTEGER li; LARGE_INTEGER li;
li.QuadPart = -MOO_SECNSEC_TO_NSEC(dur->sec, dur->nsec); 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) static void vm_startup (moo_t* moo)
{ {
#if defined(_WIN32) #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 #endif
} }
static void vm_cleanup (moo_t* moo) static void vm_cleanup (moo_t* moo)
{ {
#if defined(_WIN32) #if defined(_WIN32)
if (moo->waitable_timer) xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
if (xtn->waitable_timer)
{ {
CloseHandle (moo->waitable_timer); CloseHandle (xtn->waitable_timer);
moo->waitable_timer = MOO_NULL; xtn->waitable_timer = MOO_NULL;
} }
#endif #endif
} }

View File

@ -57,6 +57,9 @@
/* Define to 1 if you have the `closedir' function. */ /* Define to 1 if you have the `closedir' function. */
#undef HAVE_CLOSEDIR #undef HAVE_CLOSEDIR
/* computed gotos */
#undef HAVE_COMPUTED_GOTO
/* Define to 1 if you have the `coshq' function. */ /* Define to 1 if you have the `coshq' function. */
#undef HAVE_COSHQ #undef HAVE_COSHQ

View File

@ -720,11 +720,12 @@ typedef struct moo_t moo_t;
#endif #endif
#if defined(MOO_HAVE_BUILTIN_EXPECT) #if defined(MOO_HAVE_BUILTIN_EXPECT)
# define MOO_LIKELY(x) (__builtin_expect(!!x,1)) # define MOO_LIKELY(x) (__builtin_expect(!!(x),1))
# define MOO_UNLIKELY(x) (__builtin_expect(!!x,0)) # define MOO_UNLIKELY(x) (__builtin_expect(!!(x),0))
#else #else
# define MOO_LIKELY(x) (x) # define MOO_LIKELY(x) (x)
# define MOO_UNLIKELY(x) (x) # define MOO_UNLIKELY(x) (x)
#endif #endif
#endif #endif

View File

@ -873,17 +873,17 @@ enum moo_bcode_t
/* -------------------------------------- */ /* -------------------------------------- */
BCODE_MAKE_ARRAY = 0xF5, /* 245 */ BCODE_MAKE_ARRAY = 0xF5, /* 245 */
BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */ BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */
BCODE_DUP_STACKTOP = 0xF7, BCODE_DUP_STACKTOP = 0xF7,
BCODE_POP_STACKTOP = 0xF8, BCODE_POP_STACKTOP = 0xF8,
BCODE_RETURN_STACKTOP = 0xF9, /* ^something */ BCODE_RETURN_STACKTOP = 0xF9, /* ^something */
BCODE_RETURN_RECEIVER = 0xFA, /* ^self */ BCODE_RETURN_RECEIVER = 0xFA, /* ^self */
BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */ BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */
BCODE_LOCAL_RETURN = 0xFC, BCODE_LOCAL_RETURN = 0xFC,
BCODE_MAKE_BLOCK = 0xFD, BCODE_MAKE_BLOCK = 0xFD,
BCODE_SEND_BLOCK_COPY = 0xFE, BCODE_SEND_BLOCK_COPY = 0xFE,
BCODE_NOOP = 0xFF BCODE_NOOP = 0xFF
}; };
#if defined(__cplusplus) #if defined(__cplusplus)
@ -1181,7 +1181,7 @@ moo_oop_t moo_strtoint (
moo_oop_t moo_inttostr ( moo_oop_t moo_inttostr (
moo_t* moo, moo_t* moo,
moo_oop_t num, moo_oop_t num,
int radix int radix
); );
/* ========================================================================= */ /* ========================================================================= */