Mercurial > vim
comparison src/eval.c @ 8881:ed0b39dd7fd6 v7.4.1727
commit https://github.com/vim/vim/commit/ebf7dfa6f121c82f97d2adca3d45fbaba9ad8f7e
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Apr 14 12:46:51 2016 +0200
patch 7.4.1727
Problem: Cannot detect a crash in tests when caused by garbagecollect().
Solution: Add garbagecollect_for_testing(). Do not free a job if is still
useful.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 14 Apr 2016 13:00:06 +0200 |
parents | 50e40f322e78 |
children | 8bf855dea79e |
comparison
equal
deleted
inserted
replaced
8880:9f57791bc922 | 8881:ed0b39dd7fd6 |
---|---|
371 {VV_NAME("false", VAR_SPECIAL), VV_RO}, | 371 {VV_NAME("false", VAR_SPECIAL), VV_RO}, |
372 {VV_NAME("true", VAR_SPECIAL), VV_RO}, | 372 {VV_NAME("true", VAR_SPECIAL), VV_RO}, |
373 {VV_NAME("null", VAR_SPECIAL), VV_RO}, | 373 {VV_NAME("null", VAR_SPECIAL), VV_RO}, |
374 {VV_NAME("none", VAR_SPECIAL), VV_RO}, | 374 {VV_NAME("none", VAR_SPECIAL), VV_RO}, |
375 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, | 375 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, |
376 {VV_NAME("testing", VAR_NUMBER), 0}, | |
376 }; | 377 }; |
377 | 378 |
378 /* shorthand */ | 379 /* shorthand */ |
379 #define vv_type vv_di.di_tv.v_type | 380 #define vv_type vv_di.di_tv.v_type |
380 #define vv_nr vv_di.di_tv.vval.v_number | 381 #define vv_nr vv_di.di_tv.vval.v_number |
578 static void f_foldtext(typval_T *argvars, typval_T *rettv); | 579 static void f_foldtext(typval_T *argvars, typval_T *rettv); |
579 static void f_foldtextresult(typval_T *argvars, typval_T *rettv); | 580 static void f_foldtextresult(typval_T *argvars, typval_T *rettv); |
580 static void f_foreground(typval_T *argvars, typval_T *rettv); | 581 static void f_foreground(typval_T *argvars, typval_T *rettv); |
581 static void f_function(typval_T *argvars, typval_T *rettv); | 582 static void f_function(typval_T *argvars, typval_T *rettv); |
582 static void f_garbagecollect(typval_T *argvars, typval_T *rettv); | 583 static void f_garbagecollect(typval_T *argvars, typval_T *rettv); |
584 static void f_garbagecollect_for_testing(typval_T *argvars, typval_T *rettv); | |
583 static void f_get(typval_T *argvars, typval_T *rettv); | 585 static void f_get(typval_T *argvars, typval_T *rettv); |
584 static void f_getbufline(typval_T *argvars, typval_T *rettv); | 586 static void f_getbufline(typval_T *argvars, typval_T *rettv); |
585 static void f_getbufvar(typval_T *argvars, typval_T *rettv); | 587 static void f_getbufvar(typval_T *argvars, typval_T *rettv); |
586 static void f_getchar(typval_T *argvars, typval_T *rettv); | 588 static void f_getchar(typval_T *argvars, typval_T *rettv); |
587 static void f_getcharmod(typval_T *argvars, typval_T *rettv); | 589 static void f_getcharmod(typval_T *argvars, typval_T *rettv); |
1027 for (i = 1; i <= ga_scripts.ga_len; ++i) | 1029 for (i = 1; i <= ga_scripts.ga_len; ++i) |
1028 vim_free(SCRIPT_SV(i)); | 1030 vim_free(SCRIPT_SV(i)); |
1029 ga_clear(&ga_scripts); | 1031 ga_clear(&ga_scripts); |
1030 | 1032 |
1031 /* unreferenced lists and dicts */ | 1033 /* unreferenced lists and dicts */ |
1032 (void)garbage_collect(); | 1034 (void)garbage_collect(FALSE); |
1033 | 1035 |
1034 /* functions */ | 1036 /* functions */ |
1035 free_all_functions(); | 1037 free_all_functions(); |
1036 hash_clear(&func_hashtab); | 1038 hash_clear(&func_hashtab); |
1037 } | 1039 } |
6887 { | 6889 { |
6888 current_copyID += COPYID_INC; | 6890 current_copyID += COPYID_INC; |
6889 return current_copyID; | 6891 return current_copyID; |
6890 } | 6892 } |
6891 | 6893 |
6894 /* Used by get_func_tv() */ | |
6895 static garray_T funcargs = GA_EMPTY; | |
6896 | |
6892 /* | 6897 /* |
6893 * Garbage collection for lists and dictionaries. | 6898 * Garbage collection for lists and dictionaries. |
6894 * | 6899 * |
6895 * We use reference counts to be able to free most items right away when they | 6900 * We use reference counts to be able to free most items right away when they |
6896 * are no longer used. But for composite items it's possible that it becomes | 6901 * are no longer used. But for composite items it's possible that it becomes |
6909 * http://python.ca/nas/python/gc/ | 6914 * http://python.ca/nas/python/gc/ |
6910 */ | 6915 */ |
6911 | 6916 |
6912 /* | 6917 /* |
6913 * Do garbage collection for lists and dicts. | 6918 * Do garbage collection for lists and dicts. |
6919 * When "testing" is TRUE this is called from garbagecollect_for_testing(). | |
6914 * Return TRUE if some memory was freed. | 6920 * Return TRUE if some memory was freed. |
6915 */ | 6921 */ |
6916 int | 6922 int |
6917 garbage_collect(void) | 6923 garbage_collect(int testing) |
6918 { | 6924 { |
6919 int copyID; | 6925 int copyID; |
6920 int abort = FALSE; | 6926 int abort = FALSE; |
6921 buf_T *buf; | 6927 buf_T *buf; |
6922 win_T *wp; | 6928 win_T *wp; |
6926 int did_free_funccal = FALSE; | 6932 int did_free_funccal = FALSE; |
6927 #ifdef FEAT_WINDOWS | 6933 #ifdef FEAT_WINDOWS |
6928 tabpage_T *tp; | 6934 tabpage_T *tp; |
6929 #endif | 6935 #endif |
6930 | 6936 |
6931 /* Only do this once. */ | 6937 if (!testing) |
6932 want_garbage_collect = FALSE; | 6938 { |
6933 may_garbage_collect = FALSE; | 6939 /* Only do this once. */ |
6934 garbage_collect_at_exit = FALSE; | 6940 want_garbage_collect = FALSE; |
6941 may_garbage_collect = FALSE; | |
6942 garbage_collect_at_exit = FALSE; | |
6943 } | |
6935 | 6944 |
6936 /* We advance by two because we add one for items referenced through | 6945 /* We advance by two because we add one for items referenced through |
6937 * previous_funccal. */ | 6946 * previous_funccal. */ |
6938 copyID = get_copyID(); | 6947 copyID = get_copyID(); |
6939 | 6948 |
6986 for (fc = current_funccal; fc != NULL; fc = fc->caller) | 6995 for (fc = current_funccal; fc != NULL; fc = fc->caller) |
6987 { | 6996 { |
6988 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); | 6997 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); |
6989 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); | 6998 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); |
6990 } | 6999 } |
7000 | |
7001 /* function call arguments, if v:testing is set. */ | |
7002 for (i = 0; i < funcargs.ga_len; ++i) | |
7003 abort = abort || set_ref_in_item(((typval_T **)funcargs.ga_data)[i], | |
7004 copyID, NULL, NULL); | |
6991 | 7005 |
6992 /* v: vars */ | 7006 /* v: vars */ |
6993 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL); | 7007 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL); |
6994 | 7008 |
6995 #ifdef FEAT_LUA | 7009 #ifdef FEAT_LUA |
7032 pfc = &(*pfc)->caller; | 7046 pfc = &(*pfc)->caller; |
7033 } | 7047 } |
7034 if (did_free_funccal) | 7048 if (did_free_funccal) |
7035 /* When a funccal was freed some more items might be garbage | 7049 /* When a funccal was freed some more items might be garbage |
7036 * collected, so run again. */ | 7050 * collected, so run again. */ |
7037 (void)garbage_collect(); | 7051 (void)garbage_collect(testing); |
7038 } | 7052 } |
7039 else if (p_verbose > 0) | 7053 else if (p_verbose > 0) |
7040 { | 7054 { |
7041 verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!")); | 7055 verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!")); |
7042 } | 7056 } |
8422 {"foldtext", 0, 0, f_foldtext}, | 8436 {"foldtext", 0, 0, f_foldtext}, |
8423 {"foldtextresult", 1, 1, f_foldtextresult}, | 8437 {"foldtextresult", 1, 1, f_foldtextresult}, |
8424 {"foreground", 0, 0, f_foreground}, | 8438 {"foreground", 0, 0, f_foreground}, |
8425 {"function", 1, 3, f_function}, | 8439 {"function", 1, 3, f_function}, |
8426 {"garbagecollect", 0, 1, f_garbagecollect}, | 8440 {"garbagecollect", 0, 1, f_garbagecollect}, |
8441 {"garbagecollect_for_testing", 0, 0, f_garbagecollect_for_testing}, | |
8427 {"get", 2, 3, f_get}, | 8442 {"get", 2, 3, f_get}, |
8428 {"getbufline", 2, 3, f_getbufline}, | 8443 {"getbufline", 2, 3, f_getbufline}, |
8429 {"getbufvar", 2, 3, f_getbufvar}, | 8444 {"getbufvar", 2, 3, f_getbufvar}, |
8430 {"getchar", 0, 1, f_getchar}, | 8445 {"getchar", 0, 1, f_getchar}, |
8431 {"getcharmod", 0, 0, f_getcharmod}, | 8446 {"getcharmod", 0, 0, f_getcharmod}, |
8894 ++argp; | 8909 ++argp; |
8895 else | 8910 else |
8896 ret = FAIL; | 8911 ret = FAIL; |
8897 | 8912 |
8898 if (ret == OK) | 8913 if (ret == OK) |
8914 { | |
8915 int i = 0; | |
8916 | |
8917 if (get_vim_var_nr(VV_TESTING)) | |
8918 { | |
8919 /* Prepare for calling garbagecollect_for_testing(), need to know | |
8920 * what variables are used on the call stack. */ | |
8921 if (funcargs.ga_itemsize == 0) | |
8922 ga_init2(&funcargs, (int)sizeof(typval_T *), 50); | |
8923 for (i = 0; i < argcount; ++i) | |
8924 if (ga_grow(&funcargs, 1) == OK) | |
8925 ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = | |
8926 &argvars[i]; | |
8927 } | |
8928 | |
8899 ret = call_func(name, len, rettv, argcount, argvars, | 8929 ret = call_func(name, len, rettv, argcount, argvars, |
8900 firstline, lastline, doesrange, evaluate, partial, selfdict); | 8930 firstline, lastline, doesrange, evaluate, partial, selfdict); |
8931 | |
8932 funcargs.ga_len -= i; | |
8933 } | |
8901 else if (!aborting()) | 8934 else if (!aborting()) |
8902 { | 8935 { |
8903 if (argcount == MAX_FUNC_ARGS) | 8936 if (argcount == MAX_FUNC_ARGS) |
8904 emsg_funcname(N_("E740: Too many arguments for function %s"), name); | 8937 emsg_funcname(N_("E740: Too many arguments for function %s"), name); |
8905 else | 8938 else |
12313 * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ | 12346 * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ |
12314 want_garbage_collect = TRUE; | 12347 want_garbage_collect = TRUE; |
12315 | 12348 |
12316 if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) | 12349 if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) |
12317 garbage_collect_at_exit = TRUE; | 12350 garbage_collect_at_exit = TRUE; |
12351 } | |
12352 | |
12353 /* | |
12354 * "garbagecollect_for_testing()" function | |
12355 */ | |
12356 static void | |
12357 f_garbagecollect_for_testing(typval_T *argvars UNUSED, typval_T *rettv UNUSED) | |
12358 { | |
12359 /* This is dangerous, any Lists and Dicts used internally may be freed | |
12360 * while still in use. */ | |
12361 garbage_collect(TRUE); | |
12318 } | 12362 } |
12319 | 12363 |
12320 /* | 12364 /* |
12321 * "get()" function | 12365 * "get()" function |
12322 */ | 12366 */ |