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

@ -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)
MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - made process %O of size %zu\n", proc, MOO_OBJ_GET_SIZE(proc));
#endif
return proc;
}
@ -254,9 +255,9 @@ static MOO_INLINE int chain_into_processor (moo_t* moo, moo_oop_process_t proc)
MOO_ASSERT (moo, tally >= 0);
if (tally >= MOO_SMOOI_MAX)
{
#if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many process\n");
#endif
#if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many processes\n");
#endif
moo_seterrnum (moo, MOO_EPFULL);
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_ASSERT (moo, index >= 0 && index < moo->sem_heap_count);
sem = moo->sem_heap[index];
sem->heap_index = MOO_SMOOI_TO_OOP(-1);
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 */
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;
int x;
MOO_ASSERT (moo, index >= 0 && index < moo->sem_io_count);
sem = moo->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);
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;
@ -3071,11 +3075,18 @@ static moo_pfrc_t pf_system_log (moo_t* moo, moo_ooi_t nargs)
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)
{
if (moo->collectable.first)
{
moo_collectable_t* first;
moo_finalizable_t* 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_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);
moo_freemem (moo, first); /* TODO: move it to the free list instead... */
}
else
{
@ -3982,6 +3990,7 @@ static pf_t pftab[] =
{ "System__putUint32", { pf_system_put_uint32, 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 } }
};

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_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)
{
/* 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.
* finally perform some tricky symbol table clean-up.
*/
moo_uint8_t* ptr;
moo_uint8_t* scan_ptr;
moo_heap_t* tmp;
moo_oop_t old_nil;
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",
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
* in the permanant heap. minimize moving around */
old_nil = moo->_nil;
@ -701,12 +706,11 @@ void moo_gc (moo_t* moo)
}
/* 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));
ptr = scan_new_heap (moo, ptr);
scan_ptr = scan_new_heap (moo, scan_ptr);
/* FINALIZATION */
move_finalizable_objects (moo);
ptr = scan_new_heap (moo, ptr);
scan_ptr = scan_new_heap (moo, scan_ptr);
/* END FINALIZATION */
/* 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
* the previous scan to move referenced objects by
* 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.
* 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)
{
moo_collectable_t* x;
moo_finalizable_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)))
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;
@ -840,17 +843,15 @@ MOO_DEBUG1 (moo, "ADDING FINALIZABLE... %O\n", 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;
moo_finalizable_t* x;
if (!MOO_OOP_IS_POINTER(oop) ||
((MOO_OBJ_GET_FLAGS_GCFIN(oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) != MOO_GCFIN_FINALIZABLE))
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;
@ -861,7 +862,6 @@ int moo_deregfinalizable (moo_t* moo, moo_oop_t 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_DELETE_FROM_LIST (&moo->finalizable, x);
return 0;
@ -874,10 +874,11 @@ int moo_deregfinalizable (moo_t* moo, moo_oop_t oop)
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)
{
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);
}
@ -885,15 +886,20 @@ static void move_finalizable_objects (moo_t* moo)
{
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))
{
/* 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);
/* the object has not been moved. it means this object is not reachable
* from the root except this finalizable list. this object would be
* garbage if not for finalizatin. it's almost collectable. but it
* 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.
* if garbages consist of finalizable objects only, GC should fail miserably */
x->oop = moo_moveoop (moo, x->oop);
/* remove it from the finalizable list */
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 */
MOO_APPEND_TO_LIST (&moo->collectable, x);
// TODO: singal semaphore..
//signal_semaphore (moo, moo->collectable_semaphore);
}
else

View File

@ -314,7 +314,9 @@ typedef enum moo_obj_type_t moo_obj_type_t;
enum moo_gcfin_t
{
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;
@ -373,7 +375,7 @@ typedef enum moo_gcfin_t moo_gcfin_t;
#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_GCFIN_BITS 4
#define MOO_OBJ_FLAGS_TRAILER_BITS 1
#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 */
};
#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_oop_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 runnable_head; /* 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_collectable_t moo_collectable_t;
struct moo_collectable_t
typedef struct moo_finalizable_t moo_finalizable_t;
struct moo_finalizable_t
{
moo_oop_t oop;
moo_collectable_t* prev;
moo_collectable_t* next;
moo_finalizable_t* prev;
moo_finalizable_t* next;
};
/* special callback to be called for trailer */
@ -1178,14 +1180,14 @@ struct moo_t
struct
{
moo_collectable_t* first;
moo_collectable_t* last;
moo_finalizable_t* first;
moo_finalizable_t* last;
} collectable;
struct
{
moo_collectable_t* first;
moo_collectable_t* last;
moo_finalizable_t* first;
moo_finalizable_t* last;
} finalizable;
moo_uintmax_t inst_counter;