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 */