Patch 8.2.1712
Problem:    Vim9: leaking memory when calling a lambda.
Solution:   Decrement function reference from ISN_DCALL.
Files:      src/vim9compile.c, src/userfunc.c, src/proto/userfunc.pro


*** ../vim-8.2.1711/src/vim9compile.c   2020-09-19 15:16:46.395622457 +0200
--- src/vim9compile.c   2020-09-19 18:05:00.907313691 +0200
***************
*** 1452,1458 ****
                    ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
                                                         : ISN_UCALL)) == NULL)
        return FAIL;
!     if (ufunc->uf_def_status != UF_NOT_COMPILED)
      {
        isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
        isn->isn_arg.dfunc.cdf_argcount = argcount;
--- 1452,1458 ----
                    ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
                                                         : ISN_UCALL)) == NULL)
        return FAIL;
!     if (isn->isn_type == ISN_DCALL)
      {
        isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
        isn->isn_arg.dfunc.cdf_argcount = argcount;
***************
*** 2634,2641 ****
      clear_tv(&rettv);
      ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
  
!     // The function will have one line: "return {expr}".
!     // Compile it into instructions.
      compile_def_function(ufunc, TRUE, cctx);
  
      // compile the arguments
--- 2634,2641 ----
      clear_tv(&rettv);
      ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
  
!     // The function will have one line: "return {expr}".  Compile it into
!     // instructions so that we get any errors right now.
      compile_def_function(ufunc, TRUE, cctx);
  
      // compile the arguments
***************
*** 7285,7291 ****
            {
                dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
                                               + isn->isn_arg.funcref.fr_func;
!               func_ptr_unref(dfunc->df_ufunc);
            }
            break;
  
--- 7285,7303 ----
            {
                dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
                                               + isn->isn_arg.funcref.fr_func;
! 
!               if (func_name_refcount(dfunc->df_ufunc->uf_name))
!                   func_ptr_unref(dfunc->df_ufunc);
!           }
!           break;
! 
!       case ISN_DCALL:
!           {
!               dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
!                                              + isn->isn_arg.dfunc.cdf_idx;
! 
!               if (func_name_refcount(dfunc->df_ufunc->uf_name))
!                   func_ptr_unref(dfunc->df_ufunc);
            }
            break;
  
***************
*** 7333,7339 ****
        case ISN_COMPARESPECIAL:
        case ISN_COMPARESTRING:
        case ISN_CONCAT:
-       case ISN_DCALL:
        case ISN_DROP:
        case ISN_ECHO:
        case ISN_ECHOERR:
--- 7345,7350 ----
*** ../vim-8.2.1711/src/userfunc.c      2020-09-19 15:16:46.395622457 +0200
--- src/userfunc.c      2020-09-19 18:04:40.459403238 +0200
***************
*** 1058,1064 ****
   * using function() does not count as a reference, because the function is
   * looked up by name.
   */
!     static int
  func_name_refcount(char_u *name)
  {
      return isdigit(*name) || *name == '<';
--- 1058,1064 ----
   * using function() does not count as a reference, because the function is
   * looked up by name.
   */
!     int
  func_name_refcount(char_u *name)
  {
      return isdigit(*name) || *name == '<';
***************
*** 1176,1183 ****
   * Free a function and remove it from the list of functions.  Does not free
   * what a function contains, call func_clear() first.
   * When "force" is TRUE we are exiting.
   */
!     static void
  func_free(ufunc_T *fp, int force)
  {
      // Only remove it when not done already, otherwise we would remove a newer
--- 1176,1184 ----
   * Free a function and remove it from the list of functions.  Does not free
   * what a function contains, call func_clear() first.
   * When "force" is TRUE we are exiting.
+  * Returns OK when the function was actually freed.
   */
!     static int
  func_free(ufunc_T *fp, int force)
  {
      // Only remove it when not done already, otherwise we would remove a newer
***************
*** 1191,1197 ****
--- 1192,1200 ----
            unlink_def_function(fp);
        VIM_CLEAR(fp->uf_name_exp);
        vim_free(fp);
+       return OK;
      }
+     return FAIL;
  }
  
  /*
***************
*** 1890,1898 ****
                    ++skipped;
                else
                {
!                   func_free(fp, FALSE);
!                   skipped = 0;
!                   break;
                }
            }
      }
--- 1893,1905 ----
                    ++skipped;
                else
                {
!                   if (func_free(fp, FALSE) == OK)
!                   {
!                       skipped = 0;
!                       break;
!                   }
!                   // did not actually free it
!                   ++skipped;
                }
            }
      }
*** ../vim-8.2.1711/src/proto/userfunc.pro      2020-09-12 18:32:30.683427305 
+0200
--- src/proto/userfunc.pro      2020-09-19 18:04:43.675389188 +0200
***************
*** 12,17 ****
--- 12,18 ----
  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 copy_func(char_u *lambda, char_u *global);
  int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, 
typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
  void save_funccal(funccal_entry_T *entry);
*** ../vim-8.2.1711/src/version.c       2020-09-19 15:16:46.399622447 +0200
--- src/version.c       2020-09-19 18:17:36.135766329 +0200
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     1712,
  /**/

-- 
If you don't get everything you want, think of
everything you didn't get and don't want.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202009191621.08JGLAXg2956400%40masaka.moolenaar.net.

Raspunde prin e-mail lui