]> granicus.if.org Git - vim/commitdiff
patch 8.2.3753: Vim9: function unreferenced while called is never deleted v8.2.3753
authorBram Moolenaar <Bram@vim.org>
Mon, 6 Dec 2021 15:06:54 +0000 (15:06 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 6 Dec 2021 15:06:54 +0000 (15:06 +0000)
Problem:    Vim9: function unreferenced while called is never deleted.
Solution:   Delete a function when no longer referenced.

src/proto/userfunc.pro
src/userfunc.c
src/version.c
src/vim9execute.c

index b5ea9b6662cc0f869628c31e8dd64e4730400fdd..85144482e64220cb8d8b2498f369053c8c0b7eab 100644 (file)
@@ -12,6 +12,7 @@ ufunc_T *find_func_even_dead(char_u *name, int is_global, cctx_T *cctx);
 ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
 int func_is_global(ufunc_T *ufunc);
 int func_name_refcount(char_u *name);
+void func_clear_free(ufunc_T *fp, int force);
 int copy_func(char_u *lambda, char_u *global, ectx_T *ectx);
 int funcdepth_increment(void);
 void funcdepth_decrement(void);
index 7fc764e4df8a4e5c1b8ca1a975fa87542ada3180..4f86c07910bf3f978f74a82a2b242907ec30c205 100644 (file)
@@ -2281,7 +2281,7 @@ func_free(ufunc_T *fp, int force)
  * Free all things that a function contains and free the function itself.
  * When "force" is TRUE we are exiting.
  */
-    static void
+    void
 func_clear_free(ufunc_T *fp, int force)
 {
     func_clear(fp, force);
index 6d63569671ce8918d72015c3c0814ce56e0e53b2..aff25cfdd2487c846044f6a5c6cc66fb301c048a 100644 (file)
@@ -753,6 +753,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3753,
 /**/
     3752,
 /**/
index adfb9207ccbab697f367304fcd3016ae3dd549e3..f805dc0f14911653d9275ff7e338f545de3f31c5 100644 (file)
@@ -4988,8 +4988,9 @@ call_def_function(
     estack_pop();
     current_sctx = save_current_sctx;
 
-    // TODO: when is it safe to delete the function if it is no longer used?
-    --ufunc->uf_calls;
+    if (--ufunc->uf_calls <= 0 && ufunc->uf_refcount <= 0)
+       // Function was unreferenced while being used, free it now.
+       func_clear_free(ufunc, FALSE);
 
     if (*msg_list != NULL && saved_msg_list != NULL)
     {