changeset 20297:5f0611bc6377 v8.2.0704

patch 8.2.0704: Vim9: memory leak in disassemble test Commit: https://github.com/vim/vim/commit/f821ddaa0c27230012a6bffbec6fb0ab2f101171 Author: Bram Moolenaar <Bram@vim.org> Date: Wed May 6 22:18:17 2020 +0200 patch 8.2.0704: Vim9: memory leak in disassemble test Problem: Vim9: memory leak in disassemble test. Solution: Decrement refcount when creating funccal.
author Bram Moolenaar <Bram@vim.org>
date Wed, 06 May 2020 22:30:04 +0200
parents f76a55f87992
children e679630d4e0e
files src/version.c src/vim9execute.c
diffstat 2 files changed, 29 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -270,7 +270,7 @@ handle_closure_in_use(ectx_T *ectx, int 
 	    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 
 	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;
 	}