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 }
|
||||
}
|
||||
|
||||
(* ------------------------------------------------------------------
|
||||
* FINALIZATION SUPPORT
|
||||
* ------------------------------------------------------------------ *)
|
||||
method(#dual,#primitive) addToBeFinalized.
|
||||
##method(#dual,#primitive) removeToBeFinalized.
|
||||
|
||||
(* ------------------------------------------------------------------
|
||||
* HASHING
|
||||
* ------------------------------------------------------------------ *)
|
||||
|
@ -10,6 +10,45 @@
|
||||
|
||||
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
|
||||
|
@ -300,10 +300,13 @@ class X11.Widget(Object)
|
||||
|
||||
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
|
||||
{
|
||||
| gc |
|
||||
System logNl: 'LABEL GC...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'.
|
||||
|
||||
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';
|
||||
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 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).
|
||||
] 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)
|
||||
{
|
||||
var children.
|
||||
@ -646,8 +671,9 @@ extend X11
|
||||
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
|
||||
@ -664,8 +690,9 @@ extend X11
|
||||
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
|
||||
@ -675,7 +702,18 @@ extend X11
|
||||
}
|
||||
|
||||
|
||||
class Fx(Object)
|
||||
{
|
||||
method initialize
|
||||
{
|
||||
self addToBeFinalized.
|
||||
}
|
||||
|
||||
method finalize
|
||||
{
|
||||
System logNl: 'Greate... FX instance finalized'.
|
||||
}
|
||||
}
|
||||
|
||||
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: '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: '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.shell3 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.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||
self.shell1 realize.
|
||||
self.shell2 realize.
|
||||
self.shell3 realize.
|
||||
|
||||
self.disp1 enterEventLoop. ## this is not a blocking call. it spawns another process.
|
||||
self.disp2 enterEventLoop.
|
||||
|
||||
|
||||
|
||||
comp1 := Fx new.
|
||||
Fx new.
|
||||
Fx new.
|
||||
Fx new.
|
||||
}
|
||||
|
||||
method(#class) main
|
||||
|
@ -4354,7 +4354,7 @@ static int compile_block_expression (moo_t* moo)
|
||||
{
|
||||
colon_loc = moo->c->tok.loc;
|
||||
|
||||
/* block temporary variables */
|
||||
/* block temporary variables - argument to blocks */
|
||||
do
|
||||
{
|
||||
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)
|
||||
|
||||
/* 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_1(moo,fmt,a1) MOO_LOG2(moo, LOG_MASK_INST, " %06zd " fmt "\n",fetched_instruction_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_3(moo,fmt,a1,a2,a3) MOO_LOG4(moo, LOG_MASK_INST, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3)
|
||||
# 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",(moo)->last_inst_pointer, a1)
|
||||
# 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", (moo)->last_inst_pointer, a1, a2, a3)
|
||||
#else
|
||||
# define LOG_INST_0(moo,fmt)
|
||||
# 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)
|
||||
{
|
||||
MOO_DEBUG0 (moo, "VM started up\n");
|
||||
if (moo->vmprim.vm_startup (moo) <= -1) return -1;
|
||||
moo->vmprim.vm_gettime (moo, &moo->exec_start_time); /* raw time. no adjustment */
|
||||
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_cleanup (moo);
|
||||
MOO_DEBUG0 (moo, "VM cleaned up\n");
|
||||
}
|
||||
|
||||
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(). */
|
||||
|
||||
/* detach a process from a semaphore waiting list and
|
||||
/* detach a process from a semaphore's waiting list and
|
||||
* make it runnable */
|
||||
unchain_from_semaphore (moo, proc);
|
||||
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
|
||||
*/
|
||||
moo_oop_context_t ctx;
|
||||
moo_oop_association_t ass;
|
||||
moo_oop_method_t mth;
|
||||
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;
|
||||
|
||||
/* create a fake initial context. */
|
||||
ctx = (moo_oop_context_t)moo_instantiate (moo, moo->_method_context, MOO_NULL, 0);
|
||||
if (!ctx) return -1;
|
||||
moo_oocs_t startup;
|
||||
static moo_ooch_t str_startup[] = { 's', 't', 'a', 'r', 't', 'u', 'p' };
|
||||
|
||||
#if defined(INVOKE_DIRECTLY)
|
||||
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
/* this method expects more than 0 arguments.
|
||||
* 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);
|
||||
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 */
|
||||
|
||||
/* 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.
|
||||
* 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_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);
|
||||
moo_poptmps (moo, 3);
|
||||
moo_poptmps (moo, tmp_count); tmp_count = 0;
|
||||
if (!proc) return -1;
|
||||
|
||||
#if defined(INVOKE_DIRECTLY)
|
||||
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) */
|
||||
|
||||
MOO_ASSERT (moo, moo->processor->active == proc);
|
||||
@ -1203,7 +1275,11 @@ TODO: overcome this problem
|
||||
MOO_ASSERT (moo, moo->active_context == ctx);
|
||||
|
||||
/* emulate the message sending */
|
||||
#if defined(INVOKE_DIRECTLY)
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
moo_oop_t tmp;
|
||||
@ -3208,7 +3328,6 @@ static MOO_INLINE int _store_raw_uint (moo_t* moo, moo_uint8_t* rawptr, moo_oow_
|
||||
{
|
||||
int n;
|
||||
moo_oow_t w, max;
|
||||
|
||||
|
||||
if ((n = moo_inttooow (moo, voop, &w)) <= 0)
|
||||
{
|
||||
@ -3793,6 +3912,7 @@ static pf_t pftab[] =
|
||||
{ "_integer_ge", { pf_integer_ge, 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, 1, 1 } },
|
||||
{ "Apex__basicSize", { pf_basic_size, 0, 0 } },
|
||||
@ -3800,6 +3920,7 @@ static pf_t pftab[] =
|
||||
{ "Apex_basicNew:", { pf_basic_new, 1, 1 } },
|
||||
{ "Apex_basicSize", { pf_basic_size, 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 } },
|
||||
|
||||
@ -3851,6 +3972,7 @@ static pf_t pftab[] =
|
||||
{ "System__getUint64", { pf_system_get_uint64, 2, 2 } },
|
||||
{ "System__getUint8", { pf_system_get_uint8, 2, 2 } },
|
||||
{ "System__malloc", { pf_system_malloc, 1, 1 } },
|
||||
{ "System__popCollectable", { pf_system_pop_collectable, 0, 0 } },
|
||||
{ "System__putInt8", { pf_system_put_int8, 3, 3 } },
|
||||
{ "System__putInt16", { pf_system_put_int16, 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;
|
||||
|
||||
#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
|
||||
|
||||
preamble = MOO_OOP_TO_SMOOI(method->preamble);
|
||||
@ -4441,7 +4564,8 @@ finalization:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int moo_execute (moo_t* moo)
|
||||
|
||||
static int __execute (moo_t* moo)
|
||||
{
|
||||
moo_oob_t bcode;
|
||||
moo_oow_t b1, b2;
|
||||
@ -4449,15 +4573,6 @@ int moo_execute (moo_t* moo)
|
||||
int unwind_protect;
|
||||
moo_oop_context_t unwind_start;
|
||||
moo_oop_context_t unwind_stop;
|
||||
int vm_startup_called = 0;
|
||||
|
||||
#if defined(MOO_PROFILE_VM)
|
||||
moo_uintmax_t inst_counter = 0;
|
||||
#endif
|
||||
|
||||
#if defined(MOO_DEBUG_VM_EXEC)
|
||||
moo_ooi_t fetched_instruction_pointer;
|
||||
#endif
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
if (vm_startup(moo) <= -1) goto oops;
|
||||
vm_startup_called = 1;
|
||||
|
||||
moo->proc_switched = 0;
|
||||
moo->abort_req = 0;
|
||||
|
||||
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 defined(MOO_DEBUG_VM_EXEC)
|
||||
fetched_instruction_pointer = moo->ip;
|
||||
moo->last_inst_pointer = moo->ip;
|
||||
#endif
|
||||
FETCH_BYTE_CODE_TO (moo, bcode);
|
||||
/*while (bcode == BCODE_NOOP) FETCH_BYTE_CODE_TO (moo, bcode);*/
|
||||
|
||||
#if defined(MOO_PROFILE_VM)
|
||||
inst_counter++;
|
||||
moo->inst_counter++;
|
||||
#endif
|
||||
|
||||
switch (bcode)
|
||||
@ -5006,7 +5119,7 @@ int moo_execute (moo_t* moo)
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -5110,7 +5223,7 @@ int moo_execute (moo_t* moo)
|
||||
*/
|
||||
MOO_STACK_PUSH (moo, (moo_oop_t)moo->_dictionary);
|
||||
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;
|
||||
|
||||
case BCODE_POP_INTO_DICTIONARY:
|
||||
@ -5124,7 +5237,7 @@ int moo_execute (moo_t* 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);
|
||||
*/
|
||||
if (send_message (moo, moo->dicputassocsym, 0, 1) <= -1) goto oops;
|
||||
if (send_message (moo, moo->dicputassocsym, 0, 1) <= -1) return -1;
|
||||
break;
|
||||
|
||||
case BCODE_MAKE_ARRAY:
|
||||
@ -5136,7 +5249,7 @@ int moo_execute (moo_t* moo)
|
||||
|
||||
/* create an empty array */
|
||||
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 */
|
||||
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_seterrnum (moo, MOO_EINTERN); /* TODO: can i make this error catchable at the moo level? */
|
||||
goto oops;
|
||||
return -1;
|
||||
|
||||
non_local_return_ok:
|
||||
/*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)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
|
||||
{
|
||||
@ -5376,9 +5489,14 @@ int moo_execute (moo_t* moo)
|
||||
MOO_ASSERT (moo, moo->sp == 0);
|
||||
|
||||
if (moo->option.trait & MOO_AWAIT_PROCS)
|
||||
{
|
||||
terminate_process (moo, moo->processor->active);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* graceful termination of the whole vm */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* TODO: store the return value to the VM register.
|
||||
* 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 reason */
|
||||
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
|
||||
* 11000100 KKKKKKKK or 11000100 KKKKKKKK KKKKKKKK
|
||||
@ -5499,7 +5617,7 @@ int moo_execute (moo_t* moo)
|
||||
* this base block context is created with no
|
||||
* stack for this reason. */
|
||||
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
|
||||
* not to get affected by potential GC */
|
||||
@ -5566,20 +5684,37 @@ int moo_execute (moo_t* moo)
|
||||
default:
|
||||
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Fatal error - unknown byte code 0x%zx\n", bcode);
|
||||
moo_seterrnum (moo, MOO_EINTERN);
|
||||
goto oops;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
oops:
|
||||
if (vm_startup_called) vm_cleanup (moo);
|
||||
return -1;
|
||||
|
||||
int moo_execute (moo_t* moo)
|
||||
{
|
||||
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)
|
||||
|
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) },
|
||||
};
|
||||
|
||||
|
||||
static void move_finalizable_objects (moo_t* moo);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* 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 = 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.
|
||||
* if the symbol has not moved to the new heap, 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
/* gc.c */
|
||||
/* ========================================================================= */
|
||||
int moo_regfinalizable (moo_t* moo, moo_oop_t oop);
|
||||
int moo_deregfinalizable (moo_t* moo, moo_oop_t oop);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* proc.c */
|
||||
/* ========================================================================= */
|
||||
|
@ -29,6 +29,34 @@
|
||||
|
||||
#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)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -311,6 +311,13 @@ enum 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
|
||||
*
|
||||
@ -330,6 +337,7 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
||||
* moved: 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.
|
||||
* gcfin: represents finalzation state.
|
||||
* trailer: 0 or 1. indicates that there are trailing bytes
|
||||
* after the object payload. internal use only.
|
||||
*
|
||||
@ -358,14 +366,15 @@ typedef enum moo_obj_type_t moo_obj_type_t;
|
||||
* size calculation and the access to the payload fields become more complex.
|
||||
* Therefore, i've dropped the idea.
|
||||
* ========================================================================= */
|
||||
#define MOO_OBJ_FLAGS_TYPE_BITS 6
|
||||
#define MOO_OBJ_FLAGS_UNIT_BITS 5
|
||||
#define MOO_OBJ_FLAGS_EXTRA_BITS 1
|
||||
#define MOO_OBJ_FLAGS_KERNEL_BITS 2
|
||||
#define MOO_OBJ_FLAGS_MOVED_BITS 1
|
||||
#define MOO_OBJ_FLAGS_NGC_BITS 1
|
||||
#define MOO_OBJ_FLAGS_RDONLY_BITS 1
|
||||
#define MOO_OBJ_FLAGS_TRAILER_BITS 1
|
||||
#define MOO_OBJ_FLAGS_TYPE_BITS 6
|
||||
#define MOO_OBJ_FLAGS_UNIT_BITS 5
|
||||
#define MOO_OBJ_FLAGS_EXTRA_BITS 1
|
||||
#define MOO_OBJ_FLAGS_KERNEL_BITS 2
|
||||
#define MOO_OBJ_FLAGS_MOVED_BITS 1
|
||||
#define MOO_OBJ_FLAGS_NGC_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_TYPE_SHIFT (MOO_OBJ_FLAGS_UNIT_BITS + MOO_OBJ_FLAGS_UNIT_SHIFT)
|
||||
#define MOO_OBJ_FLAGS_UNIT_SHIFT (MOO_OBJ_FLAGS_EXTRA_BITS + MOO_OBJ_FLAGS_EXTRA_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_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_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_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_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_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_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_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_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_GET_SIZE(oop) ((oop)->_size)
|
||||
@ -989,6 +1001,14 @@ struct 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 */
|
||||
typedef void (*moo_trgc_t) (moo_t* moo, moo_oop_t obj);
|
||||
|
||||
@ -1156,6 +1176,21 @@ struct moo_t
|
||||
|
||||
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)
|
||||
moo_compiler_t* c;
|
||||
#endif
|
||||
|
@ -163,6 +163,7 @@ oops:
|
||||
static moo_pfrc_t pf_close_display (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
oop_x11_t x11;
|
||||
x11_trailer_t* tr;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user