changeset 26445:568f93dcdc62 v8.2.3753

patch 8.2.3753: Vim9: function unreferenced while called is never deleted Commit: https://github.com/vim/vim/commit/2336c376d5796446d44622b0dfa8fd3fd1a5d22b Author: Bram Moolenaar <Bram@vim.org> Date: Mon Dec 6 15:06:54 2021 +0000 patch 8.2.3753: Vim9: function unreferenced while called is never deleted Problem: Vim9: function unreferenced while called is never deleted. Solution: Delete a function when no longer referenced.
author Bram Moolenaar <Bram@vim.org>
date Mon, 06 Dec 2021 16:15:03 +0100
parents aee00d57234d
children ad2d758d12ea
files src/proto/userfunc.pro src/userfunc.c src/version.c src/vim9execute.c
diffstat 4 files changed, 7 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/proto/userfunc.pro
+++ b/src/proto/userfunc.pro
@@ -12,6 +12,7 @@ ufunc_T *find_func_even_dead(char_u *nam
 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);
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -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);
--- a/src/version.c
+++ b/src/version.c
@@ -754,6 +754,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3753,
+/**/
     3752,
 /**/
     3751,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -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)
     {