*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
Fixed a crash bug with invalid collection index
Fixed a memory leak with invalid invoking
@ -14,7 +17,7 @@ Fixed a lookup issue with the mb_get_var function
Nov. 17 2017
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
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);
#endif /* _HAS_REF_OBJ_LOCK */
static bool_t _is_ref(_object_t* obj);
static _ref_count_t _ref(_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);
@ -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 _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_both(void* data, void* extra, void* h);
#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 */
/* 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 */
static _ref_count_t _ref(_ref_t* ref, void* data) {
_ref_count_t before = *ref->count;
mb_unrefvar(data);
mb_assert((intptr_t)ref == (intptr_t)data);
++(*ref->count);
if(before > *ref->count) {
@ -6258,6 +6292,8 @@ static bool_t _unref(_ref_t* ref, void* data) {
_gc_t* gc = 0;
bool_t cld = false;
mb_assert((intptr_t)ref == (intptr_t)data);
cld = *ref->count == _NONE_REF + 1;
do {
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 */
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;
mb_assert(ref && data && gc);
@ -6385,7 +6421,9 @@ static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc) {
table = gc->table;
if(table)
_ht_remove(table, ref, 0);
return _ht_remove(table, ref, 0);
return 0;
}
/* 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;
_var_t* pathed_var = 0;
_object_t* old_val = 0;
_ref_t* old_val_gc = 0;
_ls_node_t* to_node = 0;
_object_t range;
_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)
pathed_var = var_loop;
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 = ⦥
_MAKE_NIL(range_ptr);
mb_make_nil(ref_val);
@ -11375,6 +11419,8 @@ _exit:
*l = ast;
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;
}
@ -13731,14 +13777,14 @@ int mb_ref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) {
#ifdef MB_ENABLE_USERTYPE_REF
obj.type != _DT_USERTYPE_REF &&
#endif /* MB_ENABLE_USERTYPE_REF */
obj.type != _DT_ARRAY &&
#ifdef MB_ENABLE_COLLECTION_LIB
obj.type != _DT_LIST && obj.type != _DT_DICT &&
#endif /* MB_ENABLE_COLLECTION_LIB */
#ifdef MB_ENABLE_CLASS
obj.type != _DT_CLASS &&
#endif /* MB_ENABLE_CLASS */
obj.type != _DT_ROUTINE &&
obj.type != _DT_ARRAY
obj.type != _DT_ROUTINE
) {
_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
obj.type != _DT_USERTYPE_REF &&
#endif /* MB_ENABLE_USERTYPE_REF */
obj.type != _DT_ARRAY &&
#ifdef MB_ENABLE_COLLECTION_LIB
obj.type != _DT_LIST && obj.type != _DT_DICT &&
#endif /* MB_ENABLE_COLLECTION_LIB */
#ifdef MB_ENABLE_CLASS
obj.type != _DT_CLASS &&
#endif /* MB_ENABLE_CLASS */
obj.type != _DT_ROUTINE &&
obj.type != _DT_ARRAY
obj.type != _DT_ROUTINE
) {
_handle_error_on_obj(s, SE_RN_REFERENCED_TYPE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
}