diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-05-06 22:18:17 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-05-06 22:18:17 +0200 |
commit | f821ddaa0c27230012a6bffbec6fb0ab2f101171 (patch) | |
tree | 3f1ec3abf833b521b235e40415b108353d8973bb | |
parent | b68b346e6db6d3f848e0a89905fcd7777b73c5d8 (diff) |
patch 8.2.0704: Vim9: memory leak in disassemble testv8.2.0704
Problem: Vim9: memory leak in disassemble test.
Solution: Decrement refcount when creating funccal.
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 28 |
2 files changed, 29 insertions, 1 deletions
diff --git a/src/version.c b/src/version.c index b507c89b28..f22b37d4cb 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 704, +/**/ 703, /**/ 702, diff --git a/src/vim9execute.c b/src/vim9execute.c index 9651f5e9b2..cc677b0013 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -270,7 +270,7 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) int refcount = tv->vval.v_partial->pt_refcount; int i; - // A Reference in a local variables doesn't count, its get + // A Reference in a local variables doesn't count, it gets // unreferenced on return. for (i = 0; i < dfunc->df_varcount; ++i) { @@ -323,6 +323,32 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) for (idx = 0; idx < dfunc->df_varcount; ++idx) { tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); + + // Do not copy a partial created for a local function. + // TODO: this won't work if the closure actually uses it. But when + // keeping it it gets complicated: it will create a reference cycle + // inside the partial, thus needs special handling for garbage + // collection. + if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) + { + int i; + typval_T *ctv; + + for (i = 0; i < dfunc->df_closure_count; ++i) + { + ctv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + + dfunc->df_varcount + i); + if (tv->vval.v_partial == ctv->vval.v_partial) + break; + } + if (i < dfunc->df_closure_count) + { + (stack + argcount + STACK_FRAME_SIZE + idx)->v_type = + VAR_UNKNOWN; + continue; + } + } + *(stack + argcount + STACK_FRAME_SIZE + idx) = *tv; tv->v_type = VAR_UNKNOWN; } |