cleanup_function_call(funccall_T *fc)
{
    int	may_free_fc = fc->fc_refcount <= 0;
    int	free_fc = TRUE;

    current_funccal = fc->caller;

    // Free all l: variables if not referred.
    if (may_free_fc && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT)
	vars_clear(&fc->l_vars.dv_hashtab);
    else
	free_fc = FALSE;

    // If the a:000 list and the l: and a: dicts are not referenced and
    // there is no closure using it, we can free the funccall_T and what's
    // in it.
    if (may_free_fc && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
	vars_clear_ext(&fc->l_avars.dv_hashtab, FALSE);
    else
    {
	int	    todo;
	hashitem_T  *hi;
	dictitem_T  *di;

	free_fc = FALSE;

	// Make a copy of the a: variables, since we didn't do that above.
	todo = (int)fc->l_avars.dv_hashtab.ht_used;
	for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
	{
	    if (!HASHITEM_EMPTY(hi))
	    {
		--todo;
		di = HI2DI(hi);
		copy_tv(&di->di_tv, &di->di_tv);
	    }
	}
    }

    if (may_free_fc && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT)
	fc->l_varlist.lv_first = NULL;
    else
    {
	listitem_T *li;

	free_fc = FALSE;

	// Make a copy of the a:000 items, since we didn't do that above.
	FOR_ALL_LIST_ITEMS(&fc->l_varlist, li)
	    copy_tv(&li->li_tv, &li->li_tv);
    }

    if (free_fc)
	free_funccal(fc);
    else
    {
	static int made_copy = 0;

	// "fc" is still in use.  This can happen when returning "a:000",
	// assigning "l:" to a global variable or defining a closure.
	// Link "fc" in the list for garbage collection later.
	fc->caller = previous_funccal;
	previous_funccal = fc;

	if (want_garbage_collect)
	    // If garbage collector is ready, clear count.
	    made_copy = 0;
	else if (++made_copy >= (int)((4096 * 1024) / sizeof(*fc)))
	{
	    // We have made a lot of copies, worth 4 Mbyte.  This can happen
	    // when repetitively calling a function that creates a reference to
	    // itself somehow.  Call the garbage collector soon to avoid using
	    // too much memory.
	    made_copy = 0;
	    want_garbage_collect = TRUE;
	}
    }
}
cleanup_function_call(funccall_T *fc)
{
    int	may_free_fc = fc->fc_refcount <= 0;
    int	free_fc = TRUE;

    current_funccal = fc->caller;

     
    if (may_free_fc && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT)
	vars_clear(&fc->l_vars.dv_hashtab);
    else
	free_fc = FALSE;

     
     
     
    if (may_free_fc && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
	vars_clear_ext(&fc->l_avars.dv_hashtab, FALSE);
    else
    {
	int	    todo;
	hashitem_T  *hi;
	dictitem_T  *di;

	free_fc = FALSE;

	 
	todo = (int)fc->l_avars.dv_hashtab.ht_used;
	for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
	{
	    if (!HASHITEM_EMPTY(hi))
	    {
		--todo;
		di = HI2DI(hi);
		copy_tv(&di->di_tv, &di->di_tv);
	    }
	}
    }

    if (may_free_fc && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT)
	fc->l_varlist.lv_first = NULL;
    else
    {
	listitem_T *li;

	free_fc = FALSE;

	 
	FOR_ALL_LIST_ITEMS(&fc->l_varlist, li)
	    copy_tv(&li->li_tv, &li->li_tv);
    }

    if (free_fc)
	free_funccal(fc);
    else
    {
	static int made_copy = 0;

	 
	 
	 
	fc->caller = previous_funccal;
	previous_funccal = fc;

	if (want_garbage_collect)
	     
	    made_copy = 0;
	else if (++made_copy >= (int)((4096 * 1024) / sizeof(*fc)))
	{
	     
	     
	     
	     
	    made_copy = 0;
	    want_garbage_collect = TRUE;
	}
    }
}