1515
1616#if defined(FEAT_EVAL ) || defined(PROTO )
1717/* function flags */
18- #define FC_ABORT 1 /* abort function on error */
19- #define FC_RANGE 2 /* function accepts range */
20- #define FC_DICT 4 /* Dict function, uses "self" */
21- #define FC_CLOSURE 8 /* closure, uses outer scope variables */
22- #define FC_DELETED 16 /* :delfunction used while uf_refcount > 0 */
18+ #define FC_ABORT 0x01 /* abort function on error */
19+ #define FC_RANGE 0x02 /* function accepts range */
20+ #define FC_DICT 0x04 /* Dict function, uses "self" */
21+ #define FC_CLOSURE 0x08 /* closure, uses outer scope variables */
22+ #define FC_DELETED 0x10 /* :delfunction used while uf_refcount > 0 */
23+ #define FC_REMOVED 0x20 /* function redefined while uf_refcount > 0 */
2324
2425/* From user function to hashitem and back. */
2526#define UF2HIKEY (fp ) ((fp)->uf_name)
@@ -178,14 +179,18 @@ get_function_args(
178179 static int
179180register_closure (ufunc_T * fp )
180181{
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 );
182186 fp -> uf_scoped = current_funccal ;
183187 current_funccal -> fc_refcount ++ ;
188+ func_ptr_ref (current_funccal -> func );
189+
184190 if (ga_grow (& current_funccal -> fc_funcs , 1 ) == FAIL )
185191 return FAIL ;
186192 ((ufunc_T * * )current_funccal -> fc_funcs .ga_data )
187193 [current_funccal -> fc_funcs .ga_len ++ ] = fp ;
188- func_ptr_ref (current_funccal -> func );
189194 return OK ;
190195}
191196
@@ -1024,60 +1029,56 @@ call_user_func(
10241029
10251030/*
10261031 * 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".
10281033 */
10291034 static void
10301035funccal_unref (funccall_T * fc , ufunc_T * fp )
10311036{
10321037 funccall_T * * pfc ;
10331038 int i ;
1034- int freed = FALSE;
10351039
10361040 if (fc == NULL )
10371041 return ;
10381042
1039- if (-- fc -> fc_refcount <= 0 )
1040- {
1043+ if (-- fc -> fc_refcount <= 0
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 )
10411047 for (pfc = & previous_funccal ; * pfc != NULL ; pfc = & (* pfc )-> caller )
10421048 {
10431049 if (fc == * pfc )
10441050 {
1045- if (fc -> l_varlist .lv_refcount == DO_NOT_FREE_CNT
1046- && fc -> l_vars .dv_refcount == DO_NOT_FREE_CNT
1047- && fc -> l_avars .dv_refcount == DO_NOT_FREE_CNT )
1048- {
1049- * pfc = fc -> caller ;
1050- free_funccal (fc , TRUE);
1051- freed = TRUE;
1052- }
1053- break ;
1051+ * pfc = fc -> caller ;
1052+ free_funccal (fc , TRUE);
1053+ return ;
10541054 }
10551055 }
1056- }
1057- if (!freed )
1056+ for (i = 0 ; i < fc -> fc_funcs .ga_len ; ++ i )
10581057 {
1059- func_ptr_unref (fc -> func );
1060-
1061- if (fp != NULL )
1062- for (i = 0 ; i < fc -> fc_funcs .ga_len ; ++ i )
1063- {
1064- if (((ufunc_T * * )(fc -> fc_funcs .ga_data ))[i ] == fp )
1065- ((ufunc_T * * )(fc -> fc_funcs .ga_data ))[i ] = NULL ;
1066- }
1058+ if (((ufunc_T * * )(fc -> fc_funcs .ga_data ))[i ] == fp )
1059+ {
1060+ func_ptr_unref (fc -> func );
1061+ ((ufunc_T * * )(fc -> fc_funcs .ga_data ))[i ] = NULL ;
1062+ }
10671063 }
10681064}
10691065
10701066/*
10711067 * Remove the function from the function hashtable. If the function was
10721068 * deleted while it still has references this was already done.
1069+ * Return TRUE if the entry was deleted, FALSE if it wasn't found.
10731070 */
1074- static void
1071+ static int
10751072func_remove (ufunc_T * fp )
10761073{
10771074 hashitem_T * hi = hash_find (& func_hashtab , UF2HIKEY (fp ));
10781075
10791076 if (!HASHITEM_EMPTY (hi ))
1077+ {
10801078 hash_remove (& func_hashtab , hi );
1079+ return TRUE;
1080+ }
1081+ return FALSE;
10811082}
10821083
10831084/*
@@ -1094,7 +1095,10 @@ func_free(ufunc_T *fp)
10941095 vim_free (fp -> uf_tml_total );
10951096 vim_free (fp -> uf_tml_self );
10961097#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 );
10981102
10991103 funccal_unref (fp -> uf_scoped , fp );
11001104
@@ -2158,6 +2162,7 @@ ex_function(exarg_T *eap)
21582162 /* This function is referenced somewhere, don't redefine it but
21592163 * create a new one. */
21602164 -- fp -> uf_refcount ;
2165+ fp -> uf_flags |= FC_REMOVED ;
21612166 fp = NULL ;
21622167 overwrite = TRUE;
21632168 }
@@ -2650,6 +2655,20 @@ get_user_func_name(expand_T *xp, int idx)
26502655
26512656#endif /* FEAT_CMDL_COMPL */
26522657
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+
26532672/*
26542673 * ":delfunction {name}"
26552674 */
@@ -2705,19 +2724,18 @@ ex_delfunction(exarg_T *eap)
27052724 }
27062725 else
27072726 {
2708- /* Normal functions (not numbered functions and lambdas) have a
2727+ /* A normal function (not a numbered function or lambda) has a
27092728 * refcount of 1 for the entry in the hashtable. When deleting
2710- * them and the refcount is more than one, it should be kept.
2711- * Numbered functions and lambdas snould be kept if the refcount is
2729+ * it and the refcount is more than one, it should be kept.
2730+ * A numbered function and lambda snould be kept if the refcount is
27122731 * one or more. */
2713- if (fp -> uf_refcount > (isdigit (fp -> uf_name [0 ])
2714- || fp -> uf_name [0 ] == '<' ? 0 : 1 ))
2732+ if (fp -> uf_refcount > (func_name_refcount (fp -> uf_name ) ? 0 : 1 ))
27152733 {
27162734 /* Function is still referenced somewhere. Don't free it but
27172735 * do remove it from the hashtable. */
2718- func_remove (fp );
2736+ if (func_remove (fp ))
2737+ fp -> uf_refcount -- ;
27192738 fp -> uf_flags |= FC_DELETED ;
2720- fp -> uf_refcount -- ;
27212739 }
27222740 else
27232741 func_free (fp );
@@ -2734,7 +2752,7 @@ func_unref(char_u *name)
27342752{
27352753 ufunc_T * fp = NULL ;
27362754
2737- if (name == NULL )
2755+ if (name == NULL || ! func_name_refcount ( name ) )
27382756 return ;
27392757 fp = find_func (name );
27402758 if (fp == NULL && isdigit (* name ))
@@ -2777,7 +2795,7 @@ func_ref(char_u *name)
27772795{
27782796 ufunc_T * fp ;
27792797
2780- if (name == NULL )
2798+ if (name == NULL || ! func_name_refcount ( name ) )
27812799 return ;
27822800 fp = find_func (name );
27832801 if (fp != NULL )
0 commit comments