added some experimental code to support object finalization
This commit is contained in:
parent
fc121cd70a
commit
03fd02d59b
@ -130,6 +130,12 @@ extend Apex
|
|||||||
else { self primitiveFailed }
|
else { self primitiveFailed }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(* ------------------------------------------------------------------
|
||||||
|
* FINALIZATION SUPPORT
|
||||||
|
* ------------------------------------------------------------------ *)
|
||||||
|
method(#dual,#primitive) addToBeFinalized.
|
||||||
|
##method(#dual,#primitive) removeToBeFinalized.
|
||||||
|
|
||||||
(* ------------------------------------------------------------------
|
(* ------------------------------------------------------------------
|
||||||
* HASHING
|
* HASHING
|
||||||
* ------------------------------------------------------------------ *)
|
* ------------------------------------------------------------------ *)
|
||||||
|
@ -10,6 +10,45 @@
|
|||||||
|
|
||||||
class System(Apex)
|
class System(Apex)
|
||||||
{
|
{
|
||||||
|
method(#class) startup(class_name, method_name)
|
||||||
|
{
|
||||||
|
| class ret |
|
||||||
|
|
||||||
|
class := System at: class_name.
|
||||||
|
if (class isError)
|
||||||
|
{
|
||||||
|
System error: ('Cannot find the class - ' & class_name).
|
||||||
|
}.
|
||||||
|
|
||||||
|
## start the gc finalizer process
|
||||||
|
[ self __gc_finalizer ] fork.
|
||||||
|
|
||||||
|
## TODO: change the method signature to variadic and pass extra arguments to perform???
|
||||||
|
ret := class perform: method_name.
|
||||||
|
|
||||||
|
#### System logNl: '======= END of startup ==============='.
|
||||||
|
^ret.
|
||||||
|
}
|
||||||
|
|
||||||
|
method(#class) __gc_finalizer
|
||||||
|
{
|
||||||
|
| tmp |
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
## TODO: exit from this loop when there are no other processes running.
|
||||||
|
while ((tmp := self _popCollectable) notError)
|
||||||
|
{
|
||||||
|
## TODO: Do i have to protected this in an exception handler???
|
||||||
|
tmp finalize.
|
||||||
|
}.
|
||||||
|
|
||||||
|
System logNl: 'gc_waiting....'.
|
||||||
|
Processor sleepFor: 1. ## TODO: wait on semaphore instead..
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
method(#class,#primitive) _popCollectable.
|
||||||
}
|
}
|
||||||
|
|
||||||
pooldic System.Log
|
pooldic System.Log
|
||||||
|
@ -300,10 +300,13 @@ class X11.Widget(Object)
|
|||||||
|
|
||||||
method onPaintEvent: paint_event
|
method onPaintEvent: paint_event
|
||||||
{
|
{
|
||||||
System logNl: 'Widget...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
method onButtonEvent: event
|
method onMouseButtonEvent: event
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
method onKeyEvent: event
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,23 +340,45 @@ class X11.Label(X11.Widget)
|
|||||||
method onPaintEvent: paint_event
|
method onPaintEvent: paint_event
|
||||||
{
|
{
|
||||||
| gc |
|
| gc |
|
||||||
System logNl: 'LABEL GC...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'.
|
|
||||||
|
|
||||||
gc := selfns.GC new: self.
|
gc := selfns.GC new: self.
|
||||||
[
|
[
|
||||||
gc foreground: self.fgcolor;
|
gc foreground: self.bgcolor;
|
||||||
fontName: '-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1';
|
fontName: '-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1';
|
||||||
apply.
|
apply.
|
||||||
|
gc fillRectangle (0, 0, self.width, self.height).
|
||||||
|
|
||||||
|
gc foreground: self.fgcolor; apply.
|
||||||
gc drawRectangle (0, 0, self.width - 1, self.height - 1).
|
gc drawRectangle (0, 0, self.width - 1, self.height - 1).
|
||||||
##gc fillRectangle (0, 0, self.width, self.height).
|
|
||||||
##gc drawLine (0, y, CTRLWIDE, y).
|
|
||||||
##gc drawLine (0, y + CHIGH + 4, CTRLWIDE, Y+CHIGH+4).
|
|
||||||
|
|
||||||
gc drawString(10, 10, self.text).
|
gc drawString(10, 10, self.text).
|
||||||
] ensure: [ gc dispose ]
|
] ensure: [ gc dispose ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class X11.Button(X11.Label)
|
||||||
|
{
|
||||||
|
method onMouseButtonEvent: llevent
|
||||||
|
{
|
||||||
|
| type x |
|
||||||
|
type := llevent type.
|
||||||
|
if (type == X11.LLEventType.BUTTON_PRESS)
|
||||||
|
{
|
||||||
|
x := self.fgcolor.
|
||||||
|
self.fgcolor := self.bgcolor.
|
||||||
|
self.bgcolor := x.
|
||||||
|
self onPaintEvent: llevent.
|
||||||
|
}
|
||||||
|
elsif (type == X11.LLEventType.BUTTON_RELEASE)
|
||||||
|
{
|
||||||
|
x := self.fgcolor.
|
||||||
|
self.fgcolor := self.bgcolor.
|
||||||
|
self.bgcolor := x.
|
||||||
|
self onPaintEvent: llevent.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class X11.Composite(X11.Widget)
|
class X11.Composite(X11.Widget)
|
||||||
{
|
{
|
||||||
var children.
|
var children.
|
||||||
@ -646,8 +671,9 @@ extend X11
|
|||||||
widget onPaintEvent: llevent
|
widget onPaintEvent: llevent
|
||||||
}
|
}
|
||||||
|
|
||||||
method __handle_button_event: event on: widget
|
method __handle_button_event: llevent on: widget
|
||||||
{
|
{
|
||||||
|
widget onMouseButtonEvent: llevent
|
||||||
}
|
}
|
||||||
|
|
||||||
method __handle_destroy_notify: event on: widget
|
method __handle_destroy_notify: event on: widget
|
||||||
@ -664,8 +690,9 @@ extend X11
|
|||||||
widget close: event.
|
widget close: event.
|
||||||
}
|
}
|
||||||
|
|
||||||
method __handle_key_event: event on: widget
|
method __handle_key_event: llevent on: widget
|
||||||
{
|
{
|
||||||
|
widget onKeyEvent: llevent
|
||||||
}
|
}
|
||||||
|
|
||||||
method __handle_shell_close: llevent on: widget
|
method __handle_shell_close: llevent on: widget
|
||||||
@ -675,7 +702,18 @@ extend X11
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Fx(Object)
|
||||||
|
{
|
||||||
|
method initialize
|
||||||
|
{
|
||||||
|
self addToBeFinalized.
|
||||||
|
}
|
||||||
|
|
||||||
|
method finalize
|
||||||
|
{
|
||||||
|
System logNl: 'Greate... FX instance finalized'.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MyObject(Object)
|
class MyObject(Object)
|
||||||
{
|
{
|
||||||
@ -706,16 +744,23 @@ class MyObject(Object)
|
|||||||
comp1 add: (X11.Label new text: '간다'; width: 100; height: 100).
|
comp1 add: (X11.Label new text: '간다'; width: 100; height: 100).
|
||||||
comp1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
comp1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||||
## self.shell1 add: (X11.Label new text: 'xxxxxxxx'; width: 100; height: 100).
|
## self.shell1 add: (X11.Label new text: 'xxxxxxxx'; width: 100; height: 100).
|
||||||
self.shell1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
self.shell1 add: (X11.Button new text: '크레용crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||||
|
|
||||||
self.shell2 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
self.shell2 add: (X11.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||||
self.shell3 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
self.shell3 add: (X11.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||||
self.shell1 realize.
|
self.shell1 realize.
|
||||||
self.shell2 realize.
|
self.shell2 realize.
|
||||||
self.shell3 realize.
|
self.shell3 realize.
|
||||||
|
|
||||||
self.disp1 enterEventLoop. ## this is not a blocking call. it spawns another process.
|
self.disp1 enterEventLoop. ## this is not a blocking call. it spawns another process.
|
||||||
self.disp2 enterEventLoop.
|
self.disp2 enterEventLoop.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
comp1 := Fx new.
|
||||||
|
Fx new.
|
||||||
|
Fx new.
|
||||||
|
Fx new.
|
||||||
}
|
}
|
||||||
|
|
||||||
method(#class) main
|
method(#class) main
|
||||||
|
@ -4354,7 +4354,7 @@ static int compile_block_expression (moo_t* moo)
|
|||||||
{
|
{
|
||||||
colon_loc = moo->c->tok.loc;
|
colon_loc = moo->c->tok.loc;
|
||||||
|
|
||||||
/* block temporary variables */
|
/* block temporary variables - argument to blocks */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
GET_TOKEN (moo);
|
GET_TOKEN (moo);
|
||||||
|
241
moo/lib/exec.c
241
moo/lib/exec.c
@ -89,10 +89,10 @@
|
|||||||
# define LOG_MASK_INST (MOO_LOG_IC | MOO_LOG_MNEMONIC)
|
# define LOG_MASK_INST (MOO_LOG_IC | MOO_LOG_MNEMONIC)
|
||||||
|
|
||||||
/* TODO: for send_message, display the method name. or include the method name before 'ip' */
|
/* TODO: for send_message, display the method name. or include the method name before 'ip' */
|
||||||
# define LOG_INST_0(moo,fmt) MOO_LOG1(moo, LOG_MASK_INST, " %06zd " fmt "\n", fetched_instruction_pointer)
|
# define LOG_INST_0(moo,fmt) MOO_LOG1(moo, LOG_MASK_INST, " %06zd " fmt "\n", (moo)->last_inst_pointer)
|
||||||
# define LOG_INST_1(moo,fmt,a1) MOO_LOG2(moo, LOG_MASK_INST, " %06zd " fmt "\n",fetched_instruction_pointer, a1)
|
# define LOG_INST_1(moo,fmt,a1) MOO_LOG2(moo, LOG_MASK_INST, " %06zd " fmt "\n",(moo)->last_inst_pointer, a1)
|
||||||
# define LOG_INST_2(moo,fmt,a1,a2) MOO_LOG3(moo, LOG_MASK_INST, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2)
|
# define LOG_INST_2(moo,fmt,a1,a2) MOO_LOG3(moo, LOG_MASK_INST, " %06zd " fmt "\n", (moo)->last_inst_pointer, a1, a2)
|
||||||
# define LOG_INST_3(moo,fmt,a1,a2,a3) MOO_LOG4(moo, LOG_MASK_INST, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3)
|
# define LOG_INST_3(moo,fmt,a1,a2,a3) MOO_LOG4(moo, LOG_MASK_INST, " %06zd " fmt "\n", (moo)->last_inst_pointer, a1, a2, a3)
|
||||||
#else
|
#else
|
||||||
# define LOG_INST_0(moo,fmt)
|
# define LOG_INST_0(moo,fmt)
|
||||||
# define LOG_INST_1(moo,fmt,a1)
|
# define LOG_INST_1(moo,fmt,a1)
|
||||||
@ -114,6 +114,7 @@ static int send_message_with_str (moo_t* moo, const moo_ooch_t* nameptr, moo_oow
|
|||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
static MOO_INLINE int vm_startup (moo_t* moo)
|
static MOO_INLINE int vm_startup (moo_t* moo)
|
||||||
{
|
{
|
||||||
|
MOO_DEBUG0 (moo, "VM started up\n");
|
||||||
if (moo->vmprim.vm_startup (moo) <= -1) return -1;
|
if (moo->vmprim.vm_startup (moo) <= -1) return -1;
|
||||||
moo->vmprim.vm_gettime (moo, &moo->exec_start_time); /* raw time. no adjustment */
|
moo->vmprim.vm_gettime (moo, &moo->exec_start_time); /* raw time. no adjustment */
|
||||||
return 0;
|
return 0;
|
||||||
@ -123,6 +124,7 @@ static MOO_INLINE void vm_cleanup (moo_t* moo)
|
|||||||
{
|
{
|
||||||
moo->vmprim.vm_gettime (moo, &moo->exec_end_time); /* raw time. no adjustment */
|
moo->vmprim.vm_gettime (moo, &moo->exec_end_time); /* raw time. no adjustment */
|
||||||
moo->vmprim.vm_cleanup (moo);
|
moo->vmprim.vm_cleanup (moo);
|
||||||
|
MOO_DEBUG0 (moo, "VM cleaned up\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOO_INLINE void vm_gettime (moo_t* moo, moo_ntime_t* now)
|
static MOO_INLINE void vm_gettime (moo_t* moo, moo_ntime_t* now)
|
||||||
@ -556,7 +558,7 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
|||||||
|
|
||||||
/* [NOTE] no GC must occur as 'proc' isn't protected with moo_pushtmp(). */
|
/* [NOTE] no GC must occur as 'proc' isn't protected with moo_pushtmp(). */
|
||||||
|
|
||||||
/* detach a process from a semaphore waiting list and
|
/* detach a process from a semaphore's waiting list and
|
||||||
* make it runnable */
|
* make it runnable */
|
||||||
unchain_from_semaphore (moo, proc);
|
unchain_from_semaphore (moo, proc);
|
||||||
resume_process (moo, proc); /* TODO: error check */
|
resume_process (moo, proc); /* TODO: error check */
|
||||||
@ -1130,30 +1132,97 @@ static int start_initial_process_and_context (moo_t* moo, const moo_oocs_t* objn
|
|||||||
* send #main
|
* send #main
|
||||||
*/
|
*/
|
||||||
moo_oop_context_t ctx;
|
moo_oop_context_t ctx;
|
||||||
moo_oop_association_t ass;
|
|
||||||
moo_oop_method_t mth;
|
moo_oop_method_t mth;
|
||||||
moo_oop_process_t proc;
|
moo_oop_process_t proc;
|
||||||
|
#if defined(INVOKE_DIRECTLY)
|
||||||
|
moo_oop_association_t ass;
|
||||||
|
#else
|
||||||
|
moo_oop_t s1, s2;
|
||||||
|
#endif
|
||||||
|
moo_oow_t tmp_count = 0;
|
||||||
|
|
||||||
|
moo_oocs_t startup;
|
||||||
|
static moo_ooch_t str_startup[] = { 's', 't', 'a', 'r', 't', 'u', 'p' };
|
||||||
|
|
||||||
|
#if defined(INVOKE_DIRECTLY)
|
||||||
|
|
||||||
/* create a fake initial context. */
|
|
||||||
ctx = (moo_oop_context_t)moo_instantiate (moo, moo->_method_context, MOO_NULL, 0);
|
|
||||||
if (!ctx) return -1;
|
|
||||||
|
|
||||||
ass = moo_lookupsysdic (moo, objname);
|
ass = moo_lookupsysdic (moo, objname);
|
||||||
if (!ass) return -1;
|
if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class)
|
||||||
|
{
|
||||||
|
MOO_DEBUG2 (moo, "Cannot find a class - %.*js", objname->len, objname->ptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
mth = find_method (moo, ass->value, mthname, 0);
|
mth = find_method (moo, ass->value, mthname, 0);
|
||||||
if (!mth) return -1;
|
if (!mth)
|
||||||
|
{
|
||||||
|
MOO_DEBUG4 (moo, "Cannot find a method in %.*js - %.*js", objname->len, objname->ptr, mthname->len, mthname->ptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (MOO_OOP_TO_SMOOI(mth->tmpr_nargs) > 0)
|
if (MOO_OOP_TO_SMOOI(mth->tmpr_nargs) > 0)
|
||||||
{
|
{
|
||||||
/* this method expects more than 0 arguments.
|
/* this method expects more than 0 arguments.
|
||||||
* i can't use it as a start-up method.
|
* i can't use it as a start-up method.
|
||||||
TODO: overcome this problem
|
TODO: overcome this problem - accept parameters....
|
||||||
*/
|
*/
|
||||||
|
MOO_DEBUG4 (moo, "Arguments not supported for a startup method - %.*js>>%.*js", objname->len, objname->ptr, mthname->len, mthname->ptr);
|
||||||
moo_seterrnum (moo, MOO_EINVAL);
|
moo_seterrnum (moo, MOO_EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moo_pushtmp (moo, (moo_oop_t*)&mth); tmp_count++;
|
||||||
|
moo_pushtmp (moo, (moo_oop_t*)&ass); tmp_count++;
|
||||||
|
#else
|
||||||
|
|
||||||
|
startup.ptr = str_startup;
|
||||||
|
startup.len = 7;
|
||||||
|
mth = find_method (moo, (moo_oop_t)moo->_system, &startup, 0);
|
||||||
|
if (!mth)
|
||||||
|
{
|
||||||
|
MOO_DEBUG0 (moo, "Cannot find the startup method in the system class");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MOO_OOP_TO_SMOOI(mth->tmpr_nargs) != 2)
|
||||||
|
{
|
||||||
|
MOO_DEBUG1 (moo, "Weird argument count %zd for a startup method - should be 2", MOO_OOP_TO_SMOOI(mth->tmpr_nargs));
|
||||||
|
moo_seterrnum (moo, MOO_EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* TODO: check if it's variadic.... it should be. and accept more than 2... */
|
||||||
|
|
||||||
|
moo_pushtmp (moo, (moo_oop_t*)&mth); tmp_count++;
|
||||||
|
s1 = moo_makesymbol (moo, objname->ptr, objname->len);
|
||||||
|
if (!s1)
|
||||||
|
{
|
||||||
|
moo_poptmps (moo, tmp_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
moo_pushtmp (moo, (moo_oop_t*)&s1);
|
||||||
|
s2 = moo_makesymbol (moo, mthname->ptr, mthname->len);
|
||||||
|
if (!s2)
|
||||||
|
{
|
||||||
|
moo_poptmps (moo, tmp_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
moo_pushtmp (moo, (moo_oop_t*)&s2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* create a fake initial context. */
|
||||||
|
ctx = (moo_oop_context_t)moo_instantiate (moo, moo->_method_context, MOO_NULL, MOO_OOP_TO_SMOOI(mth->tmpr_nargs));
|
||||||
|
if (!ctx)
|
||||||
|
{
|
||||||
|
moo_poptmps (moo, tmp_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
moo_pushtmp (moo, (moo_oop_t*)&ctx); tmp_count++;
|
||||||
|
|
||||||
|
|
||||||
/* TODO: handle preamble */
|
/* TODO: handle preamble */
|
||||||
|
|
||||||
/* the initial context starts the life of the entire VM
|
/* the initial context starts the life of the entire VM
|
||||||
@ -1184,17 +1253,20 @@ TODO: overcome this problem
|
|||||||
|
|
||||||
/* start_initial_process() calls the SWITCH_ACTIVE_CONTEXT() macro.
|
/* start_initial_process() calls the SWITCH_ACTIVE_CONTEXT() macro.
|
||||||
* the macro assumes a non-null value in moo->active_context.
|
* the macro assumes a non-null value in moo->active_context.
|
||||||
* let's force set active_context to ctx directly. */
|
* let's forcefully set active_context to ctx directly. */
|
||||||
moo->active_context = ctx;
|
moo->active_context = ctx;
|
||||||
|
|
||||||
moo_pushtmp (moo, (moo_oop_t*)&ctx);
|
|
||||||
moo_pushtmp (moo, (moo_oop_t*)&mth);
|
|
||||||
moo_pushtmp (moo, (moo_oop_t*)&ass);
|
|
||||||
proc = start_initial_process (moo, ctx);
|
proc = start_initial_process (moo, ctx);
|
||||||
moo_poptmps (moo, 3);
|
moo_poptmps (moo, tmp_count); tmp_count = 0;
|
||||||
if (!proc) return -1;
|
if (!proc) return -1;
|
||||||
|
|
||||||
|
#if defined(INVOKE_DIRECTLY)
|
||||||
MOO_STACK_PUSH (moo, ass->value); /* push the receiver - the object referenced by 'objname' */
|
MOO_STACK_PUSH (moo, ass->value); /* push the receiver - the object referenced by 'objname' */
|
||||||
|
#else
|
||||||
|
MOO_STACK_PUSH (moo, (moo_oop_t)moo->_system);
|
||||||
|
MOO_STACK_PUSH (moo, s1);
|
||||||
|
MOO_STACK_PUSH (moo, s2);
|
||||||
|
#endif
|
||||||
STORE_ACTIVE_SP (moo); /* moo->active_context->sp = MOO_SMOOI_TO_OOP(moo->sp) */
|
STORE_ACTIVE_SP (moo); /* moo->active_context->sp = MOO_SMOOI_TO_OOP(moo->sp) */
|
||||||
|
|
||||||
MOO_ASSERT (moo, moo->processor->active == proc);
|
MOO_ASSERT (moo, moo->processor->active == proc);
|
||||||
@ -1203,7 +1275,11 @@ TODO: overcome this problem
|
|||||||
MOO_ASSERT (moo, moo->active_context == ctx);
|
MOO_ASSERT (moo, moo->active_context == ctx);
|
||||||
|
|
||||||
/* emulate the message sending */
|
/* emulate the message sending */
|
||||||
|
#if defined(INVOKE_DIRECTLY)
|
||||||
return activate_new_method (moo, mth, 0);
|
return activate_new_method (moo, mth, 0);
|
||||||
|
#else
|
||||||
|
return activate_new_method (moo, mth, 2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@ -1642,6 +1718,22 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
|
|||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static moo_pfrc_t pf_add_to_be_finalized (moo_t* moo, moo_ooi_t nargs)
|
||||||
|
{
|
||||||
|
/* TODO: check if it has already been added */
|
||||||
|
moo_regfinalizable (moo, MOO_STACK_GETRCV(moo,nargs));
|
||||||
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static moo_pfrc_t pf_remove_to_be_finalized (moo_t* moo, moo_ooi_t nargs)
|
||||||
|
{
|
||||||
|
/* TODO: check if it has already been added */
|
||||||
|
moo_deregfinalizable (moo, MOO_STACK_GETRCV(moo,nargs));
|
||||||
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
|
static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
|
||||||
{
|
{
|
||||||
moo_oop_t rcv;
|
moo_oop_t rcv;
|
||||||
@ -2979,6 +3071,34 @@ static moo_pfrc_t pf_system_log (moo_t* moo, moo_ooi_t nargs)
|
|||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static moo_pfrc_t pf_system_pop_collectable (moo_t* moo, moo_ooi_t nargs)
|
||||||
|
{
|
||||||
|
if (moo->collectable.first)
|
||||||
|
{
|
||||||
|
moo_collectable_t* first;
|
||||||
|
|
||||||
|
first = moo->collectable.first;
|
||||||
|
|
||||||
|
/* TODO: if it's already fininalized, delete it from collectable */
|
||||||
|
MOO_ASSERT (moo, MOO_OOP_IS_POINTER(first->oop));
|
||||||
|
MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_GCFIN(first->oop) & MOO_GCFIN_FINALIZABLE);
|
||||||
|
|
||||||
|
MOO_STACK_SETRET (moo, nargs, first->oop);
|
||||||
|
MOO_OBJ_SET_FLAGS_GCFIN (first->oop, MOO_OBJ_GET_FLAGS_GCFIN(first->oop) | MOO_GCFIN_FINALIZED);
|
||||||
|
|
||||||
|
MOO_DEBUG1 (moo, "POPPING FINALIZABLE...%O\n", first->oop);
|
||||||
|
MOO_DELETE_FROM_LIST (&moo->collectable, first);
|
||||||
|
moo_freemem (moo, first);
|
||||||
|
|
||||||
|
MOO_DEBUG1 (moo, "POPPED FINALIZABLE...%p\n", moo->collectable.first);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT);
|
||||||
|
}
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static MOO_INLINE moo_pfrc_t _system_alloc (moo_t* moo, moo_ooi_t nargs, int clear)
|
static MOO_INLINE moo_pfrc_t _system_alloc (moo_t* moo, moo_ooi_t nargs, int clear)
|
||||||
{
|
{
|
||||||
moo_oop_t tmp;
|
moo_oop_t tmp;
|
||||||
@ -3209,7 +3329,6 @@ static MOO_INLINE int _store_raw_uint (moo_t* moo, moo_uint8_t* rawptr, moo_oow_
|
|||||||
int n;
|
int n;
|
||||||
moo_oow_t w, max;
|
moo_oow_t w, max;
|
||||||
|
|
||||||
|
|
||||||
if ((n = moo_inttooow (moo, voop, &w)) <= 0)
|
if ((n = moo_inttooow (moo, voop, &w)) <= 0)
|
||||||
{
|
{
|
||||||
if (n <= -1) moo_seterrnum (moo, MOO_ERANGE); /* negative number */
|
if (n <= -1) moo_seterrnum (moo, MOO_ERANGE); /* negative number */
|
||||||
@ -3793,6 +3912,7 @@ static pf_t pftab[] =
|
|||||||
{ "_integer_ge", { pf_integer_ge, 1, 1 } },
|
{ "_integer_ge", { pf_integer_ge, 1, 1 } },
|
||||||
{ "_integer_inttostr", { pf_integer_inttostr, 1, 1 } },
|
{ "_integer_inttostr", { pf_integer_inttostr, 1, 1 } },
|
||||||
|
|
||||||
|
{ "Apex_addToBeFinalized", { pf_add_to_be_finalized, 0, 0 } },
|
||||||
{ "Apex__basicNew", { pf_basic_new, 0, 0 } },
|
{ "Apex__basicNew", { pf_basic_new, 0, 0 } },
|
||||||
{ "Apex__basicNew:", { pf_basic_new, 1, 1 } },
|
{ "Apex__basicNew:", { pf_basic_new, 1, 1 } },
|
||||||
{ "Apex__basicSize", { pf_basic_size, 0, 0 } },
|
{ "Apex__basicSize", { pf_basic_size, 0, 0 } },
|
||||||
@ -3800,6 +3920,7 @@ static pf_t pftab[] =
|
|||||||
{ "Apex_basicNew:", { pf_basic_new, 1, 1 } },
|
{ "Apex_basicNew:", { pf_basic_new, 1, 1 } },
|
||||||
{ "Apex_basicSize", { pf_basic_size, 0, 0 } },
|
{ "Apex_basicSize", { pf_basic_size, 0, 0 } },
|
||||||
{ "Apex_class", { pf_class, 0, 0 } },
|
{ "Apex_class", { pf_class, 0, 0 } },
|
||||||
|
{ "Apex_removeToBeFinalized", { pf_remove_to_be_finalized, 0, 0 } },
|
||||||
|
|
||||||
{ "Character_asInteger", { pf_character_as_smooi, 0, 0 } },
|
{ "Character_asInteger", { pf_character_as_smooi, 0, 0 } },
|
||||||
|
|
||||||
@ -3851,6 +3972,7 @@ static pf_t pftab[] =
|
|||||||
{ "System__getUint64", { pf_system_get_uint64, 2, 2 } },
|
{ "System__getUint64", { pf_system_get_uint64, 2, 2 } },
|
||||||
{ "System__getUint8", { pf_system_get_uint8, 2, 2 } },
|
{ "System__getUint8", { pf_system_get_uint8, 2, 2 } },
|
||||||
{ "System__malloc", { pf_system_malloc, 1, 1 } },
|
{ "System__malloc", { pf_system_malloc, 1, 1 } },
|
||||||
|
{ "System__popCollectable", { pf_system_pop_collectable, 0, 0 } },
|
||||||
{ "System__putInt8", { pf_system_put_int8, 3, 3 } },
|
{ "System__putInt8", { pf_system_put_int8, 3, 3 } },
|
||||||
{ "System__putInt16", { pf_system_put_int16, 3, 3 } },
|
{ "System__putInt16", { pf_system_put_int16, 3, 3 } },
|
||||||
{ "System__putInt32", { pf_system_put_int32, 3, 3 } },
|
{ "System__putInt32", { pf_system_put_int32, 3, 3 } },
|
||||||
@ -3893,7 +4015,8 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
|
|||||||
moo_ooi_t /*sp,*/ stack_base;
|
moo_ooi_t /*sp,*/ stack_base;
|
||||||
|
|
||||||
#if defined(MOO_DEBUG_VM_EXEC)
|
#if defined(MOO_DEBUG_VM_EXEC)
|
||||||
moo_ooi_t fetched_instruction_pointer = 0; /* set it to a fake value */
|
/* set it to a fake value */
|
||||||
|
moo->last_instruction_pointer = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
preamble = MOO_OOP_TO_SMOOI(method->preamble);
|
preamble = MOO_OOP_TO_SMOOI(method->preamble);
|
||||||
@ -4441,7 +4564,8 @@ finalization:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int moo_execute (moo_t* moo)
|
|
||||||
|
static int __execute (moo_t* moo)
|
||||||
{
|
{
|
||||||
moo_oob_t bcode;
|
moo_oob_t bcode;
|
||||||
moo_oow_t b1, b2;
|
moo_oow_t b1, b2;
|
||||||
@ -4449,15 +4573,6 @@ 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)
|
|
||||||
moo_uintmax_t inst_counter = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MOO_DEBUG_VM_EXEC)
|
|
||||||
moo_ooi_t fetched_instruction_pointer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MOO_ASSERT (moo, moo->active_context != MOO_NULL);
|
MOO_ASSERT (moo, moo->active_context != MOO_NULL);
|
||||||
|
|
||||||
@ -4468,24 +4583,22 @@ int moo_execute (moo_t* moo)
|
|||||||
* these can be dirty if this function is called again esepcially after failure.
|
* these can be dirty if this function is called again esepcially after failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (vm_startup(moo) <= -1) goto oops;
|
|
||||||
vm_startup_called = 1;
|
|
||||||
|
|
||||||
moo->proc_switched = 0;
|
|
||||||
moo->abort_req = 0;
|
|
||||||
|
|
||||||
while (!moo->abort_req)
|
while (!moo->abort_req)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
if (moo->gc_finalization_pending)
|
||||||
|
switch_to_gc_process (xxxx);
|
||||||
|
else */
|
||||||
if (switch_process_if_needed(moo) == 0) break; /* no more runnable process */
|
if (switch_process_if_needed(moo) == 0) break; /* no more runnable process */
|
||||||
|
|
||||||
#if defined(MOO_DEBUG_VM_EXEC)
|
#if defined(MOO_DEBUG_VM_EXEC)
|
||||||
fetched_instruction_pointer = moo->ip;
|
moo->last_inst_pointer = moo->ip;
|
||||||
#endif
|
#endif
|
||||||
FETCH_BYTE_CODE_TO (moo, bcode);
|
FETCH_BYTE_CODE_TO (moo, bcode);
|
||||||
/*while (bcode == BCODE_NOOP) FETCH_BYTE_CODE_TO (moo, bcode);*/
|
/*while (bcode == BCODE_NOOP) FETCH_BYTE_CODE_TO (moo, bcode);*/
|
||||||
|
|
||||||
#if defined(MOO_PROFILE_VM)
|
#if defined(MOO_PROFILE_VM)
|
||||||
inst_counter++;
|
moo->inst_counter++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (bcode)
|
switch (bcode)
|
||||||
@ -5006,7 +5119,7 @@ int moo_execute (moo_t* moo)
|
|||||||
selector = (moo_oop_char_t)moo->active_method->slot[b2];
|
selector = (moo_oop_char_t)moo->active_method->slot[b2];
|
||||||
|
|
||||||
LOG_INST_3 (moo, "send_message%hs %zu @%zu", (((bcode >> 2) & 1)? "_to_super": ""), b1, b2);
|
LOG_INST_3 (moo, "send_message%hs %zu @%zu", (((bcode >> 2) & 1)? "_to_super": ""), b1, b2);
|
||||||
if (send_message (moo, selector, ((bcode >> 2) & 1), b1) <= -1) goto oops;
|
if (send_message (moo, selector, ((bcode >> 2) & 1), b1) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5110,7 +5223,7 @@ int moo_execute (moo_t* moo)
|
|||||||
*/
|
*/
|
||||||
MOO_STACK_PUSH (moo, (moo_oop_t)moo->_dictionary);
|
MOO_STACK_PUSH (moo, (moo_oop_t)moo->_dictionary);
|
||||||
MOO_STACK_PUSH (moo, MOO_SMOOI_TO_OOP(b1));
|
MOO_STACK_PUSH (moo, MOO_SMOOI_TO_OOP(b1));
|
||||||
if (send_message (moo, moo->dicnewsym, 0, 1) <= -1) goto oops;
|
if (send_message (moo, moo->dicnewsym, 0, 1) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCODE_POP_INTO_DICTIONARY:
|
case BCODE_POP_INTO_DICTIONARY:
|
||||||
@ -5124,7 +5237,7 @@ int moo_execute (moo_t* moo)
|
|||||||
t2 = MOO_STACK_GETTOP(moo);
|
t2 = MOO_STACK_GETTOP(moo);
|
||||||
moo_putatdic (moo, (moo_oop_dic_t)t2, ((moo_oop_association_t)t1)->key, ((moo_oop_association_t)t1)->value);
|
moo_putatdic (moo, (moo_oop_dic_t)t2, ((moo_oop_association_t)t1)->key, ((moo_oop_association_t)t1)->value);
|
||||||
*/
|
*/
|
||||||
if (send_message (moo, moo->dicputassocsym, 0, 1) <= -1) goto oops;
|
if (send_message (moo, moo->dicputassocsym, 0, 1) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCODE_MAKE_ARRAY:
|
case BCODE_MAKE_ARRAY:
|
||||||
@ -5136,7 +5249,7 @@ int moo_execute (moo_t* moo)
|
|||||||
|
|
||||||
/* create an empty array */
|
/* create an empty array */
|
||||||
t = moo_instantiate (moo, moo->_array, MOO_NULL, b1);
|
t = moo_instantiate (moo, moo->_array, MOO_NULL, b1);
|
||||||
if (!t) goto oops;
|
if (!t) return -1;
|
||||||
|
|
||||||
MOO_STACK_PUSH (moo, t); /* push the array created */
|
MOO_STACK_PUSH (moo, t); /* push the array created */
|
||||||
break;
|
break;
|
||||||
@ -5312,7 +5425,7 @@ int moo_execute (moo_t* moo)
|
|||||||
|
|
||||||
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_ERROR, "Error - cannot return from dead context\n");
|
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_ERROR, "Error - cannot return from dead context\n");
|
||||||
moo_seterrnum (moo, MOO_EINTERN); /* TODO: can i make this error catchable at the moo level? */
|
moo_seterrnum (moo, MOO_EINTERN); /* TODO: can i make this error catchable at the moo level? */
|
||||||
goto oops;
|
return -1;
|
||||||
|
|
||||||
non_local_return_ok:
|
non_local_return_ok:
|
||||||
/*MOO_DEBUG2 (moo, "NON_LOCAL RETURN OK TO... %p %p\n", moo->active_context->origin, moo->active_context->origin->sender);*/
|
/*MOO_DEBUG2 (moo, "NON_LOCAL RETURN OK TO... %p %p\n", moo->active_context->origin, moo->active_context->origin->sender);*/
|
||||||
@ -5349,7 +5462,7 @@ int moo_execute (moo_t* moo)
|
|||||||
MOO_STACK_PUSH (moo, (moo_oop_t)unwind_stop);
|
MOO_STACK_PUSH (moo, (moo_oop_t)unwind_stop);
|
||||||
MOO_STACK_PUSH (moo, (moo_oop_t)return_value);
|
MOO_STACK_PUSH (moo, (moo_oop_t)return_value);
|
||||||
|
|
||||||
if (send_message_with_str (moo, fbm, 16, 0, 2) <= -1) goto oops;
|
if (send_message_with_str (moo, fbm, 16, 0, 2) <= -1) return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -5376,9 +5489,14 @@ int moo_execute (moo_t* moo)
|
|||||||
MOO_ASSERT (moo, moo->sp == 0);
|
MOO_ASSERT (moo, moo->sp == 0);
|
||||||
|
|
||||||
if (moo->option.trait & MOO_AWAIT_PROCS)
|
if (moo->option.trait & MOO_AWAIT_PROCS)
|
||||||
|
{
|
||||||
terminate_process (moo, moo->processor->active);
|
terminate_process (moo, moo->processor->active);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* graceful termination of the whole vm */
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: store the return value to the VM register.
|
/* TODO: store the return value to the VM register.
|
||||||
* the caller to moo_execute() can fetch it to return it to the system */
|
* the caller to moo_execute() can fetch it to return it to the system */
|
||||||
@ -5442,7 +5560,7 @@ int moo_execute (moo_t* moo)
|
|||||||
* this base block context is created with no stack for
|
* this base block context is created with no stack for
|
||||||
* this reason */
|
* this reason */
|
||||||
blkctx = (moo_oop_context_t)moo_instantiate (moo, moo->_block_context, MOO_NULL, 0);
|
blkctx = (moo_oop_context_t)moo_instantiate (moo, moo->_block_context, MOO_NULL, 0);
|
||||||
if (!blkctx) goto oops;
|
if (!blkctx) return -1;
|
||||||
|
|
||||||
/* the long forward jump instruction has the format of
|
/* the long forward jump instruction has the format of
|
||||||
* 11000100 KKKKKKKK or 11000100 KKKKKKKK KKKKKKKK
|
* 11000100 KKKKKKKK or 11000100 KKKKKKKK KKKKKKKK
|
||||||
@ -5499,7 +5617,7 @@ int moo_execute (moo_t* moo)
|
|||||||
* this base block context is created with no
|
* this base block context is created with no
|
||||||
* stack for this reason. */
|
* stack for this reason. */
|
||||||
blkctx = (moo_oop_context_t)moo_instantiate (moo, moo->_block_context, MOO_NULL, 0);
|
blkctx = (moo_oop_context_t)moo_instantiate (moo, moo->_block_context, MOO_NULL, 0);
|
||||||
if (!blkctx) goto oops;
|
if (!blkctx) return -1;
|
||||||
|
|
||||||
/* get the receiver to the block copy message after block context instantiation
|
/* get the receiver to the block copy message after block context instantiation
|
||||||
* not to get affected by potential GC */
|
* not to get affected by potential GC */
|
||||||
@ -5566,20 +5684,37 @@ int moo_execute (moo_t* moo)
|
|||||||
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_seterrnum (moo, MOO_EINTERN);
|
moo_seterrnum (moo, MOO_EINTERN);
|
||||||
goto oops;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
vm_cleanup (moo);
|
|
||||||
#if defined(MOO_PROFILE_VM)
|
|
||||||
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_INFO, "TOTAL_INST_COUTNER = %zu\n", inst_counter);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
oops:
|
|
||||||
if (vm_startup_called) vm_cleanup (moo);
|
int moo_execute (moo_t* moo)
|
||||||
return -1;
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
#if defined(MOO_PROFILE_VM)
|
||||||
|
moo->inst_counter = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (vm_startup(moo) <= -1) return -1;
|
||||||
|
|
||||||
|
moo->proc_switched = 0;
|
||||||
|
moo->abort_req = 0;
|
||||||
|
|
||||||
|
n = __execute (moo);
|
||||||
|
|
||||||
|
vm_cleanup (moo);
|
||||||
|
|
||||||
|
#if defined(MOO_PROFILE_VM)
|
||||||
|
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_INFO, "TOTAL_INST_COUTNER = %zu\n", moo->inst_counter);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void moo_abort (moo_t* moo)
|
void moo_abort (moo_t* moo)
|
||||||
|
102
moo/lib/gc.c
102
moo/lib/gc.c
@ -117,6 +117,9 @@ static kernel_class_info_t kernel_classes[] =
|
|||||||
{ 6, { 'S','y','s','t','e','m' }, MOO_OFFSETOF(moo_t, _system) },
|
{ 6, { 'S','y','s','t','e','m' }, MOO_OFFSETOF(moo_t, _system) },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void move_finalizable_objects (moo_t* moo);
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
* BOOTSTRAPPER
|
* BOOTSTRAPPER
|
||||||
* ----------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------- */
|
||||||
@ -701,6 +704,11 @@ void moo_gc (moo_t* moo)
|
|||||||
ptr = (moo_uint8_t*) MOO_ALIGN ((moo_uintptr_t)moo->newheap->base, MOO_SIZEOF(moo_oop_t));
|
ptr = (moo_uint8_t*) MOO_ALIGN ((moo_uintptr_t)moo->newheap->base, MOO_SIZEOF(moo_oop_t));
|
||||||
ptr = scan_new_heap (moo, ptr);
|
ptr = scan_new_heap (moo, ptr);
|
||||||
|
|
||||||
|
/* FINALIZATION */
|
||||||
|
move_finalizable_objects (moo);
|
||||||
|
ptr = scan_new_heap (moo, ptr);
|
||||||
|
/* END FINALIZATION */
|
||||||
|
|
||||||
/* traverse the symbol table for unreferenced symbols.
|
/* traverse the symbol table for unreferenced symbols.
|
||||||
* if the symbol has not moved to the new heap, the symbol
|
* if the symbol has not moved to the new heap, the symbol
|
||||||
* is not referenced by any other objects than the symbol
|
* is not referenced by any other objects than the symbol
|
||||||
@ -809,3 +817,97 @@ moo_oop_t moo_shallowcopy (moo_t* moo, moo_oop_t oop)
|
|||||||
|
|
||||||
return oop;
|
return oop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int moo_regfinalizable (moo_t* moo, moo_oop_t oop)
|
||||||
|
{
|
||||||
|
moo_collectable_t* x;
|
||||||
|
|
||||||
|
MOO_DEBUG1 (moo, "ADDING FINALIZABLE... %O\n", oop);
|
||||||
|
if (!MOO_OOP_IS_POINTER(oop) ||
|
||||||
|
(MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)))
|
||||||
|
{
|
||||||
|
moo_seterrnum (moo, MOO_EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = moo_allocmem (moo, MOO_SIZEOF(*x));
|
||||||
|
if (!x) return -1;
|
||||||
|
|
||||||
|
MOO_OBJ_SET_FLAGS_GCFIN (oop, MOO_GCFIN_FINALIZABLE);
|
||||||
|
x->oop = oop;
|
||||||
|
|
||||||
|
MOO_APPEND_TO_LIST (&moo->finalizable, x);
|
||||||
|
|
||||||
|
MOO_DEBUG1 (moo, "ADDED FINALIZABLE... %O\n", oop);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int moo_deregfinalizable (moo_t* moo, moo_oop_t oop)
|
||||||
|
{
|
||||||
|
moo_collectable_t* x;
|
||||||
|
|
||||||
|
if (!MOO_OOP_IS_POINTER(oop) ||
|
||||||
|
((MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) != MOO_GCFIN_FINALIZABLE))
|
||||||
|
{
|
||||||
|
moo_seterrnum (moo, MOO_EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = moo->finalizable.first;
|
||||||
|
while (x)
|
||||||
|
{
|
||||||
|
if (x->oop == oop)
|
||||||
|
{
|
||||||
|
/* TODO: do i need to clear other flags like GC */
|
||||||
|
MOO_OBJ_SET_FLAGS_GCFIN(oop, (MOO_OBJ_GET_FLAGS_GCFIN(oop) & ~MOO_GCFIN_FINALIZABLE));
|
||||||
|
MOO_DELETE_FROM_LIST (&moo->finalizable, x);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moo_seterrnum (moo, MOO_ENOENT);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void move_finalizable_objects (moo_t* moo)
|
||||||
|
{
|
||||||
|
moo_collectable_t* x, * y;
|
||||||
|
|
||||||
|
for (x = moo->collectable.first; x; x = x->next)
|
||||||
|
{
|
||||||
|
x->oop = moo_moveoop (moo, x->oop);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = moo->finalizable.first; x; )
|
||||||
|
{
|
||||||
|
y = x->next;
|
||||||
|
|
||||||
|
if (!MOO_OBJ_GET_FLAGS_MOVED(x->oop))
|
||||||
|
{
|
||||||
|
/* TODO: if already finalized, don't move, don't add to collectable
|
||||||
|
if (MOVE_OBJ_GET_FLAGS_FINALIZED(x->oop)) continue;
|
||||||
|
* */
|
||||||
|
x->oop = moo_moveoop (moo, x->oop);
|
||||||
|
|
||||||
|
/* it's almost collectable. but don't collect it yet.
|
||||||
|
* if garbages consist of finalizable objects only, GC should fail miserably */
|
||||||
|
|
||||||
|
/* remove it from the finalizable list */
|
||||||
|
MOO_DELETE_FROM_LIST (&moo->finalizable, x);
|
||||||
|
|
||||||
|
/* add it to the collectable list */
|
||||||
|
MOO_APPEND_TO_LIST (&moo->collectable, x);
|
||||||
|
|
||||||
|
//signal_semaphore (moo, moo->collectable_semaphore);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x->oop = moo_moveoop (moo, x->oop);
|
||||||
|
}
|
||||||
|
|
||||||
|
x = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1106,6 +1106,13 @@ moo_oop_nsdic_t moo_makensdic (
|
|||||||
moo_oow_t size
|
moo_oow_t size
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* gc.c */
|
||||||
|
/* ========================================================================= */
|
||||||
|
int moo_regfinalizable (moo_t* moo, moo_oop_t oop);
|
||||||
|
int moo_deregfinalizable (moo_t* moo, moo_oop_t oop);
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
/* proc.c */
|
/* proc.c */
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
@ -29,6 +29,34 @@
|
|||||||
|
|
||||||
#include "moo-cmn.h"
|
#include "moo-cmn.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
* DOUBLY LINKED LIST MACROS
|
||||||
|
* ----------------------------------------------------------------------- */
|
||||||
|
#define MOO_APPEND_TO_LIST(list, node) do { \
|
||||||
|
(node)->next = MOO_NULL; \
|
||||||
|
(node)->prev = (list)->last; \
|
||||||
|
if ((list)->first) (list)->last->next = (node); \
|
||||||
|
else (list)->first = (node); \
|
||||||
|
(list)->last = (node); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define MOO_PREPPEND_TO_LIST(list, node) do { \
|
||||||
|
(node)->prev = MOO_NULL; \
|
||||||
|
(node)->next = (list)->first; \
|
||||||
|
if ((list)->last) (list)->first->prev = (node); \
|
||||||
|
else (list)->last = (node); \
|
||||||
|
(list)->first = (node); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define MOO_DELETE_FROM_LIST(list, node) do { \
|
||||||
|
if ((node)->prev) (node)->prev->next = (node)->next; \
|
||||||
|
else (list)->first = (node)->next; \
|
||||||
|
if ((node)->next) (node)->next->prev = (node)->prev; \
|
||||||
|
else (list)->last = (node)->prev; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -311,6 +311,13 @@ enum moo_obj_type_t
|
|||||||
};
|
};
|
||||||
typedef enum moo_obj_type_t moo_obj_type_t;
|
typedef enum moo_obj_type_t moo_obj_type_t;
|
||||||
|
|
||||||
|
enum moo_gcfin_t
|
||||||
|
{
|
||||||
|
MOO_GCFIN_FINALIZABLE = (1 << 0),
|
||||||
|
MOO_GCFIN_FINALIZED = (1 << 1)
|
||||||
|
};
|
||||||
|
typedef enum moo_gcfin_t moo_gcfin_t;
|
||||||
|
|
||||||
/* =========================================================================
|
/* =========================================================================
|
||||||
* Object header structure
|
* Object header structure
|
||||||
*
|
*
|
||||||
@ -330,6 +337,7 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
|||||||
* moved: 0 or 1. used by GC. internal use only.
|
* moved: 0 or 1. used by GC. internal use only.
|
||||||
* ngc: 0 or 1, used by GC. internal use only.
|
* ngc: 0 or 1, used by GC. internal use only.
|
||||||
* rdonly: 0 or 1. indicates that an object is immutable.
|
* rdonly: 0 or 1. indicates that an object is immutable.
|
||||||
|
* gcfin: represents finalzation state.
|
||||||
* trailer: 0 or 1. indicates that there are trailing bytes
|
* trailer: 0 or 1. indicates that there are trailing bytes
|
||||||
* after the object payload. internal use only.
|
* after the object payload. internal use only.
|
||||||
*
|
*
|
||||||
@ -365,6 +373,7 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
|||||||
#define MOO_OBJ_FLAGS_MOVED_BITS 1
|
#define MOO_OBJ_FLAGS_MOVED_BITS 1
|
||||||
#define MOO_OBJ_FLAGS_NGC_BITS 1
|
#define MOO_OBJ_FLAGS_NGC_BITS 1
|
||||||
#define MOO_OBJ_FLAGS_RDONLY_BITS 1
|
#define MOO_OBJ_FLAGS_RDONLY_BITS 1
|
||||||
|
#define MOO_OBJ_FLAGS_GCFIN_BITS 2
|
||||||
#define MOO_OBJ_FLAGS_TRAILER_BITS 1
|
#define MOO_OBJ_FLAGS_TRAILER_BITS 1
|
||||||
|
|
||||||
#define MOO_OBJ_FLAGS_TYPE_SHIFT (MOO_OBJ_FLAGS_UNIT_BITS + MOO_OBJ_FLAGS_UNIT_SHIFT)
|
#define MOO_OBJ_FLAGS_TYPE_SHIFT (MOO_OBJ_FLAGS_UNIT_BITS + MOO_OBJ_FLAGS_UNIT_SHIFT)
|
||||||
@ -373,7 +382,8 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
|||||||
#define MOO_OBJ_FLAGS_KERNEL_SHIFT (MOO_OBJ_FLAGS_MOVED_BITS + MOO_OBJ_FLAGS_MOVED_SHIFT)
|
#define MOO_OBJ_FLAGS_KERNEL_SHIFT (MOO_OBJ_FLAGS_MOVED_BITS + MOO_OBJ_FLAGS_MOVED_SHIFT)
|
||||||
#define MOO_OBJ_FLAGS_MOVED_SHIFT (MOO_OBJ_FLAGS_NGC_BITS + MOO_OBJ_FLAGS_NGC_SHIFT)
|
#define MOO_OBJ_FLAGS_MOVED_SHIFT (MOO_OBJ_FLAGS_NGC_BITS + MOO_OBJ_FLAGS_NGC_SHIFT)
|
||||||
#define MOO_OBJ_FLAGS_NGC_SHIFT (MOO_OBJ_FLAGS_RDONLY_BITS + MOO_OBJ_FLAGS_RDONLY_SHIFT)
|
#define MOO_OBJ_FLAGS_NGC_SHIFT (MOO_OBJ_FLAGS_RDONLY_BITS + MOO_OBJ_FLAGS_RDONLY_SHIFT)
|
||||||
#define MOO_OBJ_FLAGS_RDONLY_SHIFT (MOO_OBJ_FLAGS_TRAILER_BITS + MOO_OBJ_FLAGS_TRAILER_SHIFT)
|
#define MOO_OBJ_FLAGS_RDONLY_SHIFT (MOO_OBJ_FLAGS_GCFIN_BITS + MOO_OBJ_FLAGS_GCFIN_SHIFT)
|
||||||
|
#define MOO_OBJ_FLAGS_GCFIN_SHIFT (MOO_OBJ_FLAGS_TRAILER_BITS + MOO_OBJ_FLAGS_TRAILER_SHIFT)
|
||||||
#define MOO_OBJ_FLAGS_TRAILER_SHIFT (0)
|
#define MOO_OBJ_FLAGS_TRAILER_SHIFT (0)
|
||||||
|
|
||||||
#define MOO_OBJ_GET_FLAGS_TYPE(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT, MOO_OBJ_FLAGS_TYPE_BITS)
|
#define MOO_OBJ_GET_FLAGS_TYPE(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT, MOO_OBJ_FLAGS_TYPE_BITS)
|
||||||
@ -383,6 +393,7 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
|||||||
#define MOO_OBJ_GET_FLAGS_MOVED(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT, MOO_OBJ_FLAGS_MOVED_BITS)
|
#define MOO_OBJ_GET_FLAGS_MOVED(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT, MOO_OBJ_FLAGS_MOVED_BITS)
|
||||||
#define MOO_OBJ_GET_FLAGS_NGC(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT, MOO_OBJ_FLAGS_NGC_BITS)
|
#define MOO_OBJ_GET_FLAGS_NGC(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT, MOO_OBJ_FLAGS_NGC_BITS)
|
||||||
#define MOO_OBJ_GET_FLAGS_RDONLY(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT, MOO_OBJ_FLAGS_RDONLY_BITS)
|
#define MOO_OBJ_GET_FLAGS_RDONLY(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT, MOO_OBJ_FLAGS_RDONLY_BITS)
|
||||||
|
#define MOO_OBJ_GET_FLAGS_GCFIN(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_GCFIN_SHIFT, MOO_OBJ_FLAGS_GCFIN_BITS)
|
||||||
#define MOO_OBJ_GET_FLAGS_TRAILER(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS)
|
#define MOO_OBJ_GET_FLAGS_TRAILER(oop) MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS)
|
||||||
|
|
||||||
#define MOO_OBJ_SET_FLAGS_TYPE(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT, MOO_OBJ_FLAGS_TYPE_BITS, v)
|
#define MOO_OBJ_SET_FLAGS_TYPE(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT, MOO_OBJ_FLAGS_TYPE_BITS, v)
|
||||||
@ -392,6 +403,7 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
|||||||
#define MOO_OBJ_SET_FLAGS_MOVED(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT, MOO_OBJ_FLAGS_MOVED_BITS, v)
|
#define MOO_OBJ_SET_FLAGS_MOVED(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT, MOO_OBJ_FLAGS_MOVED_BITS, v)
|
||||||
#define MOO_OBJ_SET_FLAGS_NGC(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT, MOO_OBJ_FLAGS_NGC_BITS, v)
|
#define MOO_OBJ_SET_FLAGS_NGC(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT, MOO_OBJ_FLAGS_NGC_BITS, v)
|
||||||
#define MOO_OBJ_SET_FLAGS_RDONLY(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT, MOO_OBJ_FLAGS_RDONLY_BITS, v)
|
#define MOO_OBJ_SET_FLAGS_RDONLY(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT, MOO_OBJ_FLAGS_RDONLY_BITS, v)
|
||||||
|
#define MOO_OBJ_SET_FLAGS_GCFIN(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_GCFIN_SHIFT, MOO_OBJ_FLAGS_GCFIN_BITS, v)
|
||||||
#define MOO_OBJ_SET_FLAGS_TRAILER(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS, v)
|
#define MOO_OBJ_SET_FLAGS_TRAILER(oop,v) MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS, v)
|
||||||
|
|
||||||
#define MOO_OBJ_GET_SIZE(oop) ((oop)->_size)
|
#define MOO_OBJ_GET_SIZE(oop) ((oop)->_size)
|
||||||
@ -989,6 +1001,14 @@ struct moo_sbuf_t
|
|||||||
};
|
};
|
||||||
typedef struct moo_sbuf_t moo_sbuf_t;
|
typedef struct moo_sbuf_t moo_sbuf_t;
|
||||||
|
|
||||||
|
typedef struct moo_collectable_t moo_collectable_t;
|
||||||
|
struct moo_collectable_t
|
||||||
|
{
|
||||||
|
moo_oop_t oop;
|
||||||
|
moo_collectable_t* prev;
|
||||||
|
moo_collectable_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
/* special callback to be called for trailer */
|
/* special callback to be called for trailer */
|
||||||
typedef void (*moo_trgc_t) (moo_t* moo, moo_oop_t obj);
|
typedef void (*moo_trgc_t) (moo_t* moo, moo_oop_t obj);
|
||||||
|
|
||||||
@ -1156,6 +1176,21 @@ struct moo_t
|
|||||||
|
|
||||||
moo_sbuf_t sbuf[64];
|
moo_sbuf_t sbuf[64];
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
moo_collectable_t* first;
|
||||||
|
moo_collectable_t* last;
|
||||||
|
} collectable;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
moo_collectable_t* first;
|
||||||
|
moo_collectable_t* last;
|
||||||
|
} finalizable;
|
||||||
|
|
||||||
|
moo_uintmax_t inst_counter;
|
||||||
|
moo_ooi_t last_inst_pointer;
|
||||||
|
|
||||||
#if defined(MOO_INCLUDE_COMPILER)
|
#if defined(MOO_INCLUDE_COMPILER)
|
||||||
moo_compiler_t* c;
|
moo_compiler_t* c;
|
||||||
#endif
|
#endif
|
||||||
|
@ -163,6 +163,7 @@ oops:
|
|||||||
static moo_pfrc_t pf_close_display (moo_t* moo, moo_ooi_t nargs)
|
static moo_pfrc_t pf_close_display (moo_t* moo, moo_ooi_t nargs)
|
||||||
{
|
{
|
||||||
oop_x11_t x11;
|
oop_x11_t x11;
|
||||||
|
x11_trailer_t* tr;
|
||||||
|
|
||||||
// TODO: CHECK if the receiver is an X11 object
|
// TODO: CHECK if the receiver is an X11 object
|
||||||
|
|
||||||
@ -174,6 +175,14 @@ static moo_pfrc_t pf_close_display (moo_t* moo, moo_ooi_t nargs)
|
|||||||
x11->display = moo->_nil;
|
x11->display = moo->_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tr = moo_getobjtrailer (moo, MOO_STACK_GETRCV(moo,nargs), MOO_NULL);
|
||||||
|
if (tr->event)
|
||||||
|
{
|
||||||
|
moo_freemem (moo, tr->event);
|
||||||
|
tr->event = MOO_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
MOO_STACK_SETRETTORCV (moo, nargs);
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user