enhanced finalization handling further

This commit is contained in:
hyunghwan.chung 2017-07-21 16:54:43 +00:00
parent 03fd02d59b
commit 7412ae0dac
7 changed files with 185 additions and 131 deletions

View File

@ -42,8 +42,8 @@ class(#pointer,#final,#limited) Process(Object)
## the process must not be scheduled. ## the process must not be scheduled.
## ---------------------------------------------------------------------------------------------------------- ## ----------------------------------------------------------------------------------------------------------
##(Processor activeProcess ~~ self) ifTrue: [ self _suspend ]. ##if (Processor activeProcess ~~ self) { self _suspend }.
(thisProcess ~~ self) ifTrue: [ self _suspend ]. if (thisProcess ~~ self) { self _suspend }.
self.current_context unwindTo: self.initial_context return: nil. self.current_context unwindTo: self.initial_context return: nil.
^self _terminate ^self _terminate
} }
@ -68,7 +68,7 @@ class Semaphore(Object)
fireTimeSec := 0, fireTimeSec := 0,
fireTimeNsec := 0, fireTimeNsec := 0,
ioIndex := -1, ioIndex := -1,
ioData := nil, ioHandle := nil,
ioMask := 0. ioMask := 0.
method(#class) forMutualExclusion method(#class) forMutualExclusion
@ -129,6 +129,11 @@ class Semaphore(Object)
{ {
^self.fireTimeSec < (aSemaphore fireTime) ^self.fireTimeSec < (aSemaphore fireTime)
} }
method notYoungerThan: aSemaphore
{
^self.fireTimeSec >= (aSemaphore fireTime)
}
} }
class SemaphoreHeap(Object) class SemaphoreHeap(Object)
@ -190,36 +195,30 @@ class SemaphoreHeap(Object)
self.arr at: anIndex put: aSemaphore. self.arr at: anIndex put: aSemaphore.
aSemaphore heapIndex: anIndex. aSemaphore heapIndex: anIndex.
^(aSemaphore youngerThan: item) ^if (aSemaphore youngerThan: item) { self siftUp: anIndex } else { self siftDown: anIndex }.
ifTrue: [ self siftUp: anIndex ]
ifFalse: [ self siftDown: anIndex ].
} }
method deleteAt: anIndex method deleteAt: anIndex
{ {
| item | | item xitem |
item := self.arr at: anIndex. item := self.arr at: anIndex.
item heapIndex: -1. item heapIndex: -1.
self.size := self.size - 1. self.size := self.size - 1.
(anIndex == self.size) if (anIndex == self.size)
ifTrue: [ {
"the last item" ## the last item
self.arr at: self.size put: nil. self.arr at: self.size put: nil.
] }
ifFalse: [ else
| xitem | {
xitem := self.arr at: self.size. xitem := self.arr at: self.size.
self.arr at: anIndex put: xitem. self.arr at: anIndex put: xitem.
xitem heapIndex: anIndex. xitem heapIndex: anIndex.
self.arr at: self.size put: nil. self.arr at: self.size put: nil.
if (xitem youngerThan: item) { self siftUp: anIndex } else { self siftDown: anIndex }.
(xitem youngerThan: item) }
ifTrue: [self siftUp: anIndex ]
ifFalse: [self siftDown: anIndex ]
]
} }
method parentIndex: anIndex method parentIndex: anIndex
@ -239,34 +238,31 @@ class SemaphoreHeap(Object)
method siftUp: anIndex method siftUp: anIndex
{ {
| pindex cindex par item stop | | pindex cindex par item |
(anIndex <= 0) ifTrue: [ ^anIndex ]. if (anIndex <= 0) { ^anIndex }.
pindex := anIndex. pindex := anIndex.
item := self.arr at: anIndex. item := self.arr at: anIndex.
stop := false. while (true)
[ stop ] whileFalse: [ {
cindex := pindex. cindex := pindex.
(cindex > 0) if (pindex <= 0) { break }.
ifTrue: [
pindex := self parentIndex: cindex. pindex := self parentIndex: cindex.
par := self.arr at: pindex. par := self.arr at: pindex.
(item youngerThan: par) if (item notYoungerThan: par) { break }.
ifTrue: [
## item is younger than the parent.
## move the parent down ## move the parent down
self.arr at: cindex put: par. self.arr at: cindex put: par.
par heapIndex: cindex. par heapIndex: cindex.
] }.
ifFalse: [ stop := true ].
]
ifFalse: [ stop := true ].
].
## place the item as high as it can
self.arr at: cindex put: item. self.arr at: cindex put: item.
item heapIndex: cindex. item heapIndex: cindex.
@ -275,36 +271,29 @@ class SemaphoreHeap(Object)
method siftDown: anIndex method siftDown: anIndex
{ {
| base capa cindex item | | base capa cindex item
left right younger xitem |
base := self.size quo: 2. base := self.size quo: 2.
(anIndex >= base) ifTrue: [^anIndex]. if (anIndex >= base) { ^anIndex }.
cindex := anIndex. cindex := anIndex.
item := self.arr at: cindex. item := self.arr at: cindex.
[ cindex < base ] whileTrue: [ while (cindex < base)
| left right younger xitem | {
left := self leftChildIndex: cindex. left := self leftChildIndex: cindex.
right := self rightChildIndex: cindex. right := self rightChildIndex: cindex.
((right < self.size) and: [(self.arr at: right) youngerThan: (self.arr at: left)]) younger := if ((right < self.size) and: [(self.arr at: right) youngerThan: (self.arr at: left)]) { right } else { left }.
ifTrue: [ younger := right ]
ifFalse: [ younger := left ].
xitem := self.arr at: younger. xitem := self.arr at: younger.
(item youngerThan: xitem) if (item youngerThan: xitem) { break }.
ifTrue: [
"break the loop"
base := anIndex
]
ifFalse: [
self.arr at: cindex put: xitem. self.arr at: cindex put: xitem.
xitem heapIndex: cindex. xitem heapIndex: cindex.
cindex := younger. cindex := younger.
] }.
].
self.arr at: cindex put: item. self.arr at: cindex put: item.
item heapIndex: cindex. item heapIndex: cindex.
@ -315,13 +304,8 @@ class SemaphoreHeap(Object)
class(#final,#limited) ProcessScheduler(Object) class(#final,#limited) ProcessScheduler(Object)
{ {
var tally, active, runnable_head, runnable_tail, sem_heap. var(#get) tally, active.
var runnable_head, runnable_tail (*, sem_heap*).
method new
{
"instantiation is not allowed"
^nil. "TODO: raise an exception"
}
method activeProcess method activeProcess
{ {
@ -333,8 +317,8 @@ class(#final,#limited) ProcessScheduler(Object)
<primitive: #_processor_schedule> <primitive: #_processor_schedule>
self primitiveFailed. self primitiveFailed.
"The primitive does something like the following in principle: (* The primitive does something like the following in principle:
(self.tally = 0) (self.tally == 0)
ifTrue: [ ifTrue: [
self.head := process. self.head := process.
self.tail := process. self.tail := process.
@ -346,16 +330,16 @@ class(#final,#limited) ProcessScheduler(Object)
self.head := process. self.head := process.
self.tally := self.tally + 1. self.tally := self.tally + 1.
]. ].
" *)
} }
" (* -------------------
method yield method yield
{ {
<primitive: #_processor_yield> <primitive: #_processor_yield>
self primitiveFailed self primitiveFailed
} }
" ----------------- *)
method signal: semaphore after: secs method signal: semaphore after: secs
{ {

View File

@ -32,23 +32,36 @@ class System(Apex)
method(#class) __gc_finalizer method(#class) __gc_finalizer
{ {
| tmp | | tmp gc |
gc := false.
while (true) while (true)
{ {
## TODO: exit from this loop when there are no other processes running. ## TODO: exit from this loop when there are no other processes running except this finalizer process
while ((tmp := self _popCollectable) notError) while ((tmp := self _popCollectable) notError)
{ {
## TODO: Do i have to protected this in an exception handler??? ## TODO: Do i have to protected this in an exception handler???
tmp finalize. if (tmp respondsTo: #finalize) { tmp finalize }.
}. }.
System logNl: 'gc_waiting....'. (*
Processor sleepFor: 1. ## TODO: wait on semaphore instead.. if (Processor tally == 1 and: [Processor active == thisProcess])
{
if (gc) { break }.
self collectGarbage.
'GC GC GC GC' dump.
Processor tally dump.
gc := true.
}.*)
##System logNl: 'gc_waiting....'.
##Processor sleepFor: 1. ## TODO: wait on semaphore instead..
} }
} }
method(#class,#primitive) _popCollectable. method(#class,#primitive) _popCollectable.
method(#class,#primitive) collectGarbage.
} }
pooldic System.Log pooldic System.Log

View File

@ -618,10 +618,11 @@ extend X11
'CLOSING X11 EVENT LOOP' dump. 'CLOSING X11 EVENT LOOP' dump.
Processor unsignal: self.event_loop_sem. Processor unsignal: self.event_loop_sem.
## TODO: LOOK HERE FOR RACE CONDITION
self.event_loop_sem := nil. self.event_loop_sem := nil.
self.event_loop_proc := nil.
self dispose. self dispose.
] fork. ] fork.
} }
} }
@ -630,6 +631,7 @@ extend X11
{ {
if (self.event_loop_sem notNil) if (self.event_loop_sem notNil)
{ {
## TODO: handle race-condition with the part maked 'LOOK HERE FOR RACE CONDITION'
self.event_loop_proc terminate. self.event_loop_proc terminate.
self.event_loop_proc := nil. self.event_loop_proc := nil.
self.event_loop_sem := nil. self.event_loop_sem := nil.
@ -704,14 +706,19 @@ extend X11
class Fx(Object) class Fx(Object)
{ {
var(#class) X := 20.
var x.
method initialize method initialize
{ {
self.X := self.X + 1.
self.x := self.X.
self addToBeFinalized. self addToBeFinalized.
} }
method finalize method finalize
{ {
System logNl: 'Greate... FX instance finalized'. System logNl: ('Greate... FX instance finalized' & self.x asString).
} }
} }
@ -722,6 +729,7 @@ class MyObject(Object)
method main1 method main1
{ {
| comp1 | | comp1 |
self.disp1 := X11 new. self.disp1 := X11 new.
self.disp2 := X11 new. self.disp2 := X11 new.
@ -755,11 +763,9 @@ class MyObject(Object)
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. comp1 := Fx new.
Fx new. Fx new.
Fx new. comp1 := Fx new.
Fx new. Fx new.
} }

View File

@ -17,6 +17,38 @@ class MyObject(Object)
^a ^a
} }
method(#class) test_semaphore_heap
{
| sempq a |
sempq := SemaphoreHeap new.
'--------------------------' dump.
1 to: 200 by: 1 do: [ :i |
| sem |
sem := Semaphore new.
sem fireTime: (200 - i).
sempq insert: sem
].
'--------------------------' dump.
sempq deleteAt: 40.
sempq deleteAt: 50.
sempq deleteAt: 100.
a := -100.
[sempq size > 0] whileTrue: [
| sem b |
sem := sempq popTop.
b := sem fireTime.
if (a > b) { ^false }.
a := b.
].
^true
}
method(#class) main method(#class) main
{ {
| tc limit | | tc limit |
@ -24,7 +56,8 @@ class MyObject(Object)
tc := %( tc := %(
## 0 - 4 ## 0 - 4
[ self proc1 == 100 ], [ self proc1 == 100 ],
[ Processor sleepFor: 2. self proc1 == 200 ] [ Processor sleepFor: 2. self proc1 == 200 ],
[ self test_semaphore_heap == true ]
). ).
limit := tc size. limit := tc size.
@ -33,7 +66,7 @@ class MyObject(Object)
| tb | | tb |
tb := tc at: idx. tb := tc at: idx.
System log(System.Log.INFO, idx asString, (if (tb value) { ' PASS' } else { ' FAIL' }), S'\n'). System log(System.Log.INFO, idx asString, (if (tb value) { ' PASS' } else { ' FAIL' }), S'\n').
] ].
} }
} }

View File

@ -171,6 +171,7 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c)
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - made process %O of size %zu\n", proc, MOO_OBJ_GET_SIZE(proc)); MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - made process %O of size %zu\n", proc, MOO_OBJ_GET_SIZE(proc));
#endif #endif
return proc; return proc;
} }
@ -255,7 +256,7 @@ static MOO_INLINE int chain_into_processor (moo_t* moo, moo_oop_process_t proc)
if (tally >= MOO_SMOOI_MAX) if (tally >= MOO_SMOOI_MAX)
{ {
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many process\n"); MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many processes\n");
#endif #endif
moo_seterrnum (moo, MOO_EPFULL); moo_seterrnum (moo, MOO_EPFULL);
return -1; return -1;
@ -713,11 +714,13 @@ static void delete_from_sem_heap (moo_t* moo, moo_ooi_t index)
{ {
moo_oop_semaphore_t sem, lastsem; moo_oop_semaphore_t sem, lastsem;
MOO_ASSERT (moo, index >= 0 && index < moo->sem_heap_count);
sem = moo->sem_heap[index]; sem = moo->sem_heap[index];
sem->heap_index = MOO_SMOOI_TO_OOP(-1); sem->heap_index = MOO_SMOOI_TO_OOP(-1);
moo->sem_heap_count--; moo->sem_heap_count--;
if (moo->sem_heap_count > 0 && index != moo->sem_heap_count) if (/*moo->sem_heap_count > 0 &&*/ index != moo->sem_heap_count)
{ {
/* move the last item to the deletion position */ /* move the last item to the deletion position */
lastsem = moo->sem_heap[moo->sem_heap_count]; lastsem = moo->sem_heap[moo->sem_heap_count];
@ -808,6 +811,7 @@ static int delete_from_sem_io (moo_t* moo, moo_ooi_t index)
moo_oop_semaphore_t sem; moo_oop_semaphore_t sem;
int x; int x;
MOO_ASSERT (moo, index >= 0 && index < moo->sem_io_count);
sem = moo->sem_io[index]; sem = moo->sem_io[index];
MOO_ASSERT (moo, index == MOO_OOP_TO_SMOOI(sem->io_index)); MOO_ASSERT (moo, index == MOO_OOP_TO_SMOOI(sem->io_index));
@ -824,7 +828,7 @@ static int delete_from_sem_io (moo_t* moo, moo_ooi_t index)
sem->io_index = MOO_SMOOI_TO_OOP(-1); sem->io_index = MOO_SMOOI_TO_OOP(-1);
moo->sem_io_count--; moo->sem_io_count--;
if (moo->sem_io_count > 0 && index != moo->sem_io_count) if (/*moo->sem_io_count > 0 &&*/ index != moo->sem_io_count)
{ {
moo_oop_semaphore_t lastsem; moo_oop_semaphore_t lastsem;
@ -3071,11 +3075,18 @@ 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_collect_garbage (moo_t* moo, moo_ooi_t nargs)
{
moo_gc (moo);
MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_system_pop_collectable (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_system_pop_collectable (moo_t* moo, moo_ooi_t nargs)
{ {
if (moo->collectable.first) if (moo->collectable.first)
{ {
moo_collectable_t* first; moo_finalizable_t* first;
first = moo->collectable.first; first = moo->collectable.first;
@ -3086,11 +3097,8 @@ static moo_pfrc_t pf_system_pop_collectable (moo_t* moo, moo_ooi_t nargs)
MOO_STACK_SETRET (moo, nargs, first->oop); 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_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_DELETE_FROM_LIST (&moo->collectable, first);
moo_freemem (moo, first); moo_freemem (moo, first); /* TODO: move it to the free list instead... */
MOO_DEBUG1 (moo, "POPPED FINALIZABLE...%p\n", moo->collectable.first);
} }
else else
{ {
@ -3982,6 +3990,7 @@ static pf_t pftab[] =
{ "System__putUint32", { pf_system_put_uint32, 3, 3 } }, { "System__putUint32", { pf_system_put_uint32, 3, 3 } },
{ "System__putUint64", { pf_system_put_uint64, 3, 3 } }, { "System__putUint64", { pf_system_put_uint64, 3, 3 } },
{ "System_collectGarbage", { pf_system_collect_garbage, 0, 0 } },
{ "System_log", { pf_system_log, 2, MA } } { "System_log", { pf_system_log, 2, MA } }
}; };

View File

@ -551,6 +551,9 @@ static moo_uint8_t* scan_new_heap (moo_t* moo, moo_uint8_t* ptr)
moo_oop_oop_t xtmp; moo_oop_oop_t xtmp;
moo_oow_t size; moo_oow_t size;
/* TODO: is it better to use a flag bit in the header to
* determine that it is an instance of process?
* for example, if (MOO_OBJ_GET_FLAGS_PROC(oop))... */
if (moo->_process && MOO_OBJ_GET_CLASS(oop) == moo->_process) if (moo->_process && MOO_OBJ_GET_CLASS(oop) == moo->_process)
{ {
/* the stack in a process object doesn't need to be /* the stack in a process object doesn't need to be
@ -620,7 +623,7 @@ void moo_gc (moo_t* moo)
* move objects pointed to by the fields to the new heap. * move objects pointed to by the fields to the new heap.
* finally perform some tricky symbol table clean-up. * finally perform some tricky symbol table clean-up.
*/ */
moo_uint8_t* ptr; moo_uint8_t* scan_ptr;
moo_heap_t* tmp; moo_heap_t* tmp;
moo_oop_t old_nil; moo_oop_t old_nil;
moo_oow_t i; moo_oow_t i;
@ -643,6 +646,8 @@ void moo_gc (moo_t* moo)
"Starting GC curheap base %p ptr %p newheap base %p ptr %p\n", "Starting GC curheap base %p ptr %p newheap base %p ptr %p\n",
moo->curheap->base, moo->curheap->ptr, moo->newheap->base, moo->newheap->ptr); moo->curheap->base, moo->curheap->ptr, moo->newheap->base, moo->newheap->ptr);
scan_ptr = (moo_uint8_t*) MOO_ALIGN ((moo_uintptr_t)moo->newheap->base, MOO_SIZEOF(moo_oop_t));
/* TODO: allocate common objects like _nil and the root dictionary /* TODO: allocate common objects like _nil and the root dictionary
* in the permanant heap. minimize moving around */ * in the permanant heap. minimize moving around */
old_nil = moo->_nil; old_nil = moo->_nil;
@ -701,12 +706,11 @@ void moo_gc (moo_t* moo)
} }
/* scan the new heap to move referenced objects */ /* scan the new heap to move referenced objects */
ptr = (moo_uint8_t*) MOO_ALIGN ((moo_uintptr_t)moo->newheap->base, MOO_SIZEOF(moo_oop_t)); scan_ptr = scan_new_heap (moo, scan_ptr);
ptr = scan_new_heap (moo, ptr);
/* FINALIZATION */ /* FINALIZATION */
move_finalizable_objects (moo); move_finalizable_objects (moo);
ptr = scan_new_heap (moo, ptr); scan_ptr = scan_new_heap (moo, scan_ptr);
/* END FINALIZATION */ /* END FINALIZATION */
/* traverse the symbol table for unreferenced symbols. /* traverse the symbol table for unreferenced symbols.
@ -721,7 +725,7 @@ void moo_gc (moo_t* moo)
/* scan the new heap again from the end position of /* scan the new heap again from the end position of
* the previous scan to move referenced objects by * the previous scan to move referenced objects by
* the symbol table. */ * the symbol table. */
ptr = scan_new_heap (moo, ptr); scan_ptr = scan_new_heap (moo, scan_ptr);
/* the contents of the current heap is not needed any more. /* the contents of the current heap is not needed any more.
* reset the upper bound to the base. don't forget to align the heap * reset the upper bound to the base. don't forget to align the heap
@ -822,11 +826,10 @@ moo_oop_t moo_shallowcopy (moo_t* moo, moo_oop_t oop)
int moo_regfinalizable (moo_t* moo, moo_oop_t oop) int moo_regfinalizable (moo_t* moo, moo_oop_t oop)
{ {
moo_collectable_t* x; moo_finalizable_t* x;
MOO_DEBUG1 (moo, "ADDING FINALIZABLE... %O\n", oop);
if (!MOO_OOP_IS_POINTER(oop) || if (!MOO_OOP_IS_POINTER(oop) || (MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)))
(MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)))
{ {
moo_seterrnum (moo, MOO_EINVAL); moo_seterrnum (moo, MOO_EINVAL);
return -1; return -1;
@ -840,17 +843,15 @@ MOO_DEBUG1 (moo, "ADDING FINALIZABLE... %O\n", oop);
MOO_APPEND_TO_LIST (&moo->finalizable, x); MOO_APPEND_TO_LIST (&moo->finalizable, x);
MOO_DEBUG1 (moo, "ADDED FINALIZABLE... %O\n", oop);
return 0; return 0;
} }
int moo_deregfinalizable (moo_t* moo, moo_oop_t oop) int moo_deregfinalizable (moo_t* moo, moo_oop_t oop)
{ {
moo_collectable_t* x; moo_finalizable_t* x;
if (!MOO_OOP_IS_POINTER(oop) || if (!MOO_OOP_IS_POINTER(oop) || ((MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) != MOO_GCFIN_FINALIZABLE))
((MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) != MOO_GCFIN_FINALIZABLE))
{ {
moo_seterrnum (moo, MOO_EINVAL); moo_seterrnum (moo, MOO_EINVAL);
return -1; return -1;
@ -861,7 +862,6 @@ int moo_deregfinalizable (moo_t* moo, moo_oop_t oop)
{ {
if (x->oop == oop) 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_OBJ_SET_FLAGS_GCFIN(oop, (MOO_OBJ_GET_FLAGS_GCFIN(oop) & ~MOO_GCFIN_FINALIZABLE));
MOO_DELETE_FROM_LIST (&moo->finalizable, x); MOO_DELETE_FROM_LIST (&moo->finalizable, x);
return 0; return 0;
@ -874,10 +874,11 @@ int moo_deregfinalizable (moo_t* moo, moo_oop_t oop)
static void move_finalizable_objects (moo_t* moo) static void move_finalizable_objects (moo_t* moo)
{ {
moo_collectable_t* x, * y; moo_finalizable_t* x, * y;
for (x = moo->collectable.first; x; x = x->next) for (x = moo->collectable.first; x; x = x->next)
{ {
MOO_ASSERT (moo, (MOO_OBJ_GET_FLAGS_GCFIN(x->oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) == MOO_GCFIN_FINALIZABLE);
x->oop = moo_moveoop (moo, x->oop); x->oop = moo_moveoop (moo, x->oop);
} }
@ -885,15 +886,20 @@ static void move_finalizable_objects (moo_t* moo)
{ {
y = x->next; y = x->next;
MOO_ASSERT (moo, (MOO_OBJ_GET_FLAGS_GCFIN(x->oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) == MOO_GCFIN_FINALIZABLE);
if (!MOO_OBJ_GET_FLAGS_MOVED(x->oop)) if (!MOO_OBJ_GET_FLAGS_MOVED(x->oop))
{ {
/* TODO: if already finalized, don't move, don't add to collectable /* the object has not been moved. it means this object is not reachable
if (MOVE_OBJ_GET_FLAGS_FINALIZED(x->oop)) continue; * from the root except this finalizable list. this object would be
* */ * garbage if not for finalizatin. it's almost collectable. but it
x->oop = moo_moveoop (moo, x->oop); * will survive this cycle for finalization.
*
* if garbages consist of finalizable objects only, GC should fail miserably.
* however this is quite unlikely because some key objects for VM execution
* like context objects doesn't require finalization. */
/* it's almost collectable. but don't collect it yet. x->oop = moo_moveoop (moo, x->oop);
* if garbages consist of finalizable objects only, GC should fail miserably */
/* remove it from the finalizable list */ /* remove it from the finalizable list */
MOO_DELETE_FROM_LIST (&moo->finalizable, x); MOO_DELETE_FROM_LIST (&moo->finalizable, x);
@ -901,6 +907,7 @@ if (MOVE_OBJ_GET_FLAGS_FINALIZED(x->oop)) continue;
/* add it to the collectable list */ /* add it to the collectable list */
MOO_APPEND_TO_LIST (&moo->collectable, x); MOO_APPEND_TO_LIST (&moo->collectable, x);
// TODO: singal semaphore..
//signal_semaphore (moo, moo->collectable_semaphore); //signal_semaphore (moo, moo->collectable_semaphore);
} }
else else

View File

@ -314,7 +314,9 @@ typedef enum moo_obj_type_t moo_obj_type_t;
enum moo_gcfin_t enum moo_gcfin_t
{ {
MOO_GCFIN_FINALIZABLE = (1 << 0), MOO_GCFIN_FINALIZABLE = (1 << 0),
MOO_GCFIN_FINALIZED = (1 << 1) MOO_GCFIN_FINALIZED = (1 << 1),
MOO_GCFIN_RESERVED_0 = (1 << 2),
MOO_GCFIN_RESERVED_1 = (1 << 3)
}; };
typedef enum moo_gcfin_t moo_gcfin_t; typedef enum moo_gcfin_t moo_gcfin_t;
@ -373,7 +375,7 @@ typedef enum moo_gcfin_t moo_gcfin_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_GCFIN_BITS 4
#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)
@ -792,7 +794,7 @@ struct moo_semaphore_t
moo_oop_t io_mask; /* SmallInteger */ moo_oop_t io_mask; /* SmallInteger */
}; };
#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 5 #define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 4
typedef struct moo_process_scheduler_t moo_process_scheduler_t; typedef struct moo_process_scheduler_t moo_process_scheduler_t;
typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t; typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t;
struct moo_process_scheduler_t struct moo_process_scheduler_t
@ -802,7 +804,7 @@ struct moo_process_scheduler_t
moo_oop_process_t active; /* pointer to an active process in the runnable process list */ moo_oop_process_t active; /* pointer to an active process in the runnable process list */
moo_oop_process_t runnable_head; /* runnable process list */ moo_oop_process_t runnable_head; /* runnable process list */
moo_oop_process_t runnable_tail; /* runnable process list */ moo_oop_process_t runnable_tail; /* runnable process list */
moo_oop_t sempq; /* SemaphoreHeap */ /*moo_oop_t sempq;*/ /* SemaphoreHeap */
}; };
/** /**
@ -1001,12 +1003,12 @@ 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; typedef struct moo_finalizable_t moo_finalizable_t;
struct moo_collectable_t struct moo_finalizable_t
{ {
moo_oop_t oop; moo_oop_t oop;
moo_collectable_t* prev; moo_finalizable_t* prev;
moo_collectable_t* next; moo_finalizable_t* next;
}; };
/* special callback to be called for trailer */ /* special callback to be called for trailer */
@ -1178,14 +1180,14 @@ struct moo_t
struct struct
{ {
moo_collectable_t* first; moo_finalizable_t* first;
moo_collectable_t* last; moo_finalizable_t* last;
} collectable; } collectable;
struct struct
{ {
moo_collectable_t* first; moo_finalizable_t* first;
moo_collectable_t* last; moo_finalizable_t* last;
} finalizable; } finalizable;
moo_uintmax_t inst_counter; moo_uintmax_t inst_counter;