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
}
#method pcplus1
{
^self.ip + 1
}
#method pc: anInteger
{
self.ip := anInteger.
@ -107,24 +112,31 @@
<primitive: #_block_value>
self primitiveFailed.
}
#method value: a
{
<primitive: #_block_value>
self primitiveFailed.
}
#method value: a value: b
{
<primitive: #_block_value>
self primitiveFailed.
}
#method value: a value: b value: c
{
<primitive: #_block_value>
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
{
@ -143,88 +155,128 @@
#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].
## ----------------------------------------------------------------------------
## less block context before whileTrue: is recursively sent.
## whileTrue: is sent in a method context.
(self value) ifFalse: [^nil].
## --------------------------------------------------
## If VM is built with STIX_USE_PROCSTK
## --------------------------------------------------
| pc |
pc := thisContext pcplus1.
(self value) ifFalse: [ ^nil "^self" ].
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.
##thisContext pc: pc - 3 sp: sp.
##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. ].
thisContext pc: pc.
## --------------------------------------------------
}
#method whileTrue
{
(self value) ifFalse: [^nil].
self whileTrue.
## (self value) ifFalse: [^nil].
## 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
{
(self value) ifTrue: [^nil].
## --------------------------------------------------
## Naive implementation
## --------------------------------------------------
## (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.
self whileFalse: aBlock.
thisContext pc: pc.
## --------------------------------------------------
}
#method whileFalse
{
(self value) ifTrue: [^nil].
self whileFalse.
## (self value) ifTrue: [^nil].
## self whileFalse.
## --------------------------------------------------
## If VM is built with STIX_USE_PROCSTK
## --------------------------------------------------
| pc |
pc := thisContext pcplus1.
(self value) ifTrue: [ ^nil "^self" ].
thisContext pc: pc.
## --------------------------------------------------
}
#method pc
{
^ip
^self.ip
}
#method pc: anInteger
{
ip := anInteger.
self.ip := anInteger.
}
#method sp
{
^sp
^self.sp
}
#method sp: anInteger
{
sp := anInteger.
self.sp := anInteger.
}
#method restart
@ -255,7 +307,6 @@ thisContext isExceptionHandlerContext dump.
^self value.
}
#method ensure: aBlock
{
"##

View File

@ -26,14 +26,13 @@
#include "stix-prv.h"
#define TOKEN_NAME_ALIGN 256
#define CLASS_BUFFER_ALIGN 8 /* 256 */ /*TODO: change 8 to 256 */
#define LITERAL_BUFFER_ALIGN 8 /* 256 */
#define CODE_BUFFER_ALIGN 8 /* 256 */
#define BALIT_BUFFER_ALIGN 8 /* 256 */
#define ARLIT_BUFFER_ALIGN 8 /* 256 */
#define BLK_TMPRCNT_BUFFER_ALIGN 8
#define POOLDIC_OOP_BUFFER_ALIGN 8
#define CLASS_BUFFER_ALIGN 64
#define LITERAL_BUFFER_ALIGN 64
#define CODE_BUFFER_ALIGN 64
#define BALIT_BUFFER_ALIGN 64
#define ARLIT_BUFFER_ALIGN 64
#define BLK_TMPRCNT_BUFFER_ALIGN 32
#define POOLDIC_OOP_BUFFER_ALIGN 32
/* initial method dictionary 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,
* 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
* TOK_EOF to be the same line as the lxc newline. */
stix->c->curinp->line++;

View File

@ -36,6 +36,10 @@
# include <sys/time.h>
#endif
#if defined(_WIN32)
# include <windows.h>
#endif
#define PROC_STATE_RUNNING 3
#define PROC_STATE_WAITING 2
#define PROC_STATE_RUNNABLE 1
@ -163,7 +167,27 @@
#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)
struct timespec ts;
@ -180,14 +204,33 @@ static STIX_INLINE void vm_gettime (stix_ntime_t* now)
#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;
ts.tv_sec = dur->sec;
ts.tv_nsec = dur->nsec;
nanosleep (&ts, STIX_NULL);
#endif
}
/* ------------------------------------------------------------------------- */
static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c)
{
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
* 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));
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);
vm_startup (stix);
stix->proc_switched = 0;
while (1)
@ -2968,7 +3012,7 @@ int stix_execute (stix_t* stix)
if (stix->sem_heap_count > 0)
{
stix_ntime_t ft, now;
vm_gettime (&now);
vm_gettime (stix, &now);
do
{
@ -3012,8 +3056,8 @@ int stix_execute (stix_t* stix)
else if (stix->processor->active == stix->nil_process)
{
STIX_SUBNTIME (&ft, &ft, (stix_ntime_t*)&now);
vm_sleep (&ft); /* TODO: change this to i/o multiplexer??? */
vm_gettime (&now);
vm_sleep (stix, &ft); /* TODO: change this to i/o multiplexer??? */
vm_gettime (stix, &now);
}
else
{
@ -3983,6 +4027,7 @@ printf ("UNKNOWN BYTE CODE ENCOUNTERED %x\n", (int)bcode);
done:
vm_cleanup (stix);
#if defined(STIX_PROFILE_EXEC)
printf ("TOTAL_INST_COUTNER = %lu\n", (unsigned long int)inst_counter);
#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' } }
};
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' };
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' */
sym = stix_makesymbol (stix, str_stix, 4);
sym = stix_makesymbol (stix, str_system, 6);
if (!sym) 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"
};
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_main[] = { 'm', 'a', 'i', 'n' };
@ -593,8 +593,8 @@ printf ("%p\n", a);
}
}
/* objname.ptr = str_stix;
objname.len = 4;*/
/* objname.ptr = str_system;
objname.len = 6;*/
objname.ptr = str_my_object;
objname.len = 8;
mthname.ptr = str_main;

View File

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

View File

@ -169,11 +169,6 @@
# define STIX_HAVE_INT64_T
typedef unsigned __int64_t stix_uint64_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
/* no 64-bit integer */
#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_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) \
(((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_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
* =========================================================================*/
#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_EXPORT __declspec(dllexport)
# define STIX_PRIVATE