refreshed whileTrue: and whileFalse:

This commit is contained in:
hyunghwan.chung 2016-05-12 05:53:35 +00:00
parent 197ceb3a76
commit 36a54fd29f
7 changed files with 180 additions and 84 deletions

View File

@ -22,6 +22,11 @@
^self.ip ^self.ip
} }
#method pcplus1
{
^self.ip + 1
}
#method pc: anInteger #method pc: anInteger
{ {
self.ip := anInteger. self.ip := anInteger.
@ -107,24 +112,31 @@
<primitive: #_block_value> <primitive: #_block_value>
self primitiveFailed. self primitiveFailed.
} }
#method value: a #method value: a
{ {
<primitive: #_block_value> <primitive: #_block_value>
self primitiveFailed. self primitiveFailed.
} }
#method value: a value: b #method value: a value: b
{ {
<primitive: #_block_value> <primitive: #_block_value>
self primitiveFailed. self primitiveFailed.
} }
#method value: a value: b value: c #method value: a value: b value: c
{ {
<primitive: #_block_value> <primitive: #_block_value>
self primitiveFailed. self primitiveFailed.
} }
#method value: a value: b value: c value: d
{
<primitive: #_block_value>
self primitiveFailed.
}
#method value: a value: b value: c value: d value: e
{
<primitive: #_block_value>
self primitiveFailed.
}
#method ifTrue: aBlock #method ifTrue: aBlock
{ {
@ -143,88 +155,128 @@
#method whileTrue: aBlock #method whileTrue: aBlock
{ {
## http://stackoverflow.com/questions/2500483/is-there-a-way-in-a-message-only-language-to-define-a-whiletrue-message-without ## --------------------------------------------------
## Naive implementation
## --------------------------------------------------
## (self value) ifFalse: [^nil].
## aBlock value.
## self whileTrue: aBlock.
## --------------------------------------------------
## ---------------------------------------------------------------------------- ## --------------------------------------------------
## If VM is built without STIX_USE_PROCSTK
## --------------------------------------------------
## | pc sp |
## sp := thisContext sp.
## pc := thisContext pcplus1.
## self value ifFalse: [ ^nil "^self" ].
## aBlock value.
## thisContext pc: pc sp: sp.
## --------------------------------------------------
## ^(self value) ifTrue: [aBlock value. self whileTrue: aBlock]. ## --------------------------------------------------
## If VM is built with STIX_USE_PROCSTK
## ---------------------------------------------------------------------------- ## --------------------------------------------------
| pc |
## less block context before whileTrue: is recursively sent. pc := thisContext pcplus1.
## whileTrue: is sent in a method context. (self value) ifFalse: [ ^nil "^self" ].
(self value) ifFalse: [^nil].
aBlock value.
self whileTrue: aBlock.
## ----------------------------------------------------------------------------
## ----------------------------------------------------------------------------
" | pc sp xsp |
sp := thisContext sp.
sp := sp - 1. ## decrement sp by 1 becuase thisContext pushed above affects the sp method
pc := thisContext pc.
self value ifFalse: [ ^nil "^self" ].
aBlock value. aBlock value.
##thisContext pc: pc - 3 sp: sp. thisContext pc: pc.
##thisContext pc: pc + 2 sp: sp. ## --------------------------------------------------
thisContext pc: pc + 1 sp: sp.
## this +2 or - 3 above is dependent on the byte code instruction size used for 'store'
## +2 to skip STORE_INTO_TEMP(pc) and POP_STACKTOP.
## TODO: make it independent of the byte code size
"
## ----------------------------------------------------------------------------
## #<label>:
## thisContext pc: #<label> sp: sp.
##
## | pc |
## pc := thisContext pc.
## ^self value ifTrue: [aBlock value. thisContext pc: pc]
## ----------------------------------------------------------------------------
## self value ifTrue: [ aBlock value. thisContext restart. ].
} }
#method whileTrue #method whileTrue
{ {
(self value) ifFalse: [^nil]. ## (self value) ifFalse: [^nil].
self whileTrue. ## self whileTrue.
## --------------------------------------------------
## If VM is built with STIX_USE_PROCSTK
## --------------------------------------------------
| pc |
pc := thisContext pcplus1.
(self value) ifFalse: [ ^nil "^self" ].
thisContext pc: pc.
## --------------------------------------------------
} }
#method whileFalse: aBlock #method whileFalse: aBlock
{ {
(self value) ifTrue: [^nil]. ## --------------------------------------------------
aBlock value. ## Naive implementation
self whileFalse: aBlock. ## --------------------------------------------------
## (self value) ifTrue: [^nil].
## aBlock value.
## self whileFalse: aBlock.
## --------------------------------------------------
## --------------------------------------------------
## If VM is built without STIX_USE_PROCSTK
## --------------------------------------------------
## | pc sp |
## sp := thisContext sp.
## pc := thisContext pcplus1.
## self value ifTrue: [ ^nil "^self" ].
## aBlock value.
## thisContext pc: pc sp: sp.
## --------------------------------------------------
## --------------------------------------------------
## If VM is built with STIX_USE_PROCSTK
## --------------------------------------------------
## The assignment to 'pc' uses the POP_INTO_TEMPVAR_1.
## It pops a value off the stack top, stores it to the second
## temporary variable(aBlock is the first temporary variable).
## It is a single byte instruction. 'pc' returned by
## 'thisContext pcplus1'' should point to the instruction after
## the POP_INTO_TEMPVAR_0 instruction.
##
## It would need the increment of 2 if the pair of
## STORE_INTO_TEMPVAR_1 and POP_STACKTOP were used.
## This implementation is subject to the instructions chosen
## by the compiler.
##
| pc |
pc := thisContext pcplus1.
(self value) ifTrue: [ ^nil "^self" ].
aBlock value.
thisContext pc: pc.
## --------------------------------------------------
} }
#method whileFalse #method whileFalse
{ {
(self value) ifTrue: [^nil]. ## (self value) ifTrue: [^nil].
self whileFalse. ## self whileFalse.
## --------------------------------------------------
## If VM is built with STIX_USE_PROCSTK
## --------------------------------------------------
| pc |
pc := thisContext pcplus1.
(self value) ifTrue: [ ^nil "^self" ].
thisContext pc: pc.
## --------------------------------------------------
} }
#method pc #method pc
{ {
^ip ^self.ip
} }
#method pc: anInteger #method pc: anInteger
{ {
ip := anInteger. self.ip := anInteger.
} }
#method sp #method sp
{ {
^sp ^self.sp
} }
#method sp: anInteger #method sp: anInteger
{ {
sp := anInteger. self.sp := anInteger.
} }
#method restart #method restart
@ -255,7 +307,6 @@ thisContext isExceptionHandlerContext dump.
^self value. ^self value.
} }
#method ensure: aBlock #method ensure: aBlock
{ {
"## "##

View File

@ -26,14 +26,13 @@
#include "stix-prv.h" #include "stix-prv.h"
#define TOKEN_NAME_ALIGN 256 #define CLASS_BUFFER_ALIGN 64
#define CLASS_BUFFER_ALIGN 8 /* 256 */ /*TODO: change 8 to 256 */ #define LITERAL_BUFFER_ALIGN 64
#define LITERAL_BUFFER_ALIGN 8 /* 256 */ #define CODE_BUFFER_ALIGN 64
#define CODE_BUFFER_ALIGN 8 /* 256 */ #define BALIT_BUFFER_ALIGN 64
#define BALIT_BUFFER_ALIGN 8 /* 256 */ #define ARLIT_BUFFER_ALIGN 64
#define ARLIT_BUFFER_ALIGN 8 /* 256 */ #define BLK_TMPRCNT_BUFFER_ALIGN 32
#define BLK_TMPRCNT_BUFFER_ALIGN 8 #define POOLDIC_OOP_BUFFER_ALIGN 32
#define POOLDIC_OOP_BUFFER_ALIGN 8
/* initial method dictionary size */ /* initial method dictionary size */
#define INSTANCE_METHOD_DICTIONARY_SIZE 256 /* TODO: choose the right size */ #define INSTANCE_METHOD_DICTIONARY_SIZE 256 /* TODO: choose the right size */
@ -643,7 +642,7 @@ static int get_char (stix_t* stix)
{ {
/* if the previous charater was a newline, /* if the previous charater was a newline,
* increment the line counter and reset column to 1. * increment the line counter and reset column to 1.
* incrementing it line number here instead of * incrementing the line number here instead of
* updating inp->lxc causes the line number for * updating inp->lxc causes the line number for
* TOK_EOF to be the same line as the lxc newline. */ * TOK_EOF to be the same line as the lxc newline. */
stix->c->curinp->line++; stix->c->curinp->line++;

View File

@ -36,6 +36,10 @@
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#if defined(_WIN32)
# include <windows.h>
#endif
#define PROC_STATE_RUNNING 3 #define PROC_STATE_RUNNING 3
#define PROC_STATE_WAITING 2 #define PROC_STATE_WAITING 2
#define PROC_STATE_RUNNABLE 1 #define PROC_STATE_RUNNABLE 1
@ -163,7 +167,27 @@
#endif #endif
static STIX_INLINE void vm_gettime (stix_ntime_t* now) /* ------------------------------------------------------------------------- */
static void vm_startup (stix_t* stix)
{
#if defined(_WIN32)
stix->waitable_timer = CreateWaitableTimer(STIX_NULL, TRUE, STIX_NULL);
#endif
}
static void vm_cleanup (stix_t* stix)
{
#if defined(_WIN32)
if (stix->waitable_timer)
{
CloseHandle (stix->waitable_timer);
stix->waitable_timer = STIX_NULL;
}
#endif
}
static STIX_INLINE void vm_gettime (stix_t* stix, stix_ntime_t* now)
{ {
#if defined(HAVE_CLOCK_GETTIME) #if defined(HAVE_CLOCK_GETTIME)
struct timespec ts; struct timespec ts;
@ -180,14 +204,33 @@ static STIX_INLINE void vm_gettime (stix_ntime_t* now)
#endif #endif
} }
static STIX_INLINE void vm_sleep (const stix_ntime_t* dur) static STIX_INLINE void vm_sleep (stix_t* stix, const stix_ntime_t* dur)
{ {
#if defined(_WIN32)
if (stix->waitable_timer)
{
LARGE_INTEGER li;
li.QuadPart = -STIX_SECNSEC_TO_NSEC(dur->sec, dur->nsec);
if(SetWaitableTimer(timer, &li, 0, STIX_NULL, STIX_NULL, FALSE) == FALSE) goto normal_sleep;
WaitForSingleObject(timer, INFINITE);
}
else
{
normal_sleep:
/* fallback to normal Sleep() */
Sleep (STIX_SECNSEC_TO_MSEC(dur->sec,dur->nsec));
}
#else
struct timespec ts; struct timespec ts;
ts.tv_sec = dur->sec; ts.tv_sec = dur->sec;
ts.tv_nsec = dur->nsec; ts.tv_nsec = dur->nsec;
nanosleep (&ts, STIX_NULL); nanosleep (&ts, STIX_NULL);
#endif
} }
/* ------------------------------------------------------------------------- */
static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c) static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c)
{ {
stix_oop_process_t proc; stix_oop_process_t proc;
@ -1782,7 +1825,7 @@ static int prim_processor_add_timed_semaphore (stix_t* stix, stix_ooi_t nargs)
* *
* this code assumes that the monotonic clock returns a small value * this code assumes that the monotonic clock returns a small value
* that can fit into a small integer, even after some addtions... */ * that can fit into a small integer, even after some addtions... */
vm_gettime (&now); vm_gettime (stix, &now);
STIX_ADDNTIMESNS (&ft, &now, STIX_OOP_TO_SMOOI(sec), STIX_OOP_TO_SMOOI(nsec)); STIX_ADDNTIMESNS (&ft, &now, STIX_OOP_TO_SMOOI(sec), STIX_OOP_TO_SMOOI(nsec));
if (ft.sec < 0 || ft.sec > STIX_SMOOI_MAX) if (ft.sec < 0 || ft.sec > STIX_SMOOI_MAX)
{ {
@ -2961,6 +3004,7 @@ int stix_execute (stix_t* stix)
STIX_ASSERT (stix->active_context != STIX_NULL); STIX_ASSERT (stix->active_context != STIX_NULL);
vm_startup (stix);
stix->proc_switched = 0; stix->proc_switched = 0;
while (1) while (1)
@ -2968,7 +3012,7 @@ int stix_execute (stix_t* stix)
if (stix->sem_heap_count > 0) if (stix->sem_heap_count > 0)
{ {
stix_ntime_t ft, now; stix_ntime_t ft, now;
vm_gettime (&now); vm_gettime (stix, &now);
do do
{ {
@ -3012,8 +3056,8 @@ int stix_execute (stix_t* stix)
else if (stix->processor->active == stix->nil_process) else if (stix->processor->active == stix->nil_process)
{ {
STIX_SUBNTIME (&ft, &ft, (stix_ntime_t*)&now); STIX_SUBNTIME (&ft, &ft, (stix_ntime_t*)&now);
vm_sleep (&ft); /* TODO: change this to i/o multiplexer??? */ vm_sleep (stix, &ft); /* TODO: change this to i/o multiplexer??? */
vm_gettime (&now); vm_gettime (stix, &now);
} }
else else
{ {
@ -3983,6 +4027,7 @@ printf ("UNKNOWN BYTE CODE ENCOUNTERED %x\n", (int)bcode);
done: done:
vm_cleanup (stix);
#if defined(STIX_PROFILE_EXEC) #if defined(STIX_PROFILE_EXEC)
printf ("TOTAL_INST_COUTNER = %lu\n", (unsigned long int)inst_counter); printf ("TOTAL_INST_COUTNER = %lu\n", (unsigned long int)inst_counter);
#endif #endif

View File

@ -258,7 +258,7 @@ static int ignite_3 (stix_t* stix)
{ 20, { 'L','a','r','g','e','N','e','g','a','t','i','v','e','I','n','t','e','g','e','r' } } { 20, { 'L','a','r','g','e','N','e','g','a','t','i','v','e','I','n','t','e','g','e','r' } }
}; };
static stix_ooch_t str_stix[] = { 'S','t','i','x' }; static stix_ooch_t str_system[] = { 'S','y','s','t','e', 'm' };
static stix_ooch_t str_processor[] = { 'P', 'r', 'o', 'c', 'e', 's', 's', 'o', 'r' }; static stix_ooch_t str_processor[] = { 'P', 'r', 'o', 'c', 'e', 's', 's', 'o', 'r' };
stix_oow_t i; stix_oow_t i;
@ -280,7 +280,7 @@ static int ignite_3 (stix_t* stix)
} }
/* Make the system dictionary available as the global name 'Stix' */ /* Make the system dictionary available as the global name 'Stix' */
sym = stix_makesymbol (stix, str_stix, 4); sym = stix_makesymbol (stix, str_system, 6);
if (!sym) return -1; if (!sym) return -1;
if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->sysdic)) return -1; if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->sysdic)) return -1;

View File

@ -370,7 +370,7 @@ static char* syntax_error_msg[] =
"literal expected" "literal expected"
}; };
stix_ooch_t str_stix[] = { 'S', 't', 'i', 'x' }; stix_ooch_t str_system[] = { 'S', 'y', 's', 't', 'e', 'm' };
stix_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' }; stix_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' };
stix_ooch_t str_main[] = { 'm', 'a', 'i', 'n' }; stix_ooch_t str_main[] = { 'm', 'a', 'i', 'n' };
@ -593,8 +593,8 @@ printf ("%p\n", a);
} }
} }
/* objname.ptr = str_stix; /* objname.ptr = str_system;
objname.len = 4;*/ objname.len = 6;*/
objname.ptr = str_my_object; objname.ptr = str_my_object;
objname.len = 8; objname.len = 8;
mthname.ptr = str_main; mthname.ptr = str_main;

View File

@ -39,7 +39,6 @@ void* stix_allocbytes (stix_t* stix, stix_oow_t size)
{ {
stix_gc (stix); stix_gc (stix);
ptr = stix_allocheapmem (stix, stix->curheap, size); ptr = stix_allocheapmem (stix, stix->curheap, size);
/* TODO: grow heap if ptr is still null. */ /* TODO: grow heap if ptr is still null. */
} }

View File

@ -169,11 +169,6 @@
# define STIX_HAVE_INT64_T # define STIX_HAVE_INT64_T
typedef unsigned __int64_t stix_uint64_t; typedef unsigned __int64_t stix_uint64_t;
typedef signed __int64_t stix_int64_t; typedef signed __int64_t stix_int64_t;
#elif defined(_WIN64) || defined(_WIN32)
# define STIX_HAVE_UINT64_T
# define STIX_HAVE_INT64_T
typedef unsigned __int64 stix_uint64_t;
typedef signed __int64 stix_int64_t;
#else #else
/* no 64-bit integer */ /* no 64-bit integer */
#endif #endif
@ -332,10 +327,13 @@ typedef stix_ucs_t stix_oocs_t;
#define STIX_NSECS_PER_SEC (STIX_NSECS_PER_USEC * STIX_USECS_PER_MSEC * STIX_MSECS_PER_SEC) #define STIX_NSECS_PER_SEC (STIX_NSECS_PER_USEC * STIX_USECS_PER_MSEC * STIX_MSECS_PER_SEC)
#define STIX_SECNSEC_TO_MSEC(sec,nsec) \ #define STIX_SECNSEC_TO_MSEC(sec,nsec) \
(((qse_long_t)(sec) * STIX_MSECS_PER_SEC) + ((qse_long_t)(nsec) / STIX_NSECS_PER_MSEC)) (((stix_intptr_t)(sec) * STIX_MSECS_PER_SEC) + ((stix_intptr_t)(nsec) / STIX_NSECS_PER_MSEC))
#define STIX_SECNSEC_TO_USEC(sec,nsec) \ #define STIX_SECNSEC_TO_USEC(sec,nsec) \
(((qse_long_t)(sec) * STIX_USECS_PER_SEC) + ((qse_long_t)(nsec) / STIX_NSECS_PER_USEC)) (((stix_intptr_t)(sec) * STIX_USECS_PER_SEC) + ((stix_intptr_t)(nsec) / STIX_NSECS_PER_USEC))
#define STIX_SECNSEC_TO_NSEC(sec,nsec) \
(((stix_intptr_t)(sec) * STIX_NSECS_PER_SEC) + (stix_intptr_t)(nsec))
#define STIX_SEC_TO_MSEC(sec) ((sec) * STIX_MSECS_PER_SEC) #define STIX_SEC_TO_MSEC(sec) ((sec) * STIX_MSECS_PER_SEC)
#define STIX_MSEC_TO_SEC(sec) ((sec) / STIX_MSECS_PER_SEC) #define STIX_MSEC_TO_SEC(sec) ((sec) / STIX_MSECS_PER_SEC)
@ -543,7 +541,11 @@ struct stix_cmgr_t
* MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER * MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER
* =========================================================================*/ * =========================================================================*/
#if defined(_WIN32) || (defined(__WATCOMC__) && !defined(__WINDOWS_386__)) #if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
# define STIX_IMPORT
# define STIX_EXPORT
# define STIX_PRIVATE
#elif defined(_WIN32) || (defined(__WATCOMC__) && !defined(__WINDOWS_386__))
# define STIX_IMPORT __declspec(dllimport) # define STIX_IMPORT __declspec(dllimport)
# define STIX_EXPORT __declspec(dllexport) # define STIX_EXPORT __declspec(dllexport)
# define STIX_PRIVATE # define STIX_PRIVATE