some gc works

This commit is contained in:
hyung-hwan 2020-03-20 09:50:32 +00:00
parent adcbf748a2
commit f0c1a26ccc
4 changed files with 142 additions and 103 deletions

View File

@ -48,7 +48,7 @@ typedef struct hawk_tree_t hawk_tree_t;
#include "err-prv.h"
#include "misc-prv.h"
//#define HAWK_ENABLE_GC
/*#define HAWK_ENABLE_GC*/
#define HAWK_ENABLE_STR_CACHE
#define HAWK_ENABLE_MBS_CACHE
@ -395,8 +395,8 @@ struct hawk_rtx_t
{
int collecting;
hawk_oow_t all_count;
hawk_gci_t all; /* allocated objects */
hawk_gci_t saved; /* objects to preserve */
hawk_gch_t all; /* allocated objects */
hawk_gch_t saved; /* objects to preserve */
} gc;
hawk_nde_blk_t* active_block;

View File

@ -129,29 +129,29 @@ struct hawk_rtx_alt_t
/* ------------------------------------------------------------------------ */
typedef struct hawk_gci_t hawk_gci_t;
struct hawk_gci_t
typedef struct hawk_gch_t hawk_gch_t;
struct hawk_gch_t
{
hawk_gci_t* gc_prev;
hawk_gci_t* gc_next;
hawk_gch_t* gc_prev;
hawk_gch_t* gc_next;
hawk_uintptr_t gc_refs;
};
#if defined(HAWK_HAVE_INLINE)
static HAWK_INLINE hawk_val_t* hawk_gci_to_val(hawk_gci_t* gci)
static HAWK_INLINE hawk_val_t* hawk_gch_to_val(hawk_gch_t* gch)
{
return (hawk_val_t*)(gci + 1);
return (hawk_val_t*)(gch + 1);
}
static HAWK_INLINE hawk_gci_t* hawk_val_to_gci(hawk_val_t* v)
static HAWK_INLINE hawk_gch_t* hawk_val_to_gch(hawk_val_t* v)
{
return ((hawk_gci_t*)v) - 1;
return ((hawk_gch_t*)v) - 1;
}
#else
# define hawk_val_to_gci(v) (((hawk_gci_t*)(v)) - 1)
# define hawk_gci_to_val(gci) ((hawk_val_t*)(((hawk_gci_t*)(gci)) + 1))
# define hawk_val_to_gch(v) (((hawk_gch_t*)(v)) - 1)
# define hawk_gch_to_val(gch) ((hawk_val_t*)(((hawk_gch_t*)(gch)) + 1))
#endif
/**

View File

@ -3599,12 +3599,14 @@ static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t*
case HAWK_NDE_GBLIDX:
case HAWK_NDE_LCLIDX:
case HAWK_NDE_ARGIDX:
#if !defined(HAWK_ENABLE_GC)
if (HAWK_RTX_GETVALTYPE(rtx, val) == HAWK_VAL_MAP)
{
/* a map cannot become a member of a map */
errnum = HAWK_EMAPTOIDX;
goto exit_on_error;
}
#endif
ret = do_assignment_idx(rtx, (hawk_nde_var_t*)var, val);
break;
@ -3666,7 +3668,6 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOSCALAR, HAWK_T("not allowed to change a map '%.*js' to a scalar"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL;
}
#if !defined(HAWK_ENABLE_GC)
else if (vtype == HAWK_VAL_MAP)
{
/* old value is not a map but a new value is a map.
@ -3674,7 +3675,6 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOVAR, HAWK_T("not allowed to assign a map to a variable '%.*js'"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL;
}
#endif
}
if (hawk_htb_upsert(rtx->named, var->id.name.ptr, var->id.name.len, val, 0) == HAWK_NULL)
@ -3712,7 +3712,6 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOSCALAR, HAWK_T("not allowed to change a map '%.*js' to a scalar"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL;
}
#if !defined(HAWK_ENABLE_GC)
else if (vtype == HAWK_VAL_MAP)
{
/* old value is not a map but a new value is a map.
@ -3720,7 +3719,6 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOVAR, HAWK_T("not allowed to assign a map to a variable '%.*js'"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL;
}
#endif
}
hawk_rtx_refdownval (rtx, old);
@ -3744,7 +3742,6 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOSCALAR, HAWK_T("not allowed to change a map '%.*js' to a scalar"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL;
}
#if !defined(HAWK_ENABLE_GC)
else if (vtype == HAWK_VAL_MAP)
{
/* old value is not a map but a new value is a map.
@ -3752,7 +3749,6 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOVAR, HAWK_T("not allowed to assign a map to a variable '%.*js'"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL;
}
#endif
}
hawk_rtx_refdownval (rtx, old);
@ -3779,7 +3775,9 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk
var->type == HAWK_NDE_GBLIDX ||
var->type == HAWK_NDE_LCLIDX ||
var->type == HAWK_NDE_ARGIDX) && var->idx != HAWK_NULL);
#if !defined(HAWK_ENABLE_GC)
HAWK_ASSERT (HAWK_RTX_GETVALTYPE (rtx, val) != HAWK_VAL_MAP);
#endif
retry:
switch (var->type)

View File

@ -39,65 +39,91 @@ hawk_val_t* hawk_val_zlm = (hawk_val_t*)&awk_zlm;
/* --------------------------------------------------------------------- */
#define GCI_MOVED HAWK_TYPE_MAX(hawk_uintptr_t)
#if defined(HAWK_ENABLE_GC)
/*
BEGIN {
@local a, b, nil;
for (i = 1; i < 10; i++) a[i] = i;
a[11] = a;
a[12] = a;
a = nil;
b[1] = a;
c[1] = 0;
} */
#define GCH_MOVED HAWK_TYPE_MAX(hawk_uintptr_t)
static hawk_val_t* gc_calloc (hawk_rtx_t* rtx, hawk_oow_t size)
{
hawk_gci_t* gci;
hawk_gch_t* gch;
gci = (hawk_gci_t*)hawk_rtx_callocmem(rtx, HAWK_SIZEOF(*gci) + size);
if (HAWK_UNLIKELY(!gci)) return HAWK_NULL;
gch = (hawk_gch_t*)hawk_rtx_callocmem(rtx, HAWK_SIZEOF(*gch) + size);
if (HAWK_UNLIKELY(!gch)) return HAWK_NULL;
return hawk_gci_to_val(gci);
return hawk_gch_to_val(gch);
}
static HAWK_INLINE void gc_chain_gci (hawk_gci_t* list, hawk_gci_t* gci)
static HAWK_INLINE void gc_chain_gch (hawk_gch_t* list, hawk_gch_t* gch)
{
gci->gc_next = list;
gci->gc_prev = list->gc_prev;
gci->gc_prev->gc_next = gci;
list->gc_prev = gci;
gch->gc_next = list;
gch->gc_prev = list->gc_prev;
gch->gc_prev->gc_next = gch;
list->gc_prev = gch;
}
static HAWK_INLINE void gc_chain_val (hawk_gci_t* list, hawk_val_t* v)
static HAWK_INLINE void gc_chain_val (hawk_gch_t* list, hawk_val_t* v)
{
gc_chain_gci (list, hawk_val_to_gci(v));
gc_chain_gch (list, hawk_val_to_gch(v));
}
static HAWK_INLINE void gc_unchain_gci (hawk_gci_t* gci)
static HAWK_INLINE void gc_move_gchs (hawk_gch_t* list, hawk_gch_t* src)
{
gci->gc_prev->gc_next = gci->gc_next;
gci->gc_next->gc_prev = gci->gc_prev;
if (list->gc_next != list)
{
hawk_gch_t* last;
last = list->gc_prev;
last->gc_next = src->gc_next;
last->gc_next->gc_prev = last;
list->gc_prev = src->gc_prev;
list->gc_prev->gc_next = list;
}
src->gc_prev = src;
src->gc_next = src;
}
static HAWK_INLINE void gc_unchain_gch (hawk_gch_t* gch)
{
gch->gc_prev->gc_next = gch->gc_next;
gch->gc_next->gc_prev = gch->gc_prev;
}
static HAWK_INLINE void gc_unchain_val (hawk_val_t* v)
{
gc_unchain_gci (hawk_val_to_gci(v));
gc_unchain_gch (hawk_val_to_gch(v));
}
static void gc_clone_refs (hawk_gci_t* list)
static void gc_trace_refs (hawk_gch_t* list)
{
hawk_gci_t* gci;
gci = list->gc_next;
while (gci != list)
{
gci->gc_refs = hawk_gci_to_val(gci)->v_refs;
gci = gci->gc_next;
}
}
static void gc_trace_refs (hawk_gci_t* list)
{
hawk_gci_t* gci;
hawk_gch_t* gch;
hawk_val_t* v, * iv;
hawk_map_itr_t itr;
hawk_map_pair_t* pair;
gci = list->gc_next;
while (gci != list)
/* phase 1 - copy the reference count field from the value header to the gc header */
gch = list->gc_next;
while (gch != list)
{
v = hawk_gci_to_val(gci);
gch->gc_refs = hawk_gch_to_val(gch)->v_refs;
gch = gch->gc_next;
}
/* phase 2 - decrement the reference count in the gc header whenever a reference is found */
gch = list->gc_next;
while (gch != list)
{
v = hawk_gch_to_val(gch);
/* as of now, there is only one type available - HAWK_VAL_MAP */
HAWK_ASSERT (v->v_type == HAWK_VAL_MAP);
@ -108,58 +134,52 @@ static void gc_trace_refs (hawk_gci_t* list)
iv = (hawk_val_t*)HAWK_MAP_VPTR(pair);
if (HAWK_VTR_IS_POINTER(iv) && iv->v_gc)
{
printf ("decrementing...\n");
hawk_val_to_gci(iv)->gc_refs--;
hawk_val_to_gch(iv)->gc_refs--;
}
pair = hawk_map_getnextpair(((hawk_val_map_t*)v)->map, &itr);
}
gci = gci->gc_next;
gch = gch->gc_next;
}
}
static void gc_dump_refs (hawk_rtx_t* rtx, hawk_gci_t* list)
static void gc_dump_refs (hawk_rtx_t* rtx, hawk_gch_t* list)
{
hawk_gci_t* gci;
hawk_gch_t* gch;
gci = list->gc_next;
while (gci != list)
gch = list->gc_next;
while (gch != list)
{
printf (" %p %d\n", gci, (int)gci->gc_refs);
gci = gci->gc_next;
printf (" %p %d\n", gch, (int)gch->gc_refs);
gch = gch->gc_next;
}
printf ("-----all_count => %d---------\n\n", (int)rtx->gc.all_count);
}
static void gc_move_roots (hawk_gci_t* list, hawk_gci_t* reachable_list)
static void gc_move_reachables (hawk_gch_t* list, hawk_gch_t* reachable_list)
{
hawk_gci_t* gci, * next;
gci = list->gc_next;
while (gci != list)
{
next = gci->gc_next;
if (gci->gc_refs > 0)
{
gc_unchain_gci (gci);
gc_chain_gci (reachable_list, gci);
gci->gc_refs = GCI_MOVED;
}
gci = next;
}
}
static void gc_move_reachables_from_root (hawk_gci_t* reachable_list)
{
hawk_gci_t* gci, * igci;
hawk_gch_t* gch, * tmp;
hawk_val_t* v, * iv;
hawk_map_itr_t itr;
hawk_map_pair_t* pair;
gci = reachable_list->gc_next;
while (gci != reachable_list)
gch = list->gc_next;
while (gch != list)
{
v = hawk_gci_to_val(gci);
tmp = gch->gc_next;
if (gch->gc_refs > 0)
{
gc_unchain_gch (gch);
gc_chain_gch (reachable_list, gch);
gch->gc_refs = GCH_MOVED;
}
gch = tmp;
}
gch = reachable_list->gc_next;
while (gch != reachable_list)
{
v = hawk_gch_to_val(gch);
/* as of now, there is only one type available - HAWK_VAL_MAP */
/* the key part is a string. don't care. but if a generic value is allowed as a key, this should change... */
@ -171,42 +191,58 @@ static void gc_move_reachables_from_root (hawk_gci_t* reachable_list)
iv = (hawk_val_t*)HAWK_MAP_VPTR(pair);
if (HAWK_VTR_IS_POINTER(iv) && iv->v_gc)
{
igci = hawk_val_to_gci(iv);
if (igci->gc_refs != GCI_MOVED)
tmp = hawk_val_to_gch(iv);
if (tmp->gc_refs != GCH_MOVED)
{
gc_unchain_gci (igci);
gc_chain_gci (reachable_list, igci);
igci->gc_refs = GCI_MOVED;
gc_unchain_gch (tmp);
gc_chain_gch (reachable_list, tmp);
tmp->gc_refs = GCH_MOVED;
}
}
pair = hawk_map_getnextpair(((hawk_val_map_t*)v)->map, &itr);
}
gci = gci->gc_next;
gch = gch->gc_next;
}
}
static void gc_free_unreachables (hawk_rtx_t* rtx, hawk_gch_t* list)
{
hawk_gch_t* gch, * tmp;
gch = list->gc_next;
while (gch != list)
{
tmp = gch->gc_next;
printf ("^^^^^^^^^^^^^^^^^^^^^^^^ freeing %p(%p) gc_refs %d v_refs %d\n", gch, gch->gc_refs, hawk_gch_to_val(gch)->v_refs);
hawk_rtx_freeval (rtx, hawk_gch_to_val(gch), 0);
gch = tmp;
}
}
void gc_collect_garbage (hawk_rtx_t* rtx)
{
hawk_gci_t reachable;
hawk_gch_t reachable;
gc_clone_refs (&rtx->gc.all);
printf ("collecting garbage...\n");
gc_trace_refs (&rtx->gc.all);
gc_dump_refs (rtx, &rtx->gc.all);
/*reachable.gc_prev = &reachable;
reachable.gc_prev = &reachable;
reachable.gc_next = &reachable;
gc_move_roots (&rtx->gc.all, &reachable);*/
/*
gc_move_reachables_from_root (&reachable, &reachable);
gc_move_reachables (&rtx->gc.all, &reachable);
/* only unreachables are left in rtx->gc.all */
gc_dump_refs (rtx, &rtx->gc.all);
gc_free_unreachables (rtx, &rtx->gc.all);
HAWK_ASSERT (rtx->gc.all.gc_next == &rtx->gc.all);
destroy_all_in_ rtx->gc.all
move_reachable_back_to rtx->gc.all???*/
gc_move_gchs (&rtx->gc.all, &reachable);
printf ("collecting garbage.done ..\n");
}
#endif
/* --------------------------------------------------------------------- */
hawk_val_t* hawk_get_awk_nil_val (void)
@ -694,6 +730,11 @@ static void free_mapval (hawk_map_t* map, void* dptr, hawk_oow_t dlen)
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("refdown in map free - [%O]\n"), dptr);
#endif
#if defined(HAWK_ENABLE_GC)
/* this part is not right i think.... revisit this ... */
if (HAWK_RTX_GETVALTYPE(rtx, (hawk_val_t*)dptr) == HAWK_VAL_MAP &&
((hawk_val_map_t*)dptr)->map == map) return;
#endif
hawk_rtx_refdownval (rtx, dptr);
}
@ -1055,7 +1096,7 @@ void hawk_rtx_freeval (hawk_rtx_t* rtx, hawk_val_t* val, int cache)
/* don't free ptr as it is inlined to val
hawk_rtx_freemem (rtx, ((hawk_val_rex_t*)val)->ptr);
*/
/* code is just a pointer to a regular expression stored
* in parse tree nodes. so don't free it.
hawk_freerex (rtx->hawk, ((hawk_val_rex_t*)val)->code[0], ((hawk_val_rex_t*)val)->code[1]);
@ -1074,7 +1115,7 @@ void hawk_rtx_freeval (hawk_rtx_t* rtx, hawk_val_t* val, int cache)
rtx->gc.all_count--;
gc_unchain_val (val);
hawk_map_fini (((hawk_val_map_t*)val)->map);
hawk_rtx_freemem (rtx, hawk_val_to_gci(val));
hawk_rtx_freemem (rtx, hawk_val_to_gch(val));
#else
hawk_map_fini (((hawk_val_map_t*)val)->map);
hawk_rtx_freemem (rtx, val);