diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 6531cf0..27c4659 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -10585,7 +10585,7 @@ static void gc_oopbuf (moo_t* moo, moo_oopbuf_t* oopbuf) for (i = 0; i < oopbuf->count; i++) { - register moo_oop_t x = moo_moveoop(moo, oopbuf->ptr[i]); + moo_oop_t x = moo_updateoopforgc(moo, oopbuf->ptr[i]); oopbuf->ptr[i] = x; } } @@ -10614,12 +10614,12 @@ static void gc_cunit_chain (moo_t* moo) pd = (moo_cunit_pooldic_t*)cunit; if (pd->pd_oop) { - register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)pd->pd_oop); + moo_oop_t x = moo_updateoopforgc(moo, (moo_oop_t)pd->pd_oop); pd->pd_oop = (moo_oop_dic_t)x; } if (pd->ns_oop) { - register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)pd->ns_oop); + moo_oop_t x = moo_updateoopforgc(moo, (moo_oop_t)pd->ns_oop); pd->ns_oop = (moo_oop_nsdic_t)x; } break; @@ -10632,29 +10632,29 @@ static void gc_cunit_chain (moo_t* moo) cc = (moo_cunit_class_t*)cunit; if (cc->self_oop) - cc->self_oop = (moo_oop_class_t)moo_moveoop(moo, (moo_oop_t)cc->self_oop); + cc->self_oop = (moo_oop_class_t)moo_updateoopforgc(moo, (moo_oop_t)cc->self_oop); if (cc->super_oop) - cc->super_oop = moo_moveoop(moo, cc->super_oop); + cc->super_oop = moo_updateoopforgc(moo, cc->super_oop); for (i = 0; i < MOO_COUNTOF(cc->var); i++) { for (j = 0; j < cc->var[i].initv_count; j++) { register moo_oop_t x = cc->var[i].initv[j].v; - if (x) cc->var[i].initv[j].v = moo_moveoop(moo, x); + if (x) cc->var[i].initv[j].v = moo_updateoopforgc(moo, x); } } if (cc->ns_oop) { - register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)cc->ns_oop); + moo_oop_t x = moo_updateoopforgc(moo, (moo_oop_t)cc->ns_oop); cc->ns_oop = (moo_oop_nsdic_t)x; } if (cc->superns_oop) { - register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)cc->superns_oop); + moo_oop_t x = moo_updateoopforgc(moo, (moo_oop_t)cc->superns_oop); cc->superns_oop = (moo_oop_nsdic_t)x; } @@ -10672,11 +10672,11 @@ static void gc_cunit_chain (moo_t* moo) ifce = (moo_cunit_interface_t*)cunit; if (ifce->self_oop) - ifce->self_oop = (moo_oop_interface_t)moo_moveoop(moo, (moo_oop_t)ifce->self_oop); + ifce->self_oop = (moo_oop_interface_t)moo_updateoopforgc(moo, (moo_oop_t)ifce->self_oop); if (ifce->ns_oop) { - register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)ifce->ns_oop); + moo_oop_t x = moo_updateoopforgc(moo, (moo_oop_t)ifce->ns_oop); ifce->ns_oop = (moo_oop_nsdic_t)x; } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 0e3dee6..ba378a8 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -206,7 +206,7 @@ static MOO_INLINE void vm_cleanup (moo_t* moo) moo_deregallfinalizables (moo); /* final garbage collection */ - moo_gc (moo); + moo_gc (moo, 1); MOO_DEBUG0 (moo, "VM cleaned up\n"); } @@ -6356,6 +6356,7 @@ int moo_execute (moo_t* moo) moo->proc_switched = 0; moo->abort_req = 0; +moo->gci.lazy_sweep = 1; n = __execute (moo); vm_cleanup (moo); diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 6c09219..4fff5fc 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -799,7 +799,7 @@ static moo_rbt_walk_t call_module_gc (moo_rbt_t* rbt, moo_rbt_pair_t* pair, void #if defined(MOO_ENABLE_GC_MARK_SWEEP) #if 0 -static MOO_INLINE void gc_mark (moo_t* moo, moo_oop_t oop) +static MOO_INLINE void gc_ms_mark (moo_t* moo, moo_oop_t oop) { moo_oow_t i, sz; @@ -812,7 +812,7 @@ static MOO_INLINE void gc_mark (moo_t* moo, moo_oop_t oop) MOO_OBJ_SET_FLAGS_MOVED(oop, 1); /* mark */ - gc_mark (moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)); /* TODO: remove recursion */ + gc_ms_mark (moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)); /* TODO: remove recursion */ if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_OOP) { @@ -836,12 +836,12 @@ static MOO_INLINE void gc_mark (moo_t* moo, moo_oop_t oop) for (i = 0; i < size; i++) { moo_oop_t tmp = MOO_OBJ_GET_OOP_VAL(oop, i); - if (MOO_OOP_IS_POINTER(tmp)) gc_mark (moo, tmp); /* TODO: no resursion */ + if (MOO_OOP_IS_POINTER(tmp)) gc_ms_mark (moo, tmp); /* TODO: no resursion */ } } } #else -static MOO_INLINE void gc_mark_object (moo_t* moo, moo_oop_t oop) +static MOO_INLINE void gc_ms_mark_object (moo_t* moo, moo_oop_t oop) { #if defined(MOO_SUPPORT_GC_DURING_IGNITION) if (!oop) return; @@ -854,7 +854,7 @@ MOO_ASSERT (moo, moo->gci.stack.len < moo->gci.stack.capa); if (moo->gci.stack.len > moo->gci.stack.max) moo->gci.stack.max = moo->gci.stack.len; } -static MOO_INLINE void gc_scan_stack (moo_t* moo) +static MOO_INLINE void gc_ms_scan_stack (moo_t* moo) { moo_oop_t oop; @@ -862,7 +862,7 @@ static MOO_INLINE void gc_scan_stack (moo_t* moo) { oop = moo->gci.stack.ptr[--moo->gci.stack.len]; - gc_mark_object (moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)); + gc_ms_mark_object (moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)); if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_OOP) { @@ -885,20 +885,20 @@ static MOO_INLINE void gc_scan_stack (moo_t* moo) for (i = 0; i < size; i++) { - gc_mark_object (moo, MOO_OBJ_GET_OOP_VAL(oop, i)); + gc_ms_mark_object (moo, MOO_OBJ_GET_OOP_VAL(oop, i)); } } } } -static MOO_INLINE void gc_mark (moo_t* moo, moo_oop_t oop) +static MOO_INLINE void gc_ms_mark (moo_t* moo, moo_oop_t oop) { - gc_mark_object (moo, oop); - gc_scan_stack (moo); + gc_ms_mark_object (moo, oop); + gc_ms_scan_stack (moo); } #endif -static MOO_INLINE void gc_mark_root (moo_t* moo) +static MOO_INLINE void gc_ms_mark_roots (moo_t* moo) { moo_oow_t i, gcfin_count; moo_evtcb_t* cb; @@ -913,57 +913,57 @@ static MOO_INLINE void gc_mark_root (moo_t* moo) moo->processor->active->sp = MOO_SMOOI_TO_OOP(moo->sp); } - gc_mark (moo, moo->_nil); - gc_mark (moo, moo->_true); - gc_mark (moo, moo->_false); + gc_ms_mark (moo, moo->_nil); + gc_ms_mark (moo, moo->_true); + gc_ms_mark (moo, moo->_false); for (i = 0; i < MOO_COUNTOF(kernel_classes); i++) { - gc_mark (moo, *(moo_oop_t*)((moo_uint8_t*)moo + kernel_classes[i].offset)); + gc_ms_mark (moo, *(moo_oop_t*)((moo_uint8_t*)moo + kernel_classes[i].offset)); } - gc_mark (moo, (moo_oop_t)moo->sysdic); - gc_mark (moo, (moo_oop_t)moo->processor); - gc_mark (moo, (moo_oop_t)moo->nil_process); - gc_mark (moo, (moo_oop_t)moo->dicnewsym); - gc_mark (moo, (moo_oop_t)moo->dicputassocsym); - gc_mark (moo, (moo_oop_t)moo->does_not_understand_sym); - gc_mark (moo, (moo_oop_t)moo->primitive_failed_sym); - gc_mark (moo, (moo_oop_t)moo->unwindto_return_sym); + gc_ms_mark (moo, (moo_oop_t)moo->sysdic); + gc_ms_mark (moo, (moo_oop_t)moo->processor); + gc_ms_mark (moo, (moo_oop_t)moo->nil_process); + gc_ms_mark (moo, (moo_oop_t)moo->dicnewsym); + gc_ms_mark (moo, (moo_oop_t)moo->dicputassocsym); + gc_ms_mark (moo, (moo_oop_t)moo->does_not_understand_sym); + gc_ms_mark (moo, (moo_oop_t)moo->primitive_failed_sym); + gc_ms_mark (moo, (moo_oop_t)moo->unwindto_return_sym); for (i = 0; i < moo->sem_list_count; i++) { - gc_mark (moo, (moo_oop_t)moo->sem_list[i]); + gc_ms_mark (moo, (moo_oop_t)moo->sem_list[i]); } for (i = 0; i < moo->sem_heap_count; i++) { - gc_mark (moo, (moo_oop_t)moo->sem_heap[i]); + gc_ms_mark (moo, (moo_oop_t)moo->sem_heap[i]); } for (i = 0; i < moo->sem_io_tuple_count; i++) { if (moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT]) - gc_mark (moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT]); + gc_ms_mark (moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT]); if (moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT]) - gc_mark (moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT]); + gc_ms_mark (moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT]); } - gc_mark (moo, (moo_oop_t)moo->sem_gcfin); + gc_ms_mark (moo, (moo_oop_t)moo->sem_gcfin); for (i = 0; i < moo->proc_map_capa; i++) { - gc_mark (moo, moo->proc_map[i]); + gc_ms_mark (moo, moo->proc_map[i]); } for (i = 0; i < moo->volat_count; i++) { - gc_mark (moo, *moo->volat_stack[i]); + gc_ms_mark (moo, *moo->volat_stack[i]); } - if (moo->initial_context) gc_mark (moo, (moo_oop_t)moo->initial_context); - if (moo->active_context) gc_mark (moo, (moo_oop_t)moo->active_context); - if (moo->active_method) gc_mark (moo, (moo_oop_t)moo->active_method); + if (moo->initial_context) gc_ms_mark (moo, (moo_oop_t)moo->initial_context); + if (moo->active_context) gc_ms_mark (moo, (moo_oop_t)moo->active_context); + if (moo->active_method) gc_ms_mark (moo, (moo_oop_t)moo->active_method); moo_rbt_walk (&moo->modtab, call_module_gc, moo); @@ -978,7 +978,7 @@ static MOO_INLINE void gc_mark_root (moo_t* moo) { compact_symbol_table (moo, moo->_nil); /* delete symbol table entries that are not marked */ #if 0 - gc_mark (moo, (moo_oop_t)moo->symtab); /* mark the symbol table */ + gc_ms_mark (moo, (moo_oop_t)moo->symtab); /* mark the symbol table */ #else MOO_OBJ_SET_FLAGS_MOVED(moo->symtab, 1); /* mark */ MOO_OBJ_SET_FLAGS_MOVED(moo->symtab->bucket, 1); /* mark */ @@ -993,7 +993,60 @@ static MOO_INLINE void gc_mark_root (moo_t* moo) moo_clearmethodcache (moo); } -static MOO_INLINE void gc_sweep (moo_t* moo) +void moo_gc_ms_sweep_lazy (moo_t* moo, moo_oow_t allocsize) +{ + moo_gchdr_t* curr, * next, * prev; + moo_oop_t obj; + moo_oow_t freed_size; + + if (!moo->gci.ls.curr) return; + + freed_size = 0; + +//printf ("starting lazy sweep...gci.ls.curr [%p]\n", moo->gci.ls.curr); + prev = moo->gci.ls.prev; + curr = moo->gci.ls.curr; + + while (curr) + { + next = curr->next; + obj = (moo_oop_t)(curr + 1); + + if (MOO_OBJ_GET_FLAGS_MOVED(obj)) /* if marked */ + { + MOO_OBJ_SET_FLAGS_MOVED (obj, 0); /* unmark */ + prev = curr; + } + else + { + moo_oow_t objsize; + + if (prev) prev->next = next; + else moo->gci.b = next; + + objsize = MOO_SIZEOF(moo_obj_t) + moo_getobjpayloadbytes(moo, obj); + freed_size += objsize; + moo->gci.bsz -= objsize; + moo_freeheapmem (moo, moo->heap, curr); /* destroy */ + + if (freed_size > allocsize) /* TODO: can it secure large enough space? */ + { +//printf ("stopping lazy sweeping after %lu free, allocsize %lu\n", (unsigned long int)freed_size, (unsigned long int)allocsize); + moo->gci.ls.curr = next; /* let the next lazy sweeping begin at this point */ + moo->gci.ls.prev = prev; +//printf ("finished lazy sweep...\n"); + return; + } + } + + curr = next; + } + + moo->gci.ls.curr = MOO_NULL; +//printf ("finished lazy sweep...\n"); +} + +static MOO_INLINE void gc_ms_sweep (moo_t* moo) { moo_gchdr_t* curr, * next, * prev; moo_oop_t obj; @@ -1005,30 +1058,31 @@ static MOO_INLINE void gc_sweep (moo_t* moo) next = curr->next; obj = (moo_oop_t)(curr + 1); - if (MOO_OBJ_GET_FLAGS_MOVED(obj)) + if (MOO_OBJ_GET_FLAGS_MOVED(obj)) /* if marked */ { - /* unmark */ - MOO_OBJ_SET_FLAGS_MOVED (obj, 0); + MOO_OBJ_SET_FLAGS_MOVED (obj, 0); /* unmark */ prev = curr; } else { - /* destroy */ if (prev) prev->next = next; else moo->gci.b = next; moo->gci.bsz -= MOO_SIZEOF(moo_obj_t) + moo_getobjpayloadbytes(moo, obj); - moo_freeheapmem (moo, moo->heap, curr); + moo_freeheapmem (moo, moo->heap, curr); /* destroy */ } curr = next; } + +printf ("finised full sweep...\n"); + moo->gci.ls.curr = MOO_NULL; } #endif /* ----------------------------------------------------------------------- */ -static moo_oop_t move_oop_in_heap_space (moo_t* moo, moo_oop_t oop) +static moo_oop_t gc_ss_move_oop (moo_t* moo, moo_oop_t oop) { #if defined(MOO_SUPPORT_GC_DURING_IGNITION) if (!oop) return oop; @@ -1095,7 +1149,7 @@ static moo_oop_t move_oop_in_heap_space (moo_t* moo, moo_oop_t oop) } } -static moo_uint8_t* scan_heap_space (moo_t* moo, moo_uint8_t* ptr, moo_uint8_t** end) +static moo_uint8_t* gc_ss_scan_space (moo_t* moo, moo_uint8_t* ptr, moo_uint8_t** end) { while (ptr < *end) /* the end pointer may get changed, especially the new space. so it's moo_int8_t** */ { @@ -1108,7 +1162,7 @@ static moo_uint8_t* scan_heap_space (moo_t* moo, moo_uint8_t* ptr, moo_uint8_t** nbytes_aligned = moo_getobjpayloadbytes(moo, oop); - tmp = moo_moveoop(moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)); + tmp = moo_updateoopforgc(moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)); MOO_OBJ_SET_CLASS (oop, tmp); if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_OOP) @@ -1137,7 +1191,7 @@ static moo_uint8_t* scan_heap_space (moo_t* moo, moo_uint8_t* ptr, moo_uint8_t** { /* i must not use MOO_STORE_OOP() as this operation is * part of garbage collection. */ - tmp = moo_moveoop(moo, tmp); + tmp = moo_updateoopforgc(moo, tmp); MOO_OBJ_SET_OOP_VAL (oop, i, tmp); } } @@ -1170,7 +1224,7 @@ static moo_uint8_t* scan_heap_space (moo_t* moo, moo_uint8_t* ptr, moo_uint8_t** } -static void scan_roots (moo_t* moo) +static void gc_ss_scan_roots (moo_t* moo) { /* * move a referenced object to the new heap. @@ -1206,63 +1260,63 @@ static void scan_roots (moo_t* moo) old_nil = moo->_nil; /* move _nil and the root object table */ - moo->_nil = moo_moveoop(moo, moo->_nil); - moo->_true = moo_moveoop(moo, moo->_true); - moo->_false = moo_moveoop(moo, moo->_false); + moo->_nil = moo_updateoopforgc(moo, moo->_nil); + moo->_true = moo_updateoopforgc(moo, moo->_true); + moo->_false = moo_updateoopforgc(moo, moo->_false); for (i = 0; i < MOO_COUNTOF(kernel_classes); i++) { moo_oop_t tmp; tmp = *(moo_oop_t*)((moo_uint8_t*)moo + kernel_classes[i].offset); - tmp = moo_moveoop(moo, tmp); + tmp = moo_updateoopforgc(moo, tmp); *(moo_oop_t*)((moo_uint8_t*)moo + kernel_classes[i].offset) = tmp; } - moo->sysdic = (moo_oop_nsdic_t)moo_moveoop(moo, (moo_oop_t)moo->sysdic); - moo->processor = (moo_oop_process_scheduler_t)moo_moveoop(moo, (moo_oop_t)moo->processor); - moo->nil_process = (moo_oop_process_t)moo_moveoop(moo, (moo_oop_t)moo->nil_process); - moo->dicnewsym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->dicnewsym); - moo->dicputassocsym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->dicputassocsym); - moo->does_not_understand_sym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->does_not_understand_sym); - moo->primitive_failed_sym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->primitive_failed_sym); - moo->unwindto_return_sym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->unwindto_return_sym); + moo->sysdic = (moo_oop_nsdic_t)moo_updateoopforgc(moo, (moo_oop_t)moo->sysdic); + moo->processor = (moo_oop_process_scheduler_t)moo_updateoopforgc(moo, (moo_oop_t)moo->processor); + moo->nil_process = (moo_oop_process_t)moo_updateoopforgc(moo, (moo_oop_t)moo->nil_process); + moo->dicnewsym = (moo_oop_char_t)moo_updateoopforgc(moo, (moo_oop_t)moo->dicnewsym); + moo->dicputassocsym = (moo_oop_char_t)moo_updateoopforgc(moo, (moo_oop_t)moo->dicputassocsym); + moo->does_not_understand_sym = (moo_oop_char_t)moo_updateoopforgc(moo, (moo_oop_t)moo->does_not_understand_sym); + moo->primitive_failed_sym = (moo_oop_char_t)moo_updateoopforgc(moo, (moo_oop_t)moo->primitive_failed_sym); + moo->unwindto_return_sym = (moo_oop_char_t)moo_updateoopforgc(moo, (moo_oop_t)moo->unwindto_return_sym); for (i = 0; i < moo->sem_list_count; i++) { - moo->sem_list[i] = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_list[i]); + moo->sem_list[i] = (moo_oop_semaphore_t)moo_updateoopforgc(moo, (moo_oop_t)moo->sem_list[i]); } for (i = 0; i < moo->sem_heap_count; i++) { - moo->sem_heap[i] = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_heap[i]); + moo->sem_heap[i] = (moo_oop_semaphore_t)moo_updateoopforgc(moo, (moo_oop_t)moo->sem_heap[i]); } for (i = 0; i < moo->sem_io_tuple_count; i++) { if (moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT]) - moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT] = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT]); + moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT] = (moo_oop_semaphore_t)moo_updateoopforgc(moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_INPUT]); if (moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT]) - moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT] = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT]); + moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT] = (moo_oop_semaphore_t)moo_updateoopforgc(moo, (moo_oop_t)moo->sem_io_tuple[i].sem[MOO_SEMAPHORE_IO_TYPE_OUTPUT]); } - moo->sem_gcfin = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_gcfin); + moo->sem_gcfin = (moo_oop_semaphore_t)moo_updateoopforgc(moo, (moo_oop_t)moo->sem_gcfin); for (i = 0; i < moo->proc_map_capa; i++) { - moo->proc_map[i] = moo_moveoop(moo, moo->proc_map[i]); + moo->proc_map[i] = moo_updateoopforgc(moo, moo->proc_map[i]); } for (i = 0; i < moo->volat_count; i++) { - *moo->volat_stack[i] = moo_moveoop(moo, *moo->volat_stack[i]); + *moo->volat_stack[i] = moo_updateoopforgc(moo, *moo->volat_stack[i]); } if (moo->initial_context) - moo->initial_context = (moo_oop_context_t)moo_moveoop(moo, (moo_oop_t)moo->initial_context); + moo->initial_context = (moo_oop_context_t)moo_updateoopforgc(moo, (moo_oop_t)moo->initial_context); if (moo->active_context) - moo->active_context = (moo_oop_context_t)moo_moveoop(moo, (moo_oop_t)moo->active_context); + moo->active_context = (moo_oop_context_t)moo_updateoopforgc(moo, (moo_oop_t)moo->active_context); if (moo->active_method) - moo->active_method = (moo_oop_method_t)moo_moveoop(moo, (moo_oop_t)moo->active_method); + moo->active_method = (moo_oop_method_t)moo_updateoopforgc(moo, (moo_oop_t)moo->active_method); moo_rbt_walk (&moo->modtab, call_module_gc, moo); @@ -1272,16 +1326,16 @@ static void scan_roots (moo_t* moo) } /* scan the objects in the permspace in case an object there points to an object outside the permspace */ - scan_heap_space (moo, (moo_uint8_t*)MOO_ALIGN((moo_uintptr_t)moo->heap->permspace.base, MOO_SIZEOF(moo_oop_t)), &moo->heap->permspace.ptr); + gc_ss_scan_space (moo, (moo_uint8_t*)MOO_ALIGN((moo_uintptr_t)moo->heap->permspace.base, MOO_SIZEOF(moo_oop_t)), &moo->heap->permspace.ptr); /* scan the new heap to move referenced objects */ - newspace_scan_ptr = scan_heap_space(moo, newspace_scan_ptr, &moo->heap->newspace.ptr); + newspace_scan_ptr = gc_ss_scan_space(moo, newspace_scan_ptr, &moo->heap->newspace.ptr); /* check finalizable objects registered and scan the heap again. * symbol table compation is placed after this phase assuming that * no symbol is added to be finalized. */ gcfin_count = move_finalizable_objects(moo); - newspace_scan_ptr = scan_heap_space(moo, newspace_scan_ptr, &moo->heap->newspace.ptr); + newspace_scan_ptr = gc_ss_scan_space(moo, newspace_scan_ptr, &moo->heap->newspace.ptr); /* traverse the symbol table for unreferenced symbols. * if the symbol has not moved to the new heap, the symbol @@ -1290,12 +1344,12 @@ static void scan_roots (moo_t* moo) /*if (!moo->igniting) */ compact_symbol_table (moo, old_nil); /* move the symbol table itself */ - moo->symtab = (moo_oop_dic_t)moo_moveoop(moo, (moo_oop_t)moo->symtab); + moo->symtab = (moo_oop_dic_t)moo_updateoopforgc(moo, (moo_oop_t)moo->symtab); /* scan the new heap again from the end position of * the previous scan to move referenced objects by * the symbol table. */ - newspace_scan_ptr = scan_heap_space(moo, newspace_scan_ptr, &moo->heap->newspace.ptr); + newspace_scan_ptr = gc_ss_scan_space(moo, newspace_scan_ptr, &moo->heap->newspace.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 @@ -1338,37 +1392,48 @@ static void scan_roots (moo_t* moo) } -void moo_gc (moo_t* moo) +void moo_gc (moo_t* moo, int full) { #if defined(MOO_ENABLE_GC_MARK_SWEEP) if (moo->gc_type == MOO_GC_TYPE_MARK_SWEEP) { MOO_LOG1 (moo, MOO_LOG_GC | MOO_LOG_INFO, "Starting GC (mark-sweep) - gci.bsz = %zu\n", moo->gci.bsz); + moo->gci.stack.len = 0; /*moo->gci.stack.max = 0;*/ - gc_mark_root (moo); - gc_sweep (moo); + gc_ms_mark_roots (moo); + + if (!full && moo->gci.lazy_sweep) + { + moo->gci.ls.prev = MOO_NULL; + moo->gci.ls.curr = moo->gci.b; + } + else + { + gc_ms_sweep (moo); + } + MOO_LOG2 (moo, MOO_LOG_GC | MOO_LOG_INFO, "Finished GC (mark-sweep) - gci.bsz = %zu, gci.stack.max %zu\n", moo->gci.bsz, moo->gci.stack.max); } else #endif { - scan_roots (moo); + gc_ss_scan_roots (moo); } } -moo_oop_t moo_moveoop (moo_t* moo, moo_oop_t oop) +moo_oop_t moo_updateoopforgc (moo_t* moo, moo_oop_t oop) { #if defined(MOO_ENABLE_GC_MARK_SWEEP) if (moo->gc_type == MOO_GC_TYPE_MARK_SWEEP) { - gc_mark (moo, oop); + gc_ms_mark (moo, oop); return oop; } else #endif { - return move_oop_in_heap_space(moo, oop); + return gc_ss_move_oop(moo, oop); } } @@ -1502,7 +1567,7 @@ static moo_oow_t move_finalizable_objects (moo_t* moo) 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_updateoopforgc(moo, x->oop); } for (x = moo->finalizable.first; x; ) @@ -1522,7 +1587,7 @@ static moo_oow_t move_finalizable_objects (moo_t* moo) * however this is quite unlikely because some key objects for VM execution * like context objects doesn't require finalization. */ - x->oop = moo_moveoop(moo, x->oop); + x->oop = moo_updateoopforgc(moo, x->oop); /* remove it from the finalizable list */ MOO_DELETE_FROM_LIST (&moo->finalizable, x); @@ -1534,7 +1599,7 @@ static moo_oow_t move_finalizable_objects (moo_t* moo) } else { - x->oop = moo_moveoop(moo, x->oop); + x->oop = moo_updateoopforgc(moo, x->oop); } x = y; diff --git a/moo/lib/heap.c b/moo/lib/heap.c index dd414f8..f5552d0 100644 --- a/moo/lib/heap.c +++ b/moo/lib/heap.c @@ -55,7 +55,7 @@ moo_heap_t* moo_makeheap (moo_t* moo, moo_oow_t size) if (MOO_UNLIKELY(!heap)) { const moo_ooch_t* oldmsg = moo_backuperrmsg(moo); - moo_seterrbfmt (moo, moo_geterrnum(moo), "unable to allocate heap - %js", oldmsg); + moo_seterrbfmt (moo, moo_geterrnum(moo), "unable to allocate a heap - %js", oldmsg); return MOO_NULL; } diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 9221a48..0724b19 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -276,7 +276,7 @@ void moo_fini (moo_t* moo) } while (moo->gci.b); - MOO_ASSERT (moo, moo->gci.bsz == 0); + MOO_ASSERT (moo, moo->gci.bsz == 0); } if (moo->gci.stack.ptr) diff --git a/moo/lib/moo.h b/moo/lib/moo.h index d0ef763..dfe6643 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1816,15 +1816,20 @@ struct moo_t struct { moo_gchdr_t* b; /* object blocks allocated */ + struct + { + moo_gchdr_t* curr; + moo_gchdr_t* prev; + } ls; moo_oow_t bsz; /* total size of object blocks allocated */ moo_oow_t threshold; + int lazy_sweep; struct { moo_oop_t* ptr; moo_oow_t capa; moo_oow_t len; - moo_oow_t max; } stack; } gci; @@ -2219,15 +2224,16 @@ MOO_EXPORT void moo_deregevtcb ( * It is not affected by #MOO_TRAIT_NOGC. */ MOO_EXPORT void moo_gc ( - moo_t* moo + moo_t* moo, + int full ); /** - * The moo_moveoop() function moves an object and returns an updated pointer - * after having moved. it must be called in the GC callback context only. + * The moo_updateoopforgc() function moves an object and returns an updated pointer + * after having moved. It must be called in the GC callback context only. */ -MOO_EXPORT moo_oop_t moo_moveoop ( +MOO_EXPORT moo_oop_t moo_updateoopforgc ( moo_t* moo, moo_oop_t oop ); diff --git a/moo/lib/obj.c b/moo/lib/obj.c index 220a4cc..ea47319 100644 --- a/moo/lib/obj.c +++ b/moo/lib/obj.c @@ -30,7 +30,7 @@ void* moo_allocbytes (moo_t* moo, moo_oow_t size) { #if defined(MOO_BUILD_DEBUG) /* DEBUG_GC is set but NOGC is not set */ - if ((moo->option.trait & (MOO_TRAIT_DEBUG_GC | MOO_TRAIT_NOGC)) == MOO_TRAIT_DEBUG_GC) moo_gc (moo); + if ((moo->option.trait & (MOO_TRAIT_DEBUG_GC | MOO_TRAIT_NOGC)) == MOO_TRAIT_DEBUG_GC) moo_gc (moo, 1); #endif #if defined(MOO_ENABLE_GC_MARK_SWEEP) @@ -45,19 +45,37 @@ void* moo_allocbytes (moo_t* moo, moo_oow_t size) } else { + moo_oow_t allocsize; + if (moo->gci.bsz >= moo->gci.threshold) { - moo_gc (moo); + moo_gc (moo, 0); moo->gci.threshold = moo->gci.bsz + 100000; /* TODO: change this fomula */ } - gch = (moo_gchdr_t*)moo_callocheapmem(moo, moo->heap, MOO_SIZEOF(*gch) + size); + allocsize = MOO_SIZEOF(*gch) + size; + if (moo->gci.lazy_sweep) moo_gc_ms_sweep_lazy (moo, allocsize); + + gch = (moo_gchdr_t*)moo_callocheapmem(moo, moo->heap, allocsize); if (!gch && moo->errnum == MOO_EOOMEM && !(moo->option.trait & MOO_TRAIT_NOGC)) { - moo_gc (moo); - MOO_LOG0 (moo, MOO_LOG_GC | MOO_LOG_INFO, "GC completed\n"); /* TODO: add more inforamtion */ - gch = (moo_gchdr_t*)moo_callocheapmem(moo, moo->heap, MOO_SIZEOF(*gch) + size); - if (MOO_UNLIKELY(!gch)) return MOO_NULL; + moo_gc (moo, 0); + if (moo->gci.lazy_sweep) moo_gc_ms_sweep_lazy (moo, allocsize); + + gch = (moo_gchdr_t*)moo_callocheapmem(moo, moo->heap, allocsize); + if (MOO_UNLIKELY(!gch)) + { + if (moo->gci.lazy_sweep) + { + moo_gc_ms_sweep_lazy (moo, MOO_TYPE_MAX(moo_oow_t)); /* sweep the rest */ + gch = (moo_gchdr_t*)moo_callocheapmem(moo, moo->heap, allocsize); + if (MOO_UNLIKELY(!gch)) return MOO_NULL; + } + else + { + return MOO_NULL; + } + } } } @@ -82,7 +100,7 @@ void* moo_allocbytes (moo_t* moo, moo_oow_t size) ptr = (moo_uint8_t*)moo_allocheapspace(moo, &moo->heap->curspace, size); if (!ptr && moo->errnum == MOO_EOOMEM && !(moo->option.trait & MOO_TRAIT_NOGC)) { - moo_gc (moo); + moo_gc (moo, 1); MOO_LOG4 (moo, MOO_LOG_GC | MOO_LOG_INFO, "GC completed - current heap ptr %p limit %p size %zd free %zd\n", moo->heap->curspace.ptr, moo->heap->curspace.limit, diff --git a/moo/lib/pf-sys.c b/moo/lib/pf-sys.c index b049812..652710a 100644 --- a/moo/lib/pf-sys.c +++ b/moo/lib/pf-sys.c @@ -239,7 +239,7 @@ moo_pfrc_t moo_pf_system_find_next_process (moo_t* moo, moo_mod_t* mod, moo_ooi_ moo_pfrc_t moo_pf_system_collect_garbage (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) { - moo_gc (moo); + moo_gc (moo, 1); MOO_STACK_SETRETTORCV (moo, nargs); return MOO_PF_SUCCESS; } diff --git a/moo/mod/sck.c b/moo/mod/sck.c index 538c04f..caad93b 100644 --- a/moo/mod/sck.c +++ b/moo/mod/sck.c @@ -615,7 +615,7 @@ static void gc_mod_sck (moo_t* moo, moo_mod_t* mod) MOO_ASSERT (moo, ctx != MOO_NULL); if (ctx->sck_class) { - ctx->sck_class = (moo_oop_class_t)moo_moveoop(moo, (moo_oop_t)ctx->sck_class); + ctx->sck_class = (moo_oop_class_t)moo_updateoopforgc(moo, (moo_oop_t)ctx->sck_class); } } diff --git a/moo/mod/x11.c b/moo/mod/x11.c index 9fec787..bf7075c 100644 --- a/moo/mod/x11.c +++ b/moo/mod/x11.c @@ -834,7 +834,7 @@ static void gc_mod_x11 (moo_t* moo, moo_mod_t* mod) x11_modctx_t* ctx = mod->ctx; MOO_ASSERT (moo, ctx != MOO_NULL); - ctx->x11_class = (moo_oop_class_t)moo_moveoop(moo, (moo_oop_t)ctx->x11_class); + ctx->x11_class = (moo_oop_class_t)moo_updateoopforgc(moo, (moo_oop_t)ctx->x11_class); } int moo_mod_x11 (moo_t* moo, moo_mod_t* mod)