diff --git a/HISTORY b/HISTORY index 8323f5e..476b0ef 100755 --- a/HISTORY +++ b/HISTORY @@ -2,6 +2,7 @@ Feb. 26 2016 Added a ME keyword to represent a class instance itself Added shallow cloning support Fixed an overrided function copying issue +Fixed a multiple disposing bug with outer scopes of lambda Feb. 25 2016 Improved importing directory detection diff --git a/core/my_basic.c b/core/my_basic.c index 75fb22a..14d866d 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -1468,6 +1468,9 @@ static int _gc_destroy_garbage_in_lambda(void* data, void* extra, void* 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); +#ifdef MB_ENABLE_CLASS +static int _gc_destroy_garbage_class(void* data, void* extra); +#endif /* MB_ENABLE_CLASS */ static void _gc_swap_tables(mb_interpreter_t* s); static void _gc_try_trigger(mb_interpreter_t* s); static void _gc_collect_garbage(mb_interpreter_t* s, int depth); @@ -4527,6 +4530,7 @@ static int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object (*obj)->ref = true; *delsym = true; } else { +#ifdef MB_ENABLE_CLASS if(strcmp(sym, _CLASS_ME) == 0) { _handle_error_now(s, SE_RN_CANNOT_CHANGE_ME, s->source_file, MB_FUNC_ERR); (*obj)->ref = true; @@ -4534,6 +4538,7 @@ static int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object goto _exit; } +#endif /* MB_ENABLE_CLASS */ tmp.var = (_var_t*)mb_malloc(sizeof(_var_t)); memset(tmp.var, 0, sizeof(_var_t)); tmp.var->name = sym; @@ -5253,7 +5258,7 @@ static bool_t _unref(_ref_t* ref, void* data) { result = --(*ref->count) == _NONE_REF; mb_assert(*ref->count >= _NONE_REF); - _gc_add(ref, data, 0); + _gc_add(ref, data, &ref->s->gc); if(ref->count && *ref->count == _NONE_REF) _tidy_intermediate_value(ref, data); ref->on_unref(ref, data); @@ -5330,13 +5335,13 @@ static void _gc_add(_ref_t* ref, void* data, _gc_t* gc) { if(gc && _ht_find(gc->collected_table, ref)) return; - if(!ref->s->gc.table) + if(!gc->table) return; - if(ref->s->gc.collecting) - table = ref->s->gc.recursive_table; + if(gc->collecting) + table = gc->recursive_table; else - table = ref->s->gc.table; + table = gc->table; if(gc && gc->valid_table && _ht_find(gc->valid_table, ref)) _ht_remove(table, ref, 0); @@ -5578,9 +5583,6 @@ static int _gc_destroy_garbage(void* data, void* extra) { _list_t* lst = 0; _dict_t* dct = 0; #endif /* MB_ENABLE_COLLECTION_LIB */ -#ifdef MB_ENABLE_CLASS - _class_t* instance = 0; -#endif /* MB_ENABLE_CLASS */ #ifdef MB_ENABLE_LAMBDA _routine_t* routine = 0; #endif /* MB_ENABLE_LAMBDA */ @@ -5605,28 +5607,14 @@ static int _gc_destroy_garbage(void* data, void* extra) { break; #endif /* MB_ENABLE_COLLECTION_LIB */ -#ifdef MB_ENABLE_CLASS - case _DT_CLASS: - instance = (_class_t*)data; - _HT_FOREACH(instance->scope->var_dict, _do_nothing_on_object, _gc_destroy_garbage_in_class, gc); - _ht_clear(instance->scope->var_dict); - _ls_clear(instance->meta_list); -#ifdef MB_ENABLE_LAMBDA - if(instance->scope->refered_lambdas) { - _ls_destroy(instance->scope->refered_lambdas); - instance->scope->refered_lambdas = 0; - } -#endif /* MB_ENABLE_LAMBDA */ - - break; -#endif /* MB_ENABLE_CLASS */ #ifdef MB_ENABLE_LAMBDA case _DT_ROUTINE: routine = (_routine_t*)data; if(routine->type == _IT_LAMBDA) { _HT_FOREACH(routine->func.lambda.scope->var_dict, _do_nothing_on_object, _gc_destroy_garbage_in_lambda, gc); _ht_clear(routine->func.lambda.scope->var_dict); - _gc_destroy_garbage_in_outer_scope(routine->func.lambda.outer_scope, gc); + if(!routine->func.lambda.outer_scope || !_ht_find(gc->collected_table, &routine->func.lambda.outer_scope->ref)) + _gc_destroy_garbage_in_outer_scope(routine->func.lambda.outer_scope, gc); } break; @@ -5646,6 +5634,49 @@ static int _gc_destroy_garbage(void* data, void* extra) { return result; } +#ifdef MB_ENABLE_CLASS +static int _gc_destroy_garbage_class(void* data, void* extra) { + /* Destroy a class instance garbage */ + int result = _OP_RESULT_NORMAL; + _gc_t* gc = 0; + _ref_t* ref = 0; + bool_t cld = false; + _class_t* instance = 0; + + mb_assert(data && extra); + + ref = (_ref_t*)extra; + gc = &ref->s->gc; + switch(ref->type) { + case _DT_CLASS: + instance = (_class_t*)data; + _HT_FOREACH(instance->scope->var_dict, _do_nothing_on_object, _gc_destroy_garbage_in_class, gc); + _ht_clear(instance->scope->var_dict); + _ls_clear(instance->meta_list); +#ifdef MB_ENABLE_LAMBDA + if(instance->scope->refered_lambdas) { + _ls_destroy(instance->scope->refered_lambdas); + instance->scope->refered_lambdas = 0; + } +#endif /* MB_ENABLE_LAMBDA */ + + break; + default: /* Do nothing */ + break; + } + if(ref->count) { + cld = *ref->count == _NONE_REF + 1; + _unref(ref, data); + if(cld) + _ht_set_or_insert(gc->collected_table, ref, data); + } + + result = _OP_RESULT_DEL_NODE; + + return result; +} +#endif /* MB_ENABLE_CLASS */ + static void _gc_swap_tables(mb_interpreter_t* s) { /* Swap active garbage table and recursive table */ _ht_node_t* tmp = 0; @@ -5683,6 +5714,9 @@ static void _gc_collect_garbage(mb_interpreter_t* s, int depth) { _HT_FOREACH(valid, _do_nothing_on_object, _ht_remove_exist, s->gc.table); /* Collect garbage */ do { +#ifdef MB_ENABLE_CLASS + _ht_foreach(s->gc.table, _gc_destroy_garbage_class); +#endif /* MB_ENABLE_CLASS */ _ht_foreach(s->gc.table, _gc_destroy_garbage); _ht_clear(s->gc.table); if(s->gc.collecting > 1) @@ -7295,7 +7329,7 @@ static void _destroy_routine(mb_interpreter_t* s, _routine_t* r) { safe_free(r->func.lambda.scope); if(r->func.lambda.parameters) _ls_destroy(r->func.lambda.parameters); - if(r->func.lambda.outer_scope) + if(r->func.lambda.outer_scope && !_ht_find(s->gc.collected_table, &r->func.lambda.outer_scope->ref)) _unref(&r->func.lambda.outer_scope->ref, r->func.lambda.outer_scope); if(r->func.lambda.upvalues) _ht_destroy(r->func.lambda.upvalues);