@@ -1075,12 +1075,17 @@ func_remove(ufunc_T *fp)
10751075}
10761076
10771077/*
1078- * Free a function and remove it from the list of functions.
1078+ * Free all things that a function contains. Does not free the function
1079+ * itself, use func_free() for that.
10791080 * When "force" is TRUE we are exiting.
10801081 */
10811082 static void
1082- func_free (ufunc_T * fp , int force )
1083+ func_clear (ufunc_T * fp , int force )
10831084{
1085+ if (fp -> uf_cleared )
1086+ return ;
1087+ fp -> uf_cleared = TRUE;
1088+
10841089 /* clear this function */
10851090 ga_clear_strings (& (fp -> uf_args ));
10861091 ga_clear_strings (& (fp -> uf_lines ));
@@ -1089,16 +1094,35 @@ func_free(ufunc_T *fp, int force)
10891094 vim_free (fp -> uf_tml_total );
10901095 vim_free (fp -> uf_tml_self );
10911096#endif
1097+ funccal_unref (fp -> uf_scoped , fp , force );
1098+ }
1099+
1100+ /*
1101+ * Free a function and remove it from the list of functions. Does not free
1102+ * what a function contains, call func_clear() first.
1103+ */
1104+ static void
1105+ func_free (ufunc_T * fp )
1106+ {
10921107 /* only remove it when not done already, otherwise we would remove a newer
10931108 * version of the function */
10941109 if ((fp -> uf_flags & (FC_DELETED | FC_REMOVED )) == 0 )
10951110 func_remove (fp );
10961111
1097- funccal_unref (fp -> uf_scoped , fp , force );
1098-
10991112 vim_free (fp );
11001113}
11011114
1115+ /*
1116+ * Free all things that a function contains and free the function itself.
1117+ * When "force" is TRUE we are exiting.
1118+ */
1119+ static void
1120+ func_clear_free (ufunc_T * fp , int force )
1121+ {
1122+ func_clear (fp , force );
1123+ func_free (fp );
1124+ }
1125+
11021126/*
11031127 * There are two kinds of function names:
11041128 * 1. ordinary names, function defined with :function
@@ -1120,10 +1144,40 @@ free_all_functions(void)
11201144 hashitem_T * hi ;
11211145 ufunc_T * fp ;
11221146 long_u skipped = 0 ;
1123- long_u todo ;
1147+ long_u todo = 1 ;
1148+ long_u used ;
1149+
1150+ /* First clear what the functions contain. Since this may lower the
1151+ * reference count of a function, it may also free a function and change
1152+ * the hash table. Restart if that happens. */
1153+ while (todo > 0 )
1154+ {
1155+ todo = func_hashtab .ht_used ;
1156+ for (hi = func_hashtab .ht_array ; todo > 0 ; ++ hi )
1157+ if (!HASHITEM_EMPTY (hi ))
1158+ {
1159+ /* Only free functions that are not refcounted, those are
1160+ * supposed to be freed when no longer referenced. */
1161+ fp = HI2UF (hi );
1162+ if (func_name_refcount (fp -> uf_name ))
1163+ ++ skipped ;
1164+ else
1165+ {
1166+ used = func_hashtab .ht_used ;
1167+ func_clear (fp , TRUE);
1168+ if (used != func_hashtab .ht_used )
1169+ {
1170+ skipped = 0 ;
1171+ break ;
1172+ }
1173+ }
1174+ -- todo ;
1175+ }
1176+ }
11241177
1125- /* Need to start all over every time, because func_free() may change the
1126- * hash table. */
1178+ /* Now actually free the functions. Need to start all over every time,
1179+ * because func_free() may change the hash table. */
1180+ skipped = 0 ;
11271181 while (func_hashtab .ht_used > skipped )
11281182 {
11291183 todo = func_hashtab .ht_used ;
@@ -1138,7 +1192,7 @@ free_all_functions(void)
11381192 ++ skipped ;
11391193 else
11401194 {
1141- func_free (fp , TRUE );
1195+ func_free (fp );
11421196 skipped = 0 ;
11431197 break ;
11441198 }
@@ -1356,7 +1410,7 @@ call_func(
13561410 if (-- fp -> uf_calls <= 0 && fp -> uf_refcount <= 0 )
13571411 /* Function was unreferenced while being used, free it
13581412 * now. */
1359- func_free (fp , FALSE);
1413+ func_clear_free (fp , FALSE);
13601414 if (did_save_redo )
13611415 restoreRedobuff ();
13621416 restore_search_patterns ();
@@ -2756,7 +2810,7 @@ ex_delfunction(exarg_T *eap)
27562810 fp -> uf_flags |= FC_DELETED ;
27572811 }
27582812 else
2759- func_free (fp , FALSE);
2813+ func_clear_free (fp , FALSE);
27602814 }
27612815 }
27622816}
@@ -2785,7 +2839,7 @@ func_unref(char_u *name)
27852839 /* Only delete it when it's not being used. Otherwise it's done
27862840 * when "uf_calls" becomes zero. */
27872841 if (fp -> uf_calls == 0 )
2788- func_free (fp , FALSE);
2842+ func_clear_free (fp , FALSE);
27892843 }
27902844}
27912845
@@ -2801,7 +2855,7 @@ func_ptr_unref(ufunc_T *fp)
28012855 /* Only delete it when it's not being used. Otherwise it's done
28022856 * when "uf_calls" becomes zero. */
28032857 if (fp -> uf_calls == 0 )
2804- func_free (fp , FALSE);
2858+ func_clear_free (fp , FALSE);
28052859 }
28062860}
28072861
0 commit comments