@@ -41,7 +41,7 @@ static garray_T funcargs = GA_EMPTY;
4141/* pointer to funccal for currently active function */
4242funccall_T * current_funccal = NULL ;
4343
44- /* pointer to list of previously used funccal, still around because some
44+ /* Pointer to list of previously used funccal, still around because some
4545 * item in it is still being used. */
4646funccall_T * previous_funccal = NULL ;
4747
@@ -627,6 +627,55 @@ free_funccal(
627627 vim_free (fc );
628628}
629629
630+ /*
631+ * Handle the last part of returning from a function: free the local hashtable.
632+ * Unless it is still in use by a closure.
633+ */
634+ static void
635+ cleanup_function_call (funccall_T * fc )
636+ {
637+ current_funccal = fc -> caller ;
638+
639+ /* If the a:000 list and the l: and a: dicts are not referenced and there
640+ * is no closure using it, we can free the funccall_T and what's in it. */
641+ if (fc -> l_varlist .lv_refcount == DO_NOT_FREE_CNT
642+ && fc -> l_vars .dv_refcount == DO_NOT_FREE_CNT
643+ && fc -> l_avars .dv_refcount == DO_NOT_FREE_CNT
644+ && fc -> fc_refcount <= 0 )
645+ {
646+ free_funccal (fc , FALSE);
647+ }
648+ else
649+ {
650+ hashitem_T * hi ;
651+ listitem_T * li ;
652+ int todo ;
653+ dictitem_T * v ;
654+
655+ /* "fc" is still in use. This can happen when returning "a:000",
656+ * assigning "l:" to a global variable or defining a closure.
657+ * Link "fc" in the list for garbage collection later. */
658+ fc -> caller = previous_funccal ;
659+ previous_funccal = fc ;
660+
661+ /* Make a copy of the a: variables, since we didn't do that above. */
662+ todo = (int )fc -> l_avars .dv_hashtab .ht_used ;
663+ for (hi = fc -> l_avars .dv_hashtab .ht_array ; todo > 0 ; ++ hi )
664+ {
665+ if (!HASHITEM_EMPTY (hi ))
666+ {
667+ -- todo ;
668+ v = HI2DI (hi );
669+ copy_tv (& v -> di_tv , & v -> di_tv );
670+ }
671+ }
672+
673+ /* Make a copy of the a:000 items, since we didn't do that above. */
674+ for (li = fc -> l_varlist .lv_first ; li != NULL ; li = li -> li_next )
675+ copy_tv (& li -> li_tv , & li -> li_tv );
676+ }
677+ }
678+
630679/*
631680 * Call a user function.
632681 */
@@ -982,46 +1031,9 @@ call_user_func(
9821031 }
9831032
9841033 did_emsg |= save_did_emsg ;
985- current_funccal = fc -> caller ;
9861034 -- depth ;
9871035
988- /* If the a:000 list and the l: and a: dicts are not referenced and there
989- * is no closure using it, we can free the funccall_T and what's in it. */
990- if (fc -> l_varlist .lv_refcount == DO_NOT_FREE_CNT
991- && fc -> l_vars .dv_refcount == DO_NOT_FREE_CNT
992- && fc -> l_avars .dv_refcount == DO_NOT_FREE_CNT
993- && fc -> fc_refcount <= 0 )
994- {
995- free_funccal (fc , FALSE);
996- }
997- else
998- {
999- hashitem_T * hi ;
1000- listitem_T * li ;
1001- int todo ;
1002-
1003- /* "fc" is still in use. This can happen when returning "a:000",
1004- * assigning "l:" to a global variable or defining a closure.
1005- * Link "fc" in the list for garbage collection later. */
1006- fc -> caller = previous_funccal ;
1007- previous_funccal = fc ;
1008-
1009- /* Make a copy of the a: variables, since we didn't do that above. */
1010- todo = (int )fc -> l_avars .dv_hashtab .ht_used ;
1011- for (hi = fc -> l_avars .dv_hashtab .ht_array ; todo > 0 ; ++ hi )
1012- {
1013- if (!HASHITEM_EMPTY (hi ))
1014- {
1015- -- todo ;
1016- v = HI2DI (hi );
1017- copy_tv (& v -> di_tv , & v -> di_tv );
1018- }
1019- }
1020-
1021- /* Make a copy of the a:000 items, since we didn't do that above. */
1022- for (li = fc -> l_varlist .lv_first ; li != NULL ; li = li -> li_next )
1023- copy_tv (& li -> li_tv , & li -> li_tv );
1024- }
1036+ cleanup_function_call (fc );
10251037}
10261038
10271039/*
@@ -1147,6 +1159,13 @@ free_all_functions(void)
11471159 long_u todo = 1 ;
11481160 long_u used ;
11491161
1162+ /* Clean up the call stack. */
1163+ while (current_funccal != NULL )
1164+ {
1165+ clear_tv (current_funccal -> rettv );
1166+ cleanup_function_call (current_funccal );
1167+ }
1168+
11501169 /* First clear what the functions contain. Since this may lower the
11511170 * reference count of a function, it may also free a function and change
11521171 * the hash table. Restart if that happens. */
0 commit comments