comparison src/userfunc.c @ 9733:59565cdd7261 v7.4.2142

commit https://github.com/vim/vim/commit/8dd3a43d75550e9b5736066124c97697564f769e Author: Bram Moolenaar <Bram@vim.org> Date: Mon Aug 1 20:46:25 2016 +0200 patch 7.4.2142 Problem: Leaking memory when redefining a function. Solution: Don't increment the function reference count when it's found by name. Don't remove the wrong function from the hashtab. More reference counting fixes.
author Christian Brabandt <cb@256bit.org>
date Mon, 01 Aug 2016 21:00:06 +0200
parents f85d94eee05b
children 8037eb704e93
comparison
equal deleted inserted replaced
9732:fe4bdbd102ea 9733:59565cdd7261
13 13
14 #include "vim.h" 14 #include "vim.h"
15 15
16 #if defined(FEAT_EVAL) || defined(PROTO) 16 #if defined(FEAT_EVAL) || defined(PROTO)
17 /* function flags */ 17 /* function flags */
18 #define FC_ABORT 1 /* abort function on error */ 18 #define FC_ABORT 0x01 /* abort function on error */
19 #define FC_RANGE 2 /* function accepts range */ 19 #define FC_RANGE 0x02 /* function accepts range */
20 #define FC_DICT 4 /* Dict function, uses "self" */ 20 #define FC_DICT 0x04 /* Dict function, uses "self" */
21 #define FC_CLOSURE 8 /* closure, uses outer scope variables */ 21 #define FC_CLOSURE 0x08 /* closure, uses outer scope variables */
22 #define FC_DELETED 16 /* :delfunction used while uf_refcount > 0 */ 22 #define FC_DELETED 0x10 /* :delfunction used while uf_refcount > 0 */
23 #define FC_REMOVED 0x20 /* function redefined while uf_refcount > 0 */
23 24
24 /* From user function to hashitem and back. */ 25 /* From user function to hashitem and back. */
25 #define UF2HIKEY(fp) ((fp)->uf_name) 26 #define UF2HIKEY(fp) ((fp)->uf_name)
26 #define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name))) 27 #define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
27 #define HI2UF(hi) HIKEY2UF((hi)->hi_key) 28 #define HI2UF(hi) HIKEY2UF((hi)->hi_key)
176 * Register function "fp" as using "current_funccal" as its scope. 177 * Register function "fp" as using "current_funccal" as its scope.
177 */ 178 */
178 static int 179 static int
179 register_closure(ufunc_T *fp) 180 register_closure(ufunc_T *fp)
180 { 181 {
181 funccal_unref(fp->uf_scoped, NULL); 182 if (fp->uf_scoped == current_funccal)
183 /* no change */
184 return OK;
185 funccal_unref(fp->uf_scoped, fp);
182 fp->uf_scoped = current_funccal; 186 fp->uf_scoped = current_funccal;
183 current_funccal->fc_refcount++; 187 current_funccal->fc_refcount++;
188 func_ptr_ref(current_funccal->func);
189
184 if (ga_grow(&current_funccal->fc_funcs, 1) == FAIL) 190 if (ga_grow(&current_funccal->fc_funcs, 1) == FAIL)
185 return FAIL; 191 return FAIL;
186 ((ufunc_T **)current_funccal->fc_funcs.ga_data) 192 ((ufunc_T **)current_funccal->fc_funcs.ga_data)
187 [current_funccal->fc_funcs.ga_len++] = fp; 193 [current_funccal->fc_funcs.ga_len++] = fp;
188 func_ptr_ref(current_funccal->func);
189 return OK; 194 return OK;
190 } 195 }
191 196
192 /* 197 /*
193 * Parse a lambda expression and get a Funcref from "*arg". 198 * Parse a lambda expression and get a Funcref from "*arg".
1022 } 1027 }
1023 } 1028 }
1024 1029
1025 /* 1030 /*
1026 * Unreference "fc": decrement the reference count and free it when it 1031 * Unreference "fc": decrement the reference count and free it when it
1027 * becomes zero. If "fp" is not NULL, "fp" is detached from "fc". 1032 * becomes zero. "fp" is detached from "fc".
1028 */ 1033 */
1029 static void 1034 static void
1030 funccal_unref(funccall_T *fc, ufunc_T *fp) 1035 funccal_unref(funccall_T *fc, ufunc_T *fp)
1031 { 1036 {
1032 funccall_T **pfc; 1037 funccall_T **pfc;
1033 int i; 1038 int i;
1034 int freed = FALSE;
1035 1039
1036 if (fc == NULL) 1040 if (fc == NULL)
1037 return; 1041 return;
1038 1042
1039 if (--fc->fc_refcount <= 0) 1043 if (--fc->fc_refcount <= 0
1040 { 1044 && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
1045 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
1046 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
1041 for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) 1047 for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller)
1042 { 1048 {
1043 if (fc == *pfc) 1049 if (fc == *pfc)
1044 { 1050 {
1045 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT 1051 *pfc = fc->caller;
1046 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT 1052 free_funccal(fc, TRUE);
1047 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) 1053 return;
1048 {
1049 *pfc = fc->caller;
1050 free_funccal(fc, TRUE);
1051 freed = TRUE;
1052 }
1053 break;
1054 } 1054 }
1055 } 1055 }
1056 } 1056 for (i = 0; i < fc->fc_funcs.ga_len; ++i)
1057 if (!freed) 1057 {
1058 { 1058 if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp)
1059 func_ptr_unref(fc->func); 1059 {
1060 1060 func_ptr_unref(fc->func);
1061 if (fp != NULL) 1061 ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL;
1062 for (i = 0; i < fc->fc_funcs.ga_len; ++i) 1062 }
1063 {
1064 if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp)
1065 ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL;
1066 }
1067 } 1063 }
1068 } 1064 }
1069 1065
1070 /* 1066 /*
1071 * Remove the function from the function hashtable. If the function was 1067 * Remove the function from the function hashtable. If the function was
1072 * deleted while it still has references this was already done. 1068 * deleted while it still has references this was already done.
1073 */ 1069 * Return TRUE if the entry was deleted, FALSE if it wasn't found.
1074 static void 1070 */
1071 static int
1075 func_remove(ufunc_T *fp) 1072 func_remove(ufunc_T *fp)
1076 { 1073 {
1077 hashitem_T *hi = hash_find(&func_hashtab, UF2HIKEY(fp)); 1074 hashitem_T *hi = hash_find(&func_hashtab, UF2HIKEY(fp));
1078 1075
1079 if (!HASHITEM_EMPTY(hi)) 1076 if (!HASHITEM_EMPTY(hi))
1077 {
1080 hash_remove(&func_hashtab, hi); 1078 hash_remove(&func_hashtab, hi);
1079 return TRUE;
1080 }
1081 return FALSE;
1081 } 1082 }
1082 1083
1083 /* 1084 /*
1084 * Free a function and remove it from the list of functions. 1085 * Free a function and remove it from the list of functions.
1085 */ 1086 */
1092 #ifdef FEAT_PROFILE 1093 #ifdef FEAT_PROFILE
1093 vim_free(fp->uf_tml_count); 1094 vim_free(fp->uf_tml_count);
1094 vim_free(fp->uf_tml_total); 1095 vim_free(fp->uf_tml_total);
1095 vim_free(fp->uf_tml_self); 1096 vim_free(fp->uf_tml_self);
1096 #endif 1097 #endif
1097 func_remove(fp); 1098 /* only remove it when not done already, otherwise we would remove a newer
1099 * version of the function */
1100 if ((fp->uf_flags & (FC_DELETED | FC_REMOVED)) == 0)
1101 func_remove(fp);
1098 1102
1099 funccal_unref(fp->uf_scoped, fp); 1103 funccal_unref(fp->uf_scoped, fp);
1100 1104
1101 vim_free(fp); 1105 vim_free(fp);
1102 } 1106 }
2156 if (fp->uf_refcount > 1) 2160 if (fp->uf_refcount > 1)
2157 { 2161 {
2158 /* This function is referenced somewhere, don't redefine it but 2162 /* This function is referenced somewhere, don't redefine it but
2159 * create a new one. */ 2163 * create a new one. */
2160 --fp->uf_refcount; 2164 --fp->uf_refcount;
2165 fp->uf_flags |= FC_REMOVED;
2161 fp = NULL; 2166 fp = NULL;
2162 overwrite = TRUE; 2167 overwrite = TRUE;
2163 } 2168 }
2164 else 2169 else
2165 { 2170 {
2649 } 2654 }
2650 2655
2651 #endif /* FEAT_CMDL_COMPL */ 2656 #endif /* FEAT_CMDL_COMPL */
2652 2657
2653 /* 2658 /*
2659 * There are two kinds of function names:
2660 * 1. ordinary names, function defined with :function
2661 * 2. numbered functions and lambdas
2662 * For the first we only count the name stored in func_hashtab as a reference,
2663 * using function() does not count as a reference, because the function is
2664 * looked up by name.
2665 */
2666 static int
2667 func_name_refcount(char_u *name)
2668 {
2669 return isdigit(*name) || *name == '<';
2670 }
2671
2672 /*
2654 * ":delfunction {name}" 2673 * ":delfunction {name}"
2655 */ 2674 */
2656 void 2675 void
2657 ex_delfunction(exarg_T *eap) 2676 ex_delfunction(exarg_T *eap)
2658 { 2677 {
2703 * invoke func_unref() and possibly delete the function. */ 2722 * invoke func_unref() and possibly delete the function. */
2704 dictitem_remove(fudi.fd_dict, fudi.fd_di); 2723 dictitem_remove(fudi.fd_dict, fudi.fd_di);
2705 } 2724 }
2706 else 2725 else
2707 { 2726 {
2708 /* Normal functions (not numbered functions and lambdas) have a 2727 /* A normal function (not a numbered function or lambda) has a
2709 * refcount of 1 for the entry in the hashtable. When deleting 2728 * refcount of 1 for the entry in the hashtable. When deleting
2710 * them and the refcount is more than one, it should be kept. 2729 * it and the refcount is more than one, it should be kept.
2711 * Numbered functions and lambdas snould be kept if the refcount is 2730 * A numbered function and lambda snould be kept if the refcount is
2712 * one or more. */ 2731 * one or more. */
2713 if (fp->uf_refcount > (isdigit(fp->uf_name[0]) 2732 if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1))
2714 || fp->uf_name[0] == '<' ? 0 : 1))
2715 { 2733 {
2716 /* Function is still referenced somewhere. Don't free it but 2734 /* Function is still referenced somewhere. Don't free it but
2717 * do remove it from the hashtable. */ 2735 * do remove it from the hashtable. */
2718 func_remove(fp); 2736 if (func_remove(fp))
2737 fp->uf_refcount--;
2719 fp->uf_flags |= FC_DELETED; 2738 fp->uf_flags |= FC_DELETED;
2720 fp->uf_refcount--;
2721 } 2739 }
2722 else 2740 else
2723 func_free(fp); 2741 func_free(fp);
2724 } 2742 }
2725 } 2743 }
2732 void 2750 void
2733 func_unref(char_u *name) 2751 func_unref(char_u *name)
2734 { 2752 {
2735 ufunc_T *fp = NULL; 2753 ufunc_T *fp = NULL;
2736 2754
2737 if (name == NULL) 2755 if (name == NULL || !func_name_refcount(name))
2738 return; 2756 return;
2739 fp = find_func(name); 2757 fp = find_func(name);
2740 if (fp == NULL && isdigit(*name)) 2758 if (fp == NULL && isdigit(*name))
2741 { 2759 {
2742 #ifdef EXITFREE 2760 #ifdef EXITFREE
2775 void 2793 void
2776 func_ref(char_u *name) 2794 func_ref(char_u *name)
2777 { 2795 {
2778 ufunc_T *fp; 2796 ufunc_T *fp;
2779 2797
2780 if (name == NULL) 2798 if (name == NULL || !func_name_refcount(name))
2781 return; 2799 return;
2782 fp = find_func(name); 2800 fp = find_func(name);
2783 if (fp != NULL) 2801 if (fp != NULL)
2784 ++fp->uf_refcount; 2802 ++fp->uf_refcount;
2785 else if (isdigit(*name)) 2803 else if (isdigit(*name))