*fixed a gc issue.

This commit is contained in:
paladin-t 2016-03-01 16:55:33 +08:00
parent 32e93a758c
commit ae3cfb63f4
2 changed files with 57 additions and 44 deletions

View File

@ -563,6 +563,7 @@ typedef struct _object_t {
_import_info_t* import_info;
#endif /* MB_ENABLE_SOURCE_TRACE */
mb_val_bytes_t bytes;
void* pointer;
_raw_t raw;
} data;
bool_t ref;
@ -1440,6 +1441,7 @@ static char* _extract_string(_object_t* obj);
default: break; \
}
#define _ADDGC(__o, __g) \
if(!(__o)->data.pointer || !_ht_find((__g)->collected_table, (__o)->data.pointer)) { \
switch((__o)->type) { \
_ADDGC_USERTYPE_REF(__o, __g) \
_ADDGC_ARRAY(__o, __g) \
@ -1449,6 +1451,7 @@ static char* _extract_string(_object_t* obj);
_ADDGC_ROUTINE(__o, __g) \
_ADDGC_STRING(__o) \
default: break; \
} \
}
static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
@ -1466,18 +1469,18 @@ static void _gc_add(_ref_t* ref, void* data, _gc_t* gc);
static void _gc_remove(_ref_t* ref, void* data);
static int _gc_add_reachable(void* data, void* extra, void* ht);
static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht);
static int _gc_destroy_garbage_in_list(void* data, void* extra, void* gc);
static int _gc_destroy_garbage_in_dict(void* data, void* extra, void* gc);
static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc);
static int _gc_destroy_garbage_in_dict(void* data, void* extra, _gc_t* gc);
#ifdef MB_ENABLE_CLASS
static int _gc_destroy_garbage_in_class(void* data, void* extra, void* gc);
static int _gc_destroy_garbage_in_class(void* data, void* extra, _gc_t* gc);
#endif /* MB_ENABLE_CLASS */
#ifdef MB_ENABLE_LAMBDA
static int _gc_destroy_garbage_in_lambda(void* data, void* extra, void* gc);
static int _gc_destroy_garbage_in_lambda(void* data, void* extra, _gc_t* gc);
static void _gc_destroy_garbage_in_outer_scope(_running_context_ref_t* p, _gc_t* gc);
#endif /* MB_ENABLE_LAMBDA */
static int _gc_destroy_garbage(void* data, void* extra);
static int _gc_destroy_garbage(void* data, void* extra, _gc_t* gc);
#ifdef MB_ENABLE_CLASS
static int _gc_destroy_garbage_class(void* data, void* extra);
static int _gc_destroy_garbage_class(void* data, void* extra, _gc_t* gc);
#endif /* MB_ENABLE_CLASS */
static void _gc_swap_tables(mb_interpreter_t* s);
static void _gc_try_trigger(mb_interpreter_t* s);
@ -5543,17 +5546,16 @@ static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht) {
}
}
static int _gc_destroy_garbage_in_list(void* data, void* extra, void* gc) {
static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc) {
/* Destroy only the capsule (wrapper) of an object, leave the data behind, and add it to GC if possible */
int result = _OP_RESULT_NORMAL;
_object_t* obj = 0;
_gc_t* _gc = (_gc_t*)gc;
mb_unrefvar(extra);
mb_assert(data);
obj = (_object_t*)data;
_ADDGC(obj, _gc);
_ADDGC(obj, gc);
safe_free(obj);
result = _OP_RESULT_DEL_NODE;
@ -5561,20 +5563,19 @@ static int _gc_destroy_garbage_in_list(void* data, void* extra, void* gc) {
return result;
}
static int _gc_destroy_garbage_in_dict(void* data, void* extra, void* gc) {
static int _gc_destroy_garbage_in_dict(void* data, void* extra, _gc_t* gc) {
/* Destroy only the capsule (wrapper) of an object, leave the data behind, deal with extra as well, and add it to GC if possible */
int result = _OP_RESULT_NORMAL;
_object_t* obj = 0;
_gc_t* _gc = (_gc_t*)gc;
mb_assert(data);
obj = (_object_t*)data;
_ADDGC(obj, _gc);
_ADDGC(obj, gc);
safe_free(obj);
obj = (_object_t*)extra;
_ADDGC(obj, _gc);
_ADDGC(obj, gc);
safe_free(obj);
result = _OP_RESULT_DEL_NODE;
@ -5583,11 +5584,10 @@ static int _gc_destroy_garbage_in_dict(void* data, void* extra, void* gc) {
}
#ifdef MB_ENABLE_CLASS
static int _gc_destroy_garbage_in_class(void* data, void* extra, void* gc) {
static int _gc_destroy_garbage_in_class(void* data, void* extra, _gc_t* gc) {
/* Destroy only the capsule (wrapper) of an object, leave the data behind, deal with extra as well, and add it to GC if possible */
int result = _OP_RESULT_NORMAL;
_object_t* obj = 0;
_gc_t* _gc = (_gc_t*)gc;
mb_unrefvar(extra);
mb_assert(data);
@ -5598,7 +5598,7 @@ static int _gc_destroy_garbage_in_class(void* data, void* extra, void* gc) {
safe_free(obj->data.variable->name);
safe_free(obj->data.variable);
} else {
_ADDGC(obj, _gc);
_ADDGC(obj, gc);
}
safe_free(obj);
@ -5609,11 +5609,10 @@ static int _gc_destroy_garbage_in_class(void* data, void* extra, void* gc) {
#endif /* MB_ENABLE_CLASS */
#ifdef MB_ENABLE_LAMBDA
static int _gc_destroy_garbage_in_lambda(void* data, void* extra, void* gc) {
static int _gc_destroy_garbage_in_lambda(void* data, void* extra, _gc_t* gc) {
/* Destroy only the capsule (wrapper) of an object, leave the data behind, deal with extra as well, and add it to GC if possible */
int result = _OP_RESULT_NORMAL;
_object_t* obj = 0;
_gc_t* _gc = (_gc_t*)gc;
mb_unrefvar(extra);
mb_assert(data);
@ -5624,7 +5623,7 @@ static int _gc_destroy_garbage_in_lambda(void* data, void* extra, void* gc) {
safe_free(obj->data.variable->name);
safe_free(obj->data.variable);
} else {
_ADDGC(obj, _gc);
_ADDGC(obj, gc);
}
safe_free(obj);
@ -5644,11 +5643,11 @@ static void _gc_destroy_garbage_in_outer_scope(_running_context_ref_t* p, _gc_t*
}
#endif /* MB_ENABLE_LAMBDA */
static int _gc_destroy_garbage(void* data, void* extra) {
static int _gc_destroy_garbage(void* data, void* extra, _gc_t* gc) {
/* Destroy a garbage */
int result = _OP_RESULT_NORMAL;
_gc_t* gc = 0;
_ref_t* ref = 0;
bool_t proc = true;
bool_t cld = false;
#ifdef MB_ENABLE_COLLECTION_LIB
_list_t* lst = 0;
@ -5661,7 +5660,8 @@ static int _gc_destroy_garbage(void* data, void* extra) {
mb_assert(data && extra);
ref = (_ref_t*)extra;
gc = &ref->s->gc;
if(_ht_find(gc->collected_table, ref))
goto _exit;
switch(ref->type) {
#ifdef MB_ENABLE_COLLECTION_LIB
case _DT_LIST:
@ -5690,34 +5690,41 @@ static int _gc_destroy_garbage(void* data, void* extra) {
break;
#endif /* MB_ENABLE_LAMBDA */
default: /* Do nothing */
default:
proc = false;
break;
}
if(ref->count) {
if(proc && ref->count) {
cld = *ref->count == _NONE_REF + 1;
_unref(ref, data);
if(cld)
if(cld) {
_ht_set_or_insert(gc->collected_table, ref, data);
_ht_set_or_insert(gc->collected_table, data, ref);
}
}
_exit:
if(proc)
result = _OP_RESULT_DEL_NODE;
return result;
}
#ifdef MB_ENABLE_CLASS
static int _gc_destroy_garbage_class(void* data, void* extra) {
static int _gc_destroy_garbage_class(void* data, void* extra, _gc_t* gc) {
/* Destroy a class instance garbage */
int result = _OP_RESULT_NORMAL;
_gc_t* gc = 0;
_ref_t* ref = 0;
bool_t proc = true;
bool_t cld = false;
_class_t* instance = 0;
mb_assert(data && extra);
ref = (_ref_t*)extra;
gc = &ref->s->gc;
if(_ht_find(gc->collected_table, ref))
goto _exit;
switch(ref->type) {
case _DT_CLASS:
instance = (_class_t*)data;
@ -5732,16 +5739,22 @@ static int _gc_destroy_garbage_class(void* data, void* extra) {
#endif /* MB_ENABLE_LAMBDA */
break;
default: /* Do nothing */
default:
proc = false;
break;
}
if(ref->count) {
if(proc && ref->count) {
cld = *ref->count == _NONE_REF + 1;
_unref(ref, data);
if(cld)
if(cld) {
_ht_set_or_insert(gc->collected_table, ref, data);
_ht_set_or_insert(gc->collected_table, data, ref);
}
}
_exit:
if(proc)
result = _OP_RESULT_DEL_NODE;
return result;
@ -5789,9 +5802,9 @@ static void _gc_collect_garbage(mb_interpreter_t* s, int depth) {
/* Collect garbage */
do {
#ifdef MB_ENABLE_CLASS
_ht_foreach(s->gc.table, _gc_destroy_garbage_class);
_HT_FOREACH(s->gc.table, _do_nothing_on_object, _gc_destroy_garbage_class, &s->gc);
#endif /* MB_ENABLE_CLASS */
_ht_foreach(s->gc.table, _gc_destroy_garbage);
_HT_FOREACH(s->gc.table, _do_nothing_on_object, _gc_destroy_garbage, &s->gc);
_ht_clear(s->gc.table);
if(s->gc.collecting > 1)
s->gc.collecting--;

Binary file not shown.