@@ -1075,12 +1075,17 @@ func_remove(ufunc_T *fp)
1075
1075
}
1076
1076
1077
1077
/*
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.
1079
1080
* When "force" is TRUE we are exiting.
1080
1081
*/
1081
1082
static void
1082
- func_free (ufunc_T * fp , int force )
1083
+ func_clear (ufunc_T * fp , int force )
1083
1084
{
1085
+ if (fp -> uf_cleared )
1086
+ return ;
1087
+ fp -> uf_cleared = TRUE;
1088
+
1084
1089
/* clear this function */
1085
1090
ga_clear_strings (& (fp -> uf_args ));
1086
1091
ga_clear_strings (& (fp -> uf_lines ));
@@ -1089,16 +1094,35 @@ func_free(ufunc_T *fp, int force)
1089
1094
vim_free (fp -> uf_tml_total );
1090
1095
vim_free (fp -> uf_tml_self );
1091
1096
#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
+ {
1092
1107
/* only remove it when not done already, otherwise we would remove a newer
1093
1108
* version of the function */
1094
1109
if ((fp -> uf_flags & (FC_DELETED | FC_REMOVED )) == 0 )
1095
1110
func_remove (fp );
1096
1111
1097
- funccal_unref (fp -> uf_scoped , fp , force );
1098
-
1099
1112
vim_free (fp );
1100
1113
}
1101
1114
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
+
1102
1126
/*
1103
1127
* There are two kinds of function names:
1104
1128
* 1. ordinary names, function defined with :function
@@ -1120,10 +1144,40 @@ free_all_functions(void)
1120
1144
hashitem_T * hi ;
1121
1145
ufunc_T * fp ;
1122
1146
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
+ }
1124
1177
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 ;
1127
1181
while (func_hashtab .ht_used > skipped )
1128
1182
{
1129
1183
todo = func_hashtab .ht_used ;
@@ -1138,7 +1192,7 @@ free_all_functions(void)
1138
1192
++ skipped ;
1139
1193
else
1140
1194
{
1141
- func_free (fp , TRUE );
1195
+ func_free (fp );
1142
1196
skipped = 0 ;
1143
1197
break ;
1144
1198
}
@@ -1356,7 +1410,7 @@ call_func(
1356
1410
if (-- fp -> uf_calls <= 0 && fp -> uf_refcount <= 0 )
1357
1411
/* Function was unreferenced while being used, free it
1358
1412
* now. */
1359
- func_free (fp , FALSE);
1413
+ func_clear_free (fp , FALSE);
1360
1414
if (did_save_redo )
1361
1415
restoreRedobuff ();
1362
1416
restore_search_patterns ();
@@ -2756,7 +2810,7 @@ ex_delfunction(exarg_T *eap)
2756
2810
fp -> uf_flags |= FC_DELETED ;
2757
2811
}
2758
2812
else
2759
- func_free (fp , FALSE);
2813
+ func_clear_free (fp , FALSE);
2760
2814
}
2761
2815
}
2762
2816
}
@@ -2785,7 +2839,7 @@ func_unref(char_u *name)
2785
2839
/* Only delete it when it's not being used. Otherwise it's done
2786
2840
* when "uf_calls" becomes zero. */
2787
2841
if (fp -> uf_calls == 0 )
2788
- func_free (fp , FALSE);
2842
+ func_clear_free (fp , FALSE);
2789
2843
}
2790
2844
}
2791
2845
@@ -2801,7 +2855,7 @@ func_ptr_unref(ufunc_T *fp)
2801
2855
/* Only delete it when it's not being used. Otherwise it's done
2802
2856
* when "uf_calls" becomes zero. */
2803
2857
if (fp -> uf_calls == 0 )
2804
- func_free (fp , FALSE);
2858
+ func_clear_free (fp , FALSE);
2805
2859
}
2806
2860
}
2807
2861
0 commit comments