Patch 8.2.2614
Problem: Vim9: function is deleted while executing.
Solution: increment the call count, when more than zero do not delete the
function but mark it as dead. (closes #7977)
Files: src/vim9execute.c, src/userfunc.c,
src/testdir/test_vim9_script.vim
*** ../vim-8.2.2613/src/vim9execute.c 2021-03-14 18:38:50.016676652 +0100
--- src/vim9execute.c 2021-03-17 14:36:37.714004999 +0100
***************
*** 323,328 ****
--- 323,330 ----
else
ectx->ec_outer = NULL;
+ ++ufunc->uf_calls;
+
// Set execution state to the start of the called function.
ectx->ec_dfunc_idx = cdf_idx;
ectx->ec_instr = INSTRUCTIONS(dfunc);
***************
*** 556,561 ****
--- 558,566 ----
}
}
#endif
+ // TODO: when is it safe to delete the function when it is no longer used?
+ --dfunc->df_ufunc->uf_calls;
+
// execution context goes one level up
entry = estack_pop();
if (entry != NULL)
***************
*** 1334,1340 ****
++ectx.ec_stack.ga_len;
}
if (ufunc->uf_va_name != NULL)
! ++ectx.ec_stack.ga_len;
// Frame pointer points to just after arguments.
ectx.ec_frame_idx = ectx.ec_stack.ga_len;
--- 1339,1345 ----
++ectx.ec_stack.ga_len;
}
if (ufunc->uf_va_name != NULL)
! ++ectx.ec_stack.ga_len;
// Frame pointer points to just after arguments.
ectx.ec_frame_idx = ectx.ec_stack.ga_len;
***************
*** 1407,1412 ****
--- 1412,1420 ----
// Do turn errors into exceptions.
suppress_errthrow = FALSE;
+ // Do not delete the function while executing it.
+ ++ufunc->uf_calls;
+
// When ":silent!" was used before calling then we still abort the
// function. If ":silent!" is used in the function then we don't.
emsg_silent_def = emsg_silent;
***************
*** 3838,3843 ****
--- 3846,3854 ----
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 (*msg_list != NULL && saved_msg_list != NULL)
{
msglist_T **plist = saved_msg_list;
*** ../vim-8.2.2613/src/userfunc.c 2021-03-06 22:33:09.009928681 +0100
--- src/userfunc.c 2021-03-17 14:48:52.748558096 +0100
***************
*** 1359,1367 ****
// function, so we can find the index when defining the function again.
// Do remove it when it's a copy.
if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0)
fp->uf_flags |= FC_DEAD;
! else
! hash_remove(&func_hashtab, hi);
return TRUE;
}
return FALSE;
--- 1359,1370 ----
// function, so we can find the index when defining the function again.
// Do remove it when it's a copy.
if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0)
+ {
fp->uf_flags |= FC_DEAD;
! return FALSE;
! }
! hash_remove(&func_hashtab, hi);
! fp->uf_flags |= FC_DELETED;
return TRUE;
}
return FALSE;
***************
*** 2134,2144 ****
int changed = func_hashtab.ht_changed;
fp->uf_flags |= FC_DEAD;
! func_clear(fp, TRUE);
! // When clearing a function another function can be cleared
! // as a side effect. When that happens start over.
! if (changed != func_hashtab.ht_changed)
! break;
}
--todo;
}
--- 2137,2159 ----
int changed = func_hashtab.ht_changed;
fp->uf_flags |= FC_DEAD;
!
! if (fp->uf_calls > 0)
! {
! // Function is executing, don't free it but do remove
! // it from the hashtable.
! if (func_remove(fp))
! fp->uf_refcount--;
! }
! else
! {
! func_clear(fp, TRUE);
! // When clearing a function another function can be
! // cleared as a side effect. When that happens start
! // over.
! if (changed != func_hashtab.ht_changed)
! break;
! }
}
--todo;
}
***************
*** 4251,4257 ****
// do remove it from the hashtable.
if (func_remove(fp))
fp->uf_refcount--;
- fp->uf_flags |= FC_DELETED;
}
else
func_clear_free(fp, FALSE);
--- 4266,4271 ----
*** ../vim-8.2.2613/src/testdir/test_vim9_script.vim 2021-03-14
12:13:30.192279488 +0100
--- src/testdir/test_vim9_script.vim 2021-03-17 14:56:02.523543957 +0100
***************
*** 1561,1566 ****
--- 1561,1595 ----
delete('Xreload.vim')
enddef
+ " Define CallFunc so that the test can be compiled
+ command CallFunc echo 'nop'
+
+ def Test_script_reload_from_function()
+ var lines =<< trim END
+ vim9script
+
+ if exists('g:loaded')
+ finish
+ endif
+ g:loaded = 1
+ delcommand CallFunc
+ command CallFunc Func()
+ def Func()
+ so /tmp/test.vim
+ g:didTheFunc = 1
+ enddef
+ END
+ writefile(lines, 'XreloadFunc.vim')
+ source XreloadFunc.vim
+ CallFunc
+ assert_equal(1, g:didTheFunc)
+
+ delete('XreloadFunc.vim')
+ delcommand CallFunc
+ unlet g:loaded
+ unlet g:didTheFunc
+ enddef
+
def Test_script_var_shadows_function()
var lines =<< trim END
vim9script
*** ../vim-8.2.2613/src/version.c 2021-03-17 13:39:30.657050576 +0100
--- src/version.c 2021-03-17 14:30:06.690693111 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2614,
/**/
--
Engineers are always delighted to share wisdom, even in areas in which they
have no experience whatsoever. Their logic provides them with inherent
insight into any field of expertise. This can be a problem when dealing with
the illogical people who believe that knowledge can only be derived through
experience.
(Scott Adams - The Dilbert principle)
/// 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/202103171404.12HE4cTV1009948%40masaka.moolenaar.net.