*fixed a gc issue.
This commit is contained in:
parent
32e93a758c
commit
ae3cfb63f4
@ -563,6 +563,7 @@ typedef struct _object_t {
|
|||||||
_import_info_t* import_info;
|
_import_info_t* import_info;
|
||||||
#endif /* MB_ENABLE_SOURCE_TRACE */
|
#endif /* MB_ENABLE_SOURCE_TRACE */
|
||||||
mb_val_bytes_t bytes;
|
mb_val_bytes_t bytes;
|
||||||
|
void* pointer;
|
||||||
_raw_t raw;
|
_raw_t raw;
|
||||||
} data;
|
} data;
|
||||||
bool_t ref;
|
bool_t ref;
|
||||||
@ -1440,6 +1441,7 @@ static char* _extract_string(_object_t* obj);
|
|||||||
default: break; \
|
default: break; \
|
||||||
}
|
}
|
||||||
#define _ADDGC(__o, __g) \
|
#define _ADDGC(__o, __g) \
|
||||||
|
if(!(__o)->data.pointer || !_ht_find((__g)->collected_table, (__o)->data.pointer)) { \
|
||||||
switch((__o)->type) { \
|
switch((__o)->type) { \
|
||||||
_ADDGC_USERTYPE_REF(__o, __g) \
|
_ADDGC_USERTYPE_REF(__o, __g) \
|
||||||
_ADDGC_ARRAY(__o, __g) \
|
_ADDGC_ARRAY(__o, __g) \
|
||||||
@ -1449,6 +1451,7 @@ static char* _extract_string(_object_t* obj);
|
|||||||
_ADDGC_ROUTINE(__o, __g) \
|
_ADDGC_ROUTINE(__o, __g) \
|
||||||
_ADDGC_STRING(__o) \
|
_ADDGC_STRING(__o) \
|
||||||
default: break; \
|
default: break; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
|
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 void _gc_remove(_ref_t* ref, void* data);
|
||||||
static int _gc_add_reachable(void* data, void* extra, void* ht);
|
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 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);
|
||||||
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);
|
||||||
#ifdef MB_ENABLE_CLASS
|
#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 */
|
#endif /* MB_ENABLE_CLASS */
|
||||||
#ifdef MB_ENABLE_LAMBDA
|
#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);
|
static void _gc_destroy_garbage_in_outer_scope(_running_context_ref_t* p, _gc_t* gc);
|
||||||
#endif /* MB_ENABLE_LAMBDA */
|
#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
|
#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 */
|
#endif /* MB_ENABLE_CLASS */
|
||||||
static void _gc_swap_tables(mb_interpreter_t* s);
|
static void _gc_swap_tables(mb_interpreter_t* s);
|
||||||
static void _gc_try_trigger(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 */
|
/* Destroy only the capsule (wrapper) of an object, leave the data behind, and add it to GC if possible */
|
||||||
int result = _OP_RESULT_NORMAL;
|
int result = _OP_RESULT_NORMAL;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
_gc_t* _gc = (_gc_t*)gc;
|
|
||||||
mb_unrefvar(extra);
|
mb_unrefvar(extra);
|
||||||
|
|
||||||
mb_assert(data);
|
mb_assert(data);
|
||||||
|
|
||||||
obj = (_object_t*)data;
|
obj = (_object_t*)data;
|
||||||
_ADDGC(obj, _gc);
|
_ADDGC(obj, gc);
|
||||||
safe_free(obj);
|
safe_free(obj);
|
||||||
|
|
||||||
result = _OP_RESULT_DEL_NODE;
|
result = _OP_RESULT_DEL_NODE;
|
||||||
@ -5561,20 +5563,19 @@ static int _gc_destroy_garbage_in_list(void* data, void* extra, void* gc) {
|
|||||||
return result;
|
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 */
|
/* 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;
|
int result = _OP_RESULT_NORMAL;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
_gc_t* _gc = (_gc_t*)gc;
|
|
||||||
|
|
||||||
mb_assert(data);
|
mb_assert(data);
|
||||||
|
|
||||||
obj = (_object_t*)data;
|
obj = (_object_t*)data;
|
||||||
_ADDGC(obj, _gc);
|
_ADDGC(obj, gc);
|
||||||
safe_free(obj);
|
safe_free(obj);
|
||||||
|
|
||||||
obj = (_object_t*)extra;
|
obj = (_object_t*)extra;
|
||||||
_ADDGC(obj, _gc);
|
_ADDGC(obj, gc);
|
||||||
safe_free(obj);
|
safe_free(obj);
|
||||||
|
|
||||||
result = _OP_RESULT_DEL_NODE;
|
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
|
#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 */
|
/* 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;
|
int result = _OP_RESULT_NORMAL;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
_gc_t* _gc = (_gc_t*)gc;
|
|
||||||
mb_unrefvar(extra);
|
mb_unrefvar(extra);
|
||||||
|
|
||||||
mb_assert(data);
|
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->name);
|
||||||
safe_free(obj->data.variable);
|
safe_free(obj->data.variable);
|
||||||
} else {
|
} else {
|
||||||
_ADDGC(obj, _gc);
|
_ADDGC(obj, gc);
|
||||||
}
|
}
|
||||||
safe_free(obj);
|
safe_free(obj);
|
||||||
|
|
||||||
@ -5609,11 +5609,10 @@ static int _gc_destroy_garbage_in_class(void* data, void* extra, void* gc) {
|
|||||||
#endif /* MB_ENABLE_CLASS */
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
|
||||||
#ifdef MB_ENABLE_LAMBDA
|
#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 */
|
/* 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;
|
int result = _OP_RESULT_NORMAL;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
_gc_t* _gc = (_gc_t*)gc;
|
|
||||||
mb_unrefvar(extra);
|
mb_unrefvar(extra);
|
||||||
|
|
||||||
mb_assert(data);
|
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->name);
|
||||||
safe_free(obj->data.variable);
|
safe_free(obj->data.variable);
|
||||||
} else {
|
} else {
|
||||||
_ADDGC(obj, _gc);
|
_ADDGC(obj, gc);
|
||||||
}
|
}
|
||||||
safe_free(obj);
|
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 */
|
#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 */
|
/* Destroy a garbage */
|
||||||
int result = _OP_RESULT_NORMAL;
|
int result = _OP_RESULT_NORMAL;
|
||||||
_gc_t* gc = 0;
|
|
||||||
_ref_t* ref = 0;
|
_ref_t* ref = 0;
|
||||||
|
bool_t proc = true;
|
||||||
bool_t cld = false;
|
bool_t cld = false;
|
||||||
#ifdef MB_ENABLE_COLLECTION_LIB
|
#ifdef MB_ENABLE_COLLECTION_LIB
|
||||||
_list_t* lst = 0;
|
_list_t* lst = 0;
|
||||||
@ -5661,7 +5660,8 @@ static int _gc_destroy_garbage(void* data, void* extra) {
|
|||||||
mb_assert(data && extra);
|
mb_assert(data && extra);
|
||||||
|
|
||||||
ref = (_ref_t*)extra;
|
ref = (_ref_t*)extra;
|
||||||
gc = &ref->s->gc;
|
if(_ht_find(gc->collected_table, ref))
|
||||||
|
goto _exit;
|
||||||
switch(ref->type) {
|
switch(ref->type) {
|
||||||
#ifdef MB_ENABLE_COLLECTION_LIB
|
#ifdef MB_ENABLE_COLLECTION_LIB
|
||||||
case _DT_LIST:
|
case _DT_LIST:
|
||||||
@ -5690,34 +5690,41 @@ static int _gc_destroy_garbage(void* data, void* extra) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* MB_ENABLE_LAMBDA */
|
#endif /* MB_ENABLE_LAMBDA */
|
||||||
default: /* Do nothing */
|
default:
|
||||||
|
proc = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(ref->count) {
|
if(proc && ref->count) {
|
||||||
cld = *ref->count == _NONE_REF + 1;
|
cld = *ref->count == _NONE_REF + 1;
|
||||||
_unref(ref, data);
|
_unref(ref, data);
|
||||||
if(cld)
|
if(cld) {
|
||||||
_ht_set_or_insert(gc->collected_table, ref, data);
|
_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;
|
result = _OP_RESULT_DEL_NODE;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MB_ENABLE_CLASS
|
#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 */
|
/* Destroy a class instance garbage */
|
||||||
int result = _OP_RESULT_NORMAL;
|
int result = _OP_RESULT_NORMAL;
|
||||||
_gc_t* gc = 0;
|
|
||||||
_ref_t* ref = 0;
|
_ref_t* ref = 0;
|
||||||
|
bool_t proc = true;
|
||||||
bool_t cld = false;
|
bool_t cld = false;
|
||||||
_class_t* instance = 0;
|
_class_t* instance = 0;
|
||||||
|
|
||||||
mb_assert(data && extra);
|
mb_assert(data && extra);
|
||||||
|
|
||||||
ref = (_ref_t*)extra;
|
ref = (_ref_t*)extra;
|
||||||
gc = &ref->s->gc;
|
if(_ht_find(gc->collected_table, ref))
|
||||||
|
goto _exit;
|
||||||
switch(ref->type) {
|
switch(ref->type) {
|
||||||
case _DT_CLASS:
|
case _DT_CLASS:
|
||||||
instance = (_class_t*)data;
|
instance = (_class_t*)data;
|
||||||
@ -5732,16 +5739,22 @@ static int _gc_destroy_garbage_class(void* data, void* extra) {
|
|||||||
#endif /* MB_ENABLE_LAMBDA */
|
#endif /* MB_ENABLE_LAMBDA */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default: /* Do nothing */
|
default:
|
||||||
|
proc = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(ref->count) {
|
if(proc && ref->count) {
|
||||||
cld = *ref->count == _NONE_REF + 1;
|
cld = *ref->count == _NONE_REF + 1;
|
||||||
_unref(ref, data);
|
_unref(ref, data);
|
||||||
if(cld)
|
if(cld) {
|
||||||
_ht_set_or_insert(gc->collected_table, ref, data);
|
_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;
|
result = _OP_RESULT_DEL_NODE;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -5789,9 +5802,9 @@ static void _gc_collect_garbage(mb_interpreter_t* s, int depth) {
|
|||||||
/* Collect garbage */
|
/* Collect garbage */
|
||||||
do {
|
do {
|
||||||
#ifdef MB_ENABLE_CLASS
|
#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 */
|
#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);
|
_ht_clear(s->gc.table);
|
||||||
if(s->gc.collecting > 1)
|
if(s->gc.collecting > 1)
|
||||||
s->gc.collecting--;
|
s->gc.collecting--;
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user