mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.1711: Vim9: leaking memory when using partial
Problem: Vim9: leaking memory when using partial. Solution: Do delete the function even when it was compiled.
This commit is contained in:
@@ -17,5 +17,6 @@ int compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx
|
|||||||
void set_function_type(ufunc_T *ufunc);
|
void set_function_type(ufunc_T *ufunc);
|
||||||
void delete_instr(isn_T *isn);
|
void delete_instr(isn_T *isn);
|
||||||
void clear_def_function(ufunc_T *ufunc);
|
void clear_def_function(ufunc_T *ufunc);
|
||||||
|
void unlink_def_function(ufunc_T *ufunc);
|
||||||
void free_def_functions(void);
|
void free_def_functions(void);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -1049,6 +1049,21 @@ cleanup_function_call(funccall_T *fc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are two kinds of function names:
|
||||||
|
* 1. ordinary names, function defined with :function or :def
|
||||||
|
* 2. numbered functions and lambdas
|
||||||
|
* For the first we only count the name stored in func_hashtab as a reference,
|
||||||
|
* 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 == '<';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unreference "fc": decrement the reference count and free it when it
|
* Unreference "fc": decrement the reference count and free it when it
|
||||||
* becomes zero. "fp" is detached from "fc".
|
* becomes zero. "fp" is detached from "fc".
|
||||||
@@ -1172,6 +1187,8 @@ func_free(ufunc_T *fp, int force)
|
|||||||
|
|
||||||
if ((fp->uf_flags & FC_DEAD) == 0 || force)
|
if ((fp->uf_flags & FC_DEAD) == 0 || force)
|
||||||
{
|
{
|
||||||
|
if (fp->uf_dfunc_idx > 0)
|
||||||
|
unlink_def_function(fp);
|
||||||
VIM_CLEAR(fp->uf_name_exp);
|
VIM_CLEAR(fp->uf_name_exp);
|
||||||
vim_free(fp);
|
vim_free(fp);
|
||||||
}
|
}
|
||||||
@@ -1185,7 +1202,8 @@ func_free(ufunc_T *fp, int force)
|
|||||||
func_clear_free(ufunc_T *fp, int force)
|
func_clear_free(ufunc_T *fp, int force)
|
||||||
{
|
{
|
||||||
func_clear(fp, force);
|
func_clear(fp, force);
|
||||||
if (force || fp->uf_dfunc_idx == 0 || (fp->uf_flags & FC_COPY))
|
if (force || fp->uf_dfunc_idx == 0 || func_name_refcount(fp->uf_name)
|
||||||
|
|| (fp->uf_flags & FC_COPY))
|
||||||
func_free(fp, force);
|
func_free(fp, force);
|
||||||
else
|
else
|
||||||
fp->uf_flags |= FC_DEAD;
|
fp->uf_flags |= FC_DEAD;
|
||||||
@@ -1730,20 +1748,6 @@ call_user_func_check(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* There are two kinds of function names:
|
|
||||||
* 1. ordinary names, function defined with :function
|
|
||||||
* 2. numbered functions and lambdas
|
|
||||||
* For the first we only count the name stored in func_hashtab as a reference,
|
|
||||||
* 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 == '<';
|
|
||||||
}
|
|
||||||
|
|
||||||
static funccal_entry_T *funccal_stack = NULL;
|
static funccal_entry_T *funccal_stack = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1711,
|
||||||
/**/
|
/**/
|
||||||
1710,
|
1710,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2593,6 +2593,9 @@ compile_lambda(char_u **arg, cctx_T *cctx)
|
|||||||
// The return type will now be known.
|
// The return type will now be known.
|
||||||
set_function_type(ufunc);
|
set_function_type(ufunc);
|
||||||
|
|
||||||
|
// The function reference count will be 1. When the ISN_FUNCREF
|
||||||
|
// instruction is deleted the reference count is decremented and the
|
||||||
|
// function is freed.
|
||||||
return generate_FUNCREF(cctx, ufunc);
|
return generate_FUNCREF(cctx, ufunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7424,6 +7427,18 @@ clear_def_function(ufunc_T *ufunc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used when a user function is about to be deleted: remove the pointer to it.
|
||||||
|
* The entry in def_functions is then unused.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
unlink_def_function(ufunc_T *ufunc)
|
||||||
|
{
|
||||||
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
||||||
|
|
||||||
|
dfunc->df_ufunc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE) || defined(PROTO)
|
#if defined(EXITFREE) || defined(PROTO)
|
||||||
/*
|
/*
|
||||||
* Free all functions defined with ":def".
|
* Free all functions defined with ":def".
|
||||||
|
@@ -270,12 +270,18 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
|
|||||||
{
|
{
|
||||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
+ ectx->ec_dfunc_idx;
|
+ ectx->ec_dfunc_idx;
|
||||||
int argcount = ufunc_argcount(dfunc->df_ufunc);
|
int argcount;
|
||||||
int top = ectx->ec_frame_idx - argcount;
|
int top;
|
||||||
int idx;
|
int idx;
|
||||||
typval_T *tv;
|
typval_T *tv;
|
||||||
int closure_in_use = FALSE;
|
int closure_in_use = FALSE;
|
||||||
|
|
||||||
|
if (dfunc->df_ufunc == NULL)
|
||||||
|
// function was freed
|
||||||
|
return OK;
|
||||||
|
argcount = ufunc_argcount(dfunc->df_ufunc);
|
||||||
|
top = ectx->ec_frame_idx - argcount;
|
||||||
|
|
||||||
// Check if any created closure is still in use.
|
// Check if any created closure is still in use.
|
||||||
for (idx = 0; idx < dfunc->df_closure_count; ++idx)
|
for (idx = 0; idx < dfunc->df_closure_count; ++idx)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user