Skip to content

Commit e20c946

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 79bbe33 + 5f436fc commit e20c946

File tree

5 files changed

+76
-32
lines changed

5 files changed

+76
-32
lines changed

src/Make_cyg_ming.mak

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ WINDRES_CC = $(CC)
415415
###########################################################################
416416

417417
CFLAGS = -Iproto $(DEFINES) -pipe -march=$(ARCH) -Wall
418-
CXXFLAGS = -std=c++11
418+
CXXFLAGS = -std=gnu++11
419419
WINDRES_FLAGS = --preprocessor="$(WINDRES_CC) -E -xc" -DRC_INVOKED
420420
EXTRA_LIBS =
421421

src/eval.c

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ static hashtab_T func_hashtab;
209209
/* The names of packages that once were loaded are remembered. */
210210
static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
211211

212-
/* list heads for garbage collection */
212+
/* List heads for garbage collection. Although there can be a reference loop
213+
* from partial to dict to partial, we don't need to keep track of the partial,
214+
* since it will get freed when the dict is unused and gets freed. */
213215
static dict_T *first_dict = NULL; /* list of all dicts */
214216
static list_T *first_list = NULL; /* list of all lists */
215217

@@ -7130,9 +7132,14 @@ set_ref_in_item(
71307132
list_T *ll;
71317133
int abort = FALSE;
71327134

7133-
if (tv->v_type == VAR_DICT)
7135+
if (tv->v_type == VAR_DICT || tv->v_type == VAR_PARTIAL)
71347136
{
7135-
dd = tv->vval.v_dict;
7137+
if (tv->v_type == VAR_DICT)
7138+
dd = tv->vval.v_dict;
7139+
else if (tv->vval.v_partial != NULL)
7140+
dd = tv->vval.v_partial->pt_dict;
7141+
else
7142+
dd = NULL;
71367143
if (dd != NULL && dd->dv_copyID != copyID)
71377144
{
71387145
/* Didn't see this dict yet. */
@@ -7184,6 +7191,32 @@ set_ref_in_item(
71847191
return abort;
71857192
}
71867193

7194+
static void
7195+
partial_free(partial_T *pt, int free_dict)
7196+
{
7197+
int i;
7198+
7199+
for (i = 0; i < pt->pt_argc; ++i)
7200+
clear_tv(&pt->pt_argv[i]);
7201+
vim_free(pt->pt_argv);
7202+
if (free_dict)
7203+
dict_unref(pt->pt_dict);
7204+
func_unref(pt->pt_name);
7205+
vim_free(pt->pt_name);
7206+
vim_free(pt);
7207+
}
7208+
7209+
/*
7210+
* Unreference a closure: decrement the reference count and free it when it
7211+
* becomes zero.
7212+
*/
7213+
void
7214+
partial_unref(partial_T *pt)
7215+
{
7216+
if (pt != NULL && --pt->pt_refcount <= 0)
7217+
partial_free(pt, TRUE);
7218+
}
7219+
71877220
/*
71887221
* Allocate an empty header for a dictionary.
71897222
*/
@@ -7275,7 +7308,18 @@ dict_free(
72757308
hash_remove(&d->dv_hashtab, hi);
72767309
if (recurse || (di->di_tv.v_type != VAR_LIST
72777310
&& di->di_tv.v_type != VAR_DICT))
7278-
clear_tv(&di->di_tv);
7311+
{
7312+
if (!recurse && di->di_tv.v_type == VAR_PARTIAL)
7313+
{
7314+
partial_T *pt = di->di_tv.vval.v_partial;
7315+
7316+
/* We unref the partial but not the dict it refers to. */
7317+
if (pt != NULL && --pt->pt_refcount == 0)
7318+
partial_free(pt, FALSE);
7319+
}
7320+
else
7321+
clear_tv(&di->di_tv);
7322+
}
72797323
vim_free(di);
72807324
--todo;
72817325
}
@@ -12011,30 +12055,6 @@ f_function(typval_T *argvars, typval_T *rettv)
1201112055
}
1201212056
}
1201312057

12014-
static void
12015-
partial_free(partial_T *pt)
12016-
{
12017-
int i;
12018-
12019-
for (i = 0; i < pt->pt_argc; ++i)
12020-
clear_tv(&pt->pt_argv[i]);
12021-
vim_free(pt->pt_argv);
12022-
func_unref(pt->pt_name);
12023-
vim_free(pt->pt_name);
12024-
vim_free(pt);
12025-
}
12026-
12027-
/*
12028-
* Unreference a closure: decrement the reference count and free it when it
12029-
* becomes zero.
12030-
*/
12031-
void
12032-
partial_unref(partial_T *pt)
12033-
{
12034-
if (pt != NULL && --pt->pt_refcount <= 0)
12035-
partial_free(pt);
12036-
}
12037-
1203812058
/*
1203912059
* "garbagecollect()" function
1204012060
*/
@@ -21824,16 +21844,20 @@ handle_subscript(
2182421844
selfdict = NULL;
2182521845
if (rettv->v_type == VAR_FUNC)
2182621846
{
21827-
/* just a function: use selfdict */
21847+
/* Just a function: Take over the function name and use
21848+
* selfdict. */
2182821849
pt->pt_name = rettv->vval.v_string;
2182921850
}
2183021851
else
2183121852
{
2183221853
partial_T *ret_pt = rettv->vval.v_partial;
2183321854
int i;
2183421855

21835-
/* partial: use selfdict and copy args */
21856+
/* Partial: copy the function name, use selfdict and copy
21857+
* args. Can't take over name or args, the partial might
21858+
* be referenced elsewhere. */
2183621859
pt->pt_name = vim_strsave(ret_pt->pt_name);
21860+
func_ref(pt->pt_name);
2183721861
if (ret_pt->pt_argc > 0)
2183821862
{
2183921863
pt->pt_argv = (typval_T *)alloc(
@@ -21850,7 +21874,6 @@ handle_subscript(
2185021874
}
2185121875
partial_unref(ret_pt);
2185221876
}
21853-
func_ref(pt->pt_name);
2185421877
rettv->v_type = VAR_PARTIAL;
2185521878
rettv->vval.v_partial = pt;
2185621879
}

src/ex_getln.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,7 @@ getcmdline_prompt(
19971997
char_u *s;
19981998
struct cmdline_info save_ccline;
19991999
int msg_col_save = msg_col;
2000+
int msg_silent_save = msg_silent;
20002001

20012002
save_cmdline(&save_ccline);
20022003
ccline.cmdprompt = prompt;
@@ -2006,8 +2007,10 @@ getcmdline_prompt(
20062007
ccline.xp_arg = xp_arg;
20072008
ccline.input_fn = (firstc == '@');
20082009
# endif
2010+
msg_silent = 0;
20092011
s = getcmdline(firstc, 1L, 0);
20102012
restore_cmdline(&save_ccline);
2013+
msg_silent = msg_silent_save;
20112014
/* Restore msg_col, the prompt from input() may have changed it.
20122015
* But only if called recursively and the commandline is therefore being
20132016
* restored to an old one; if not, the input() prompt stays on the screen,

src/testdir/test_partial.vim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,13 @@ func Test_partial_string()
170170
let F = function('MyFunc', ['foo'], d)
171171
call assert_equal("function('MyFunc', ['foo'], {'one': 1})", string(F))
172172
endfunc
173+
174+
func Test_func_unref()
175+
let obj = {}
176+
function! obj.func() abort
177+
endfunction
178+
let funcnumber = matchstr(string(obj.func), '^function(''\zs.\{-}\ze''')
179+
call assert_true(exists('*{' . funcnumber . '}'))
180+
unlet obj
181+
call assert_false(exists('*{' . funcnumber . '}'))
182+
endfunc

src/version.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,14 @@ static char *(features[]) =
763763

764764
static int included_patches[] =
765765
{ /* Add new patch number below this line */
766+
/**/
767+
1639,
768+
/**/
769+
1638,
770+
/**/
771+
1637,
772+
/**/
773+
1636,
766774
/**/
767775
1635,
768776
/**/

0 commit comments

Comments
 (0)