*fixed a gc bug with ranged for loop.

This commit is contained in:
Wang Renxin 2018-03-09 18:31:31 +08:00
parent 03c60e3646
commit ae4053c687
2 changed files with 58 additions and 9 deletions

View File

@ -1,3 +1,6 @@
Mar. 9 2018
Fixed a GC bug with ranged FOR loop
Jan. 15 2018 Jan. 15 2018
Fixed a crash bug with invalid collection index Fixed a crash bug with invalid collection index
Fixed a memory leak with invalid invoking Fixed a memory leak with invalid invoking
@ -14,7 +17,7 @@ Fixed a lookup issue with the mb_get_var function
Nov. 17 2017 Nov. 17 2017
Fixed an assignment issue with upvalues Fixed an assignment issue with upvalues
Fixed a variable lookup issue with a ranged FOR loop Fixed a variable lookup issue with ranged FOR loop
Nov. 16 2017 Nov. 16 2017
Fixed a clearing issue of intermediate values in forked scope chain Fixed a clearing issue of intermediate values in forked scope chain

View File

@ -1745,6 +1745,7 @@ static bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
static bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj); static bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
#endif /* _HAS_REF_OBJ_LOCK */ #endif /* _HAS_REF_OBJ_LOCK */
static bool_t _is_ref(_object_t* obj);
static _ref_count_t _ref(_ref_t* ref, void* data); static _ref_count_t _ref(_ref_t* ref, void* data);
static bool_t _unref(_ref_t* ref, void* data); static bool_t _unref(_ref_t* ref, void* data);
static _ref_count_t _weak_ref(_ref_t* ref, void* data, _ref_t* weak); static _ref_count_t _weak_ref(_ref_t* ref, void* data, _ref_t* weak);
@ -1753,7 +1754,7 @@ static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpret
static void _destroy_ref(_ref_t* ref); static void _destroy_ref(_ref_t* ref);
static void _gc_add(_ref_t* ref, void* data, _gc_t* gc); static void _gc_add(_ref_t* ref, void* data, _gc_t* gc);
static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc); static unsigned _gc_remove(_ref_t* ref, void* data, _gc_t* gc);
static int _gc_add_reachable(void* data, void* extra, void* h); static int _gc_add_reachable(void* data, void* extra, void* h);
static int _gc_add_reachable_both(void* data, void* extra, void* h); static int _gc_add_reachable_both(void* data, void* extra, void* h);
#ifdef MB_ENABLE_FORK #ifdef MB_ENABLE_FORK
@ -6237,10 +6238,43 @@ static bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj) {
} }
#endif /* _HAS_REF_OBJ_LOCK */ #endif /* _HAS_REF_OBJ_LOCK */
/* Tell whether an object is referenced */
static bool_t _is_ref(_object_t* obj) {
switch(obj->type) {
#ifdef MB_ENABLE_USERTYPE_REF
case _DT_USERTYPE_REF:
return true;
#endif /* MB_ENABLE_USERTYPE_REF */
#ifdef MB_ENABLE_ARRAY_REF
case _DT_ARRAY:
return true;
#endif /* MB_ENABLE_ARRAY_REF */
#ifdef MB_ENABLE_COLLECTION_LIB
case _DT_LIST:
return true;
case _DT_DICT:
return true;
#endif /* MB_ENABLE_COLLECTION_LIB */
#ifdef MB_ENABLE_CLASS
case _DT_CLASS:
return true;
#endif /* MB_ENABLE_CLASS */
case _DT_ROUTINE:
#ifdef MB_ENABLE_LAMBDA
return obj->data.routine->type == MB_RT_LAMBDA;
#else /* MB_ENABLE_LAMBDA */
return false;
#endif /* MB_ENABLE_LAMBDA */
default:
return false;
}
}
/* Increase the reference of a stub by 1 */ /* Increase the reference of a stub by 1 */
static _ref_count_t _ref(_ref_t* ref, void* data) { static _ref_count_t _ref(_ref_t* ref, void* data) {
_ref_count_t before = *ref->count; _ref_count_t before = *ref->count;
mb_unrefvar(data);
mb_assert((intptr_t)ref == (intptr_t)data);
++(*ref->count); ++(*ref->count);
if(before > *ref->count) { if(before > *ref->count) {
@ -6258,6 +6292,8 @@ static bool_t _unref(_ref_t* ref, void* data) {
_gc_t* gc = 0; _gc_t* gc = 0;
bool_t cld = false; bool_t cld = false;
mb_assert((intptr_t)ref == (intptr_t)data);
cld = *ref->count == _NONE_REF + 1; cld = *ref->count == _NONE_REF + 1;
do { do {
gc = &ref->s->gc; gc = &ref->s->gc;
@ -6374,7 +6410,7 @@ static void _gc_add(_ref_t* ref, void* data, _gc_t* gc) {
} }
/* Remove a referenced object from GC */ /* Remove a referenced object from GC */
static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc) { static unsigned _gc_remove(_ref_t* ref, void* data, _gc_t* gc) {
_ht_node_t* table = 0; _ht_node_t* table = 0;
mb_assert(ref && data && gc); mb_assert(ref && data && gc);
@ -6385,7 +6421,9 @@ static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc) {
table = gc->table; table = gc->table;
if(table) if(table)
_ht_remove(table, ref, 0); return _ht_remove(table, ref, 0);
return 0;
} }
/* Get reachable objects */ /* Get reachable objects */
@ -11196,6 +11234,7 @@ static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_t*
_running_context_t* running = 0; _running_context_t* running = 0;
_var_t* pathed_var = 0; _var_t* pathed_var = 0;
_object_t* old_val = 0; _object_t* old_val = 0;
_ref_t* old_val_gc = 0;
_ls_node_t* to_node = 0; _ls_node_t* to_node = 0;
_object_t range; _object_t range;
_object_t* range_ptr = 0; _object_t* range_ptr = 0;
@ -11223,6 +11262,11 @@ static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_t*
if(!pathed_var) if(!pathed_var)
pathed_var = var_loop; pathed_var = var_loop;
old_val = pathed_var->data; old_val = pathed_var->data;
if(_is_ref(old_val)) {
old_val_gc = (_ref_t*)old_val->data.pointer;
if(!_gc_remove(old_val_gc, (void*)old_val_gc, &old_val_gc->s->gc))
old_val_gc = 0;
}
range_ptr = ⦥ range_ptr = ⦥
_MAKE_NIL(range_ptr); _MAKE_NIL(range_ptr);
mb_make_nil(ref_val); mb_make_nil(ref_val);
@ -11375,6 +11419,8 @@ _exit:
*l = ast; *l = ast;
pathed_var->data = old_val; pathed_var->data = old_val;
if(old_val_gc)
_gc_add(old_val_gc, (void*)old_val_gc, &old_val_gc->s->gc);
return result; return result;
} }
@ -13731,14 +13777,14 @@ int mb_ref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) {
#ifdef MB_ENABLE_USERTYPE_REF #ifdef MB_ENABLE_USERTYPE_REF
obj.type != _DT_USERTYPE_REF && obj.type != _DT_USERTYPE_REF &&
#endif /* MB_ENABLE_USERTYPE_REF */ #endif /* MB_ENABLE_USERTYPE_REF */
obj.type != _DT_ARRAY &&
#ifdef MB_ENABLE_COLLECTION_LIB #ifdef MB_ENABLE_COLLECTION_LIB
obj.type != _DT_LIST && obj.type != _DT_DICT && obj.type != _DT_LIST && obj.type != _DT_DICT &&
#endif /* MB_ENABLE_COLLECTION_LIB */ #endif /* MB_ENABLE_COLLECTION_LIB */
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
obj.type != _DT_CLASS && obj.type != _DT_CLASS &&
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
obj.type != _DT_ROUTINE && obj.type != _DT_ROUTINE
obj.type != _DT_ARRAY
) { ) {
_handle_error_on_obj(s, SE_RN_REFERENCED_TYPE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_REFERENCED_TYPE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
} }
@ -13770,14 +13816,14 @@ int mb_unref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) {
#ifdef MB_ENABLE_USERTYPE_REF #ifdef MB_ENABLE_USERTYPE_REF
obj.type != _DT_USERTYPE_REF && obj.type != _DT_USERTYPE_REF &&
#endif /* MB_ENABLE_USERTYPE_REF */ #endif /* MB_ENABLE_USERTYPE_REF */
obj.type != _DT_ARRAY &&
#ifdef MB_ENABLE_COLLECTION_LIB #ifdef MB_ENABLE_COLLECTION_LIB
obj.type != _DT_LIST && obj.type != _DT_DICT && obj.type != _DT_LIST && obj.type != _DT_DICT &&
#endif /* MB_ENABLE_COLLECTION_LIB */ #endif /* MB_ENABLE_COLLECTION_LIB */
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
obj.type != _DT_CLASS && obj.type != _DT_CLASS &&
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
obj.type != _DT_ROUTINE && obj.type != _DT_ROUTINE
obj.type != _DT_ARRAY
) { ) {
_handle_error_on_obj(s, SE_RN_REFERENCED_TYPE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_REFERENCED_TYPE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
} }