]> git.pld-linux.org Git - packages/vim.git/blame - 7.2.070
- updated to 7.2.102
[packages/vim.git] / 7.2.070
CommitLineData
65bfde4c
AG
1To: vim-dev@vim.org
2Subject: Patch 7.2.070
3Fcc: outbox
4From: Bram Moolenaar <Bram@moolenaar.net>
5Mime-Version: 1.0
6Content-Type: text/plain; charset=ISO-8859-1
7Content-Transfer-Encoding: 8bit
8------------
9
10Patch 7.2.070
11Problem: Crash when a function returns a:000. (Matt Wozkiski)
12Solution: Don't put the function struct on the stack, allocate it. Free it
13 only when nothing in it is used.
14Files: src/eval.c
15
16
17*** ../vim-7.2.069/src/eval.c Tue Dec 9 10:56:50 2008
18--- src/eval.c Wed Dec 17 21:32:26 2008
19***************
20*** 32,37 ****
21--- 32,40 ----
22
23 #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
24
25+ #define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not
26+ be freed. */
27+
28 /*
29 * In a hashtab item "hi_key" points to "di_key" in a dictitem.
30 * This avoids adding a pointer to the hashtab item.
31***************
32*** 789,794 ****
33--- 792,799 ----
34 static void func_unref __ARGS((char_u *name));
35 static void func_ref __ARGS((char_u *name));
36 static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
37+ static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
38+ static void free_funccal __ARGS((funccall_T *fc, int free_val));
39 static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
40 static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp));
41 static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
42***************
43*** 923,928 ****
44--- 928,937 ----
45 /* pointer to funccal for currently active function */
46 funccall_T *current_funccal = NULL;
47
48+ /* pointer to list of previously used funccal, still around because some
49+ * item in it is still being used. */
50+ funccall_T *previous_funccal = NULL;
51+
52 /*
53 * Return TRUE when a function was ended by a ":return" command.
54 */
55***************
56*** 6490,6496 ****
57 buf_T *buf;
58 win_T *wp;
59 int i;
60! funccall_T *fc;
61 int did_free = FALSE;
62 #ifdef FEAT_WINDOWS
63 tabpage_T *tp;
64--- 6499,6505 ----
65 buf_T *buf;
66 win_T *wp;
67 int i;
68! funccall_T *fc, **pfc;
69 int did_free = FALSE;
70 #ifdef FEAT_WINDOWS
71 tabpage_T *tp;
72***************
73*** 6574,6579 ****
74--- 6583,6602 ----
75 else
76 ll = ll->lv_used_next;
77
78+ /* check if any funccal can be freed now */
79+ for (pfc = &previous_funccal; *pfc != NULL; )
80+ {
81+ if (can_free_funccal(*pfc, copyID))
82+ {
83+ fc = *pfc;
84+ *pfc = fc->caller;
85+ free_funccal(fc, TRUE);
86+ did_free = TRUE;
87+ }
88+ else
89+ pfc = &(*pfc)->caller;
90+ }
91+
92 return did_free;
93 }
94
95***************
96*** 18962,18968 ****
97 dictitem_T *dict_var;
98 {
99 hash_init(&dict->dv_hashtab);
100! dict->dv_refcount = 99999;
101 dict_var->di_tv.vval.v_dict = dict;
102 dict_var->di_tv.v_type = VAR_DICT;
103 dict_var->di_tv.v_lock = VAR_FIXED;
104--- 18985,18991 ----
105 dictitem_T *dict_var;
106 {
107 hash_init(&dict->dv_hashtab);
108! dict->dv_refcount = DO_NOT_FREE_CNT;
109 dict_var->di_tv.vval.v_dict = dict;
110 dict_var->di_tv.v_type = VAR_DICT;
111 dict_var->di_tv.v_lock = VAR_FIXED;
112***************
113*** 19299,19304 ****
114--- 19322,19329 ----
115 * Copy the values from typval_T "from" to typval_T "to".
116 * When needed allocates string or increases reference count.
117 * Does not make a copy of a list or dict but copies the reference!
118+ * It is OK for "from" and "to" to point to the same item. This is used to
119+ * make a copy later.
120 */
121 static void
122 copy_tv(from, to)
123***************
124*** 21111,21117 ****
125 char_u *save_sourcing_name;
126 linenr_T save_sourcing_lnum;
127 scid_T save_current_SID;
128! funccall_T fc;
129 int save_did_emsg;
130 static int depth = 0;
131 dictitem_T *v;
132--- 21136,21142 ----
133 char_u *save_sourcing_name;
134 linenr_T save_sourcing_lnum;
135 scid_T save_current_SID;
136! funccall_T *fc;
137 int save_did_emsg;
138 static int depth = 0;
139 dictitem_T *v;
140***************
141*** 21137,21172 ****
142
143 line_breakcheck(); /* check for CTRL-C hit */
144
145! fc.caller = current_funccal;
146! current_funccal = &fc;
147! fc.func = fp;
148! fc.rettv = rettv;
149 rettv->vval.v_number = 0;
150! fc.linenr = 0;
151! fc.returned = FALSE;
152! fc.level = ex_nesting_level;
153 /* Check if this function has a breakpoint. */
154! fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
155! fc.dbg_tick = debug_tick;
156
157 /*
158! * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
159 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
160 * each argument variable and saves a lot of time.
161 */
162 /*
163 * Init l: variables.
164 */
165! init_var_dict(&fc.l_vars, &fc.l_vars_var);
166 if (selfdict != NULL)
167 {
168 /* Set l:self to "selfdict". Use "name" to avoid a warning from
169 * some compiler that checks the destination size. */
170! v = &fc.fixvar[fixvar_idx++].var;
171 name = v->di_key;
172 STRCPY(name, "self");
173 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
174! hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
175 v->di_tv.v_type = VAR_DICT;
176 v->di_tv.v_lock = 0;
177 v->di_tv.vval.v_dict = selfdict;
178--- 21162,21198 ----
179
180 line_breakcheck(); /* check for CTRL-C hit */
181
182! fc = (funccall_T *)alloc(sizeof(funccall_T));
183! fc->caller = current_funccal;
184! current_funccal = fc;
185! fc->func = fp;
186! fc->rettv = rettv;
187 rettv->vval.v_number = 0;
188! fc->linenr = 0;
189! fc->returned = FALSE;
190! fc->level = ex_nesting_level;
191 /* Check if this function has a breakpoint. */
192! fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
193! fc->dbg_tick = debug_tick;
194
195 /*
196! * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables
197 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
198 * each argument variable and saves a lot of time.
199 */
200 /*
201 * Init l: variables.
202 */
203! init_var_dict(&fc->l_vars, &fc->l_vars_var);
204 if (selfdict != NULL)
205 {
206 /* Set l:self to "selfdict". Use "name" to avoid a warning from
207 * some compiler that checks the destination size. */
208! v = &fc->fixvar[fixvar_idx++].var;
209 name = v->di_key;
210 STRCPY(name, "self");
211 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
212! hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
213 v->di_tv.v_type = VAR_DICT;
214 v->di_tv.v_lock = 0;
215 v->di_tv.vval.v_dict = selfdict;
216***************
217*** 21178,21208 ****
218 * Set a:0 to "argcount".
219 * Set a:000 to a list with room for the "..." arguments.
220 */
221! init_var_dict(&fc.l_avars, &fc.l_avars_var);
222! add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
223 (varnumber_T)(argcount - fp->uf_args.ga_len));
224 /* Use "name" to avoid a warning from some compiler that checks the
225 * destination size. */
226! v = &fc.fixvar[fixvar_idx++].var;
227 name = v->di_key;
228 STRCPY(name, "000");
229 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
230! hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
231 v->di_tv.v_type = VAR_LIST;
232 v->di_tv.v_lock = VAR_FIXED;
233! v->di_tv.vval.v_list = &fc.l_varlist;
234! vim_memset(&fc.l_varlist, 0, sizeof(list_T));
235! fc.l_varlist.lv_refcount = 99999;
236! fc.l_varlist.lv_lock = VAR_FIXED;
237
238 /*
239 * Set a:firstline to "firstline" and a:lastline to "lastline".
240 * Set a:name to named arguments.
241 * Set a:N to the "..." arguments.
242 */
243! add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
244 (varnumber_T)firstline);
245! add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
246 (varnumber_T)lastline);
247 for (i = 0; i < argcount; ++i)
248 {
249--- 21204,21234 ----
250 * Set a:0 to "argcount".
251 * Set a:000 to a list with room for the "..." arguments.
252 */
253! init_var_dict(&fc->l_avars, &fc->l_avars_var);
254! add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
255 (varnumber_T)(argcount - fp->uf_args.ga_len));
256 /* Use "name" to avoid a warning from some compiler that checks the
257 * destination size. */
258! v = &fc->fixvar[fixvar_idx++].var;
259 name = v->di_key;
260 STRCPY(name, "000");
261 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
262! hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
263 v->di_tv.v_type = VAR_LIST;
264 v->di_tv.v_lock = VAR_FIXED;
265! v->di_tv.vval.v_list = &fc->l_varlist;
266! vim_memset(&fc->l_varlist, 0, sizeof(list_T));
267! fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT;
268! fc->l_varlist.lv_lock = VAR_FIXED;
269
270 /*
271 * Set a:firstline to "firstline" and a:lastline to "lastline".
272 * Set a:name to named arguments.
273 * Set a:N to the "..." arguments.
274 */
275! add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
276 (varnumber_T)firstline);
277! add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
278 (varnumber_T)lastline);
279 for (i = 0; i < argcount; ++i)
280 {
281***************
282*** 21218,21224 ****
283 }
284 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
285 {
286! v = &fc.fixvar[fixvar_idx++].var;
287 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
288 }
289 else
290--- 21244,21250 ----
291 }
292 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
293 {
294! v = &fc->fixvar[fixvar_idx++].var;
295 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
296 }
297 else
298***************
299*** 21230,21236 ****
300 v->di_flags = DI_FLAGS_RO;
301 }
302 STRCPY(v->di_key, name);
303! hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
304
305 /* Note: the values are copied directly to avoid alloc/free.
306 * "argvars" must have VAR_FIXED for v_lock. */
307--- 21256,21262 ----
308 v->di_flags = DI_FLAGS_RO;
309 }
310 STRCPY(v->di_key, name);
311! hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
312
313 /* Note: the values are copied directly to avoid alloc/free.
314 * "argvars" must have VAR_FIXED for v_lock. */
315***************
316*** 21239,21247 ****
317
318 if (ai >= 0 && ai < MAX_FUNC_ARGS)
319 {
320! list_append(&fc.l_varlist, &fc.l_listitems[ai]);
321! fc.l_listitems[ai].li_tv = argvars[i];
322! fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
323 }
324 }
325
326--- 21265,21273 ----
327
328 if (ai >= 0 && ai < MAX_FUNC_ARGS)
329 {
330! list_append(&fc->l_varlist, &fc->l_listitems[ai]);
331! fc->l_listitems[ai].li_tv = argvars[i];
332! fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED;
333 }
334 }
335
336***************
337*** 21306,21312 ****
338 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
339 func_do_profile(fp);
340 if (fp->uf_profiling
341! || (fc.caller != NULL && fc.caller->func->uf_profiling))
342 {
343 ++fp->uf_tm_count;
344 profile_start(&call_start);
345--- 21332,21338 ----
346 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
347 func_do_profile(fp);
348 if (fp->uf_profiling
349! || (fc->caller != NULL && fc->caller->func->uf_profiling))
350 {
351 ++fp->uf_tm_count;
352 profile_start(&call_start);
353***************
354*** 21322,21328 ****
355 did_emsg = FALSE;
356
357 /* call do_cmdline() to execute the lines */
358! do_cmdline(NULL, get_func_line, (void *)&fc,
359 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
360
361 --RedrawingDisabled;
362--- 21348,21354 ----
363 did_emsg = FALSE;
364
365 /* call do_cmdline() to execute the lines */
366! do_cmdline(NULL, get_func_line, (void *)fc,
367 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
368
369 --RedrawingDisabled;
370***************
371*** 21337,21352 ****
372
373 #ifdef FEAT_PROFILE
374 if (do_profiling == PROF_YES && (fp->uf_profiling
375! || (fc.caller != NULL && fc.caller->func->uf_profiling)))
376 {
377 profile_end(&call_start);
378 profile_sub_wait(&wait_start, &call_start);
379 profile_add(&fp->uf_tm_total, &call_start);
380 profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children);
381! if (fc.caller != NULL && fc.caller->func->uf_profiling)
382 {
383! profile_add(&fc.caller->func->uf_tm_children, &call_start);
384! profile_add(&fc.caller->func->uf_tml_children, &call_start);
385 }
386 }
387 #endif
388--- 21363,21378 ----
389
390 #ifdef FEAT_PROFILE
391 if (do_profiling == PROF_YES && (fp->uf_profiling
392! || (fc->caller != NULL && fc->caller->func->uf_profiling)))
393 {
394 profile_end(&call_start);
395 profile_sub_wait(&wait_start, &call_start);
396 profile_add(&fp->uf_tm_total, &call_start);
397 profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children);
398! if (fc->caller != NULL && fc->caller->func->uf_profiling)
399 {
400! profile_add(&fc->caller->func->uf_tm_children, &call_start);
401! profile_add(&fc->caller->func->uf_tml_children, &call_start);
402 }
403 }
404 #endif
405***************
406*** 21359,21367 ****
407
408 if (aborting())
409 smsg((char_u *)_("%s aborted"), sourcing_name);
410! else if (fc.rettv->v_type == VAR_NUMBER)
411 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
412! (long)fc.rettv->vval.v_number);
413 else
414 {
415 char_u buf[MSG_BUF_LEN];
416--- 21385,21393 ----
417
418 if (aborting())
419 smsg((char_u *)_("%s aborted"), sourcing_name);
420! else if (fc->rettv->v_type == VAR_NUMBER)
421 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
422! (long)fc->rettv->vval.v_number);
423 else
424 {
425 char_u buf[MSG_BUF_LEN];
426***************
427*** 21372,21378 ****
428 /* The value may be very long. Skip the middle part, so that we
429 * have some idea how it starts and ends. smsg() would always
430 * truncate it at the end. */
431! s = tv2string(fc.rettv, &tofree, numbuf2, 0);
432 if (s != NULL)
433 {
434 trunc_string(s, buf, MSG_BUF_CLEN);
435--- 21398,21404 ----
436 /* The value may be very long. Skip the middle part, so that we
437 * have some idea how it starts and ends. smsg() would always
438 * truncate it at the end. */
439! s = tv2string(fc->rettv, &tofree, numbuf2, 0);
440 if (s != NULL)
441 {
442 trunc_string(s, buf, MSG_BUF_CLEN);
443***************
444*** 21408,21421 ****
445 }
446
447 did_emsg |= save_did_emsg;
448! current_funccal = fc.caller;
449
450! /* The a: variables typevals were not allocated, only free the allocated
451! * variables. */
452! vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
453
454! vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
455! --depth;
456 }
457
458 /*
459--- 21434,21517 ----
460 }
461
462 did_emsg |= save_did_emsg;
463! current_funccal = fc->caller;
464! --depth;
465
466! /* if the a:000 list and the a: dict are not referenced we can free the
467! * funccall_T and what's in it. */
468! if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
469! && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
470! && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
471! {
472! free_funccal(fc, FALSE);
473! }
474! else
475! {
476! hashitem_T *hi;
477! listitem_T *li;
478! int todo;
479
480! /* "fc" is still in use. This can happen when returning "a:000" or
481! * assigning "l:" to a global variable.
482! * Link "fc" in the list for garbage collection later. */
483! fc->caller = previous_funccal;
484! previous_funccal = fc;
485!
486! /* Make a copy of the a: variables, since we didn't do that above. */
487! todo = (int)fc->l_avars.dv_hashtab.ht_used;
488! for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
489! {
490! if (!HASHITEM_EMPTY(hi))
491! {
492! --todo;
493! v = HI2DI(hi);
494! copy_tv(&v->di_tv, &v->di_tv);
495! }
496! }
497!
498! /* Make a copy of the a:000 items, since we didn't do that above. */
499! for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
500! copy_tv(&li->li_tv, &li->li_tv);
501! }
502! }
503!
504! /*
505! * Return TRUE if items in "fc" do not have "copyID". That means they are not
506! * referenced from anywyere.
507! */
508! static int
509! can_free_funccal(fc, copyID)
510! funccall_T *fc;
511! int copyID;
512! {
513! return (fc->l_varlist.lv_copyID != copyID
514! && fc->l_vars.dv_copyID != copyID
515! && fc->l_avars.dv_copyID != copyID);
516! }
517!
518! /*
519! * Free "fc" and what it contains.
520! */
521! static void
522! free_funccal(fc, free_val)
523! funccall_T *fc;
524! int free_val; /* a: vars were allocated */
525! {
526! listitem_T *li;
527!
528! /* The a: variables typevals may not have been allocated, only free the
529! * allocated variables. */
530! vars_clear_ext(&fc->l_avars.dv_hashtab, free_val);
531!
532! /* free all l: variables */
533! vars_clear(&fc->l_vars.dv_hashtab);
534!
535! /* Free the a:000 variables if they were allocated. */
536! if (free_val)
537! for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
538! clear_tv(&li->li_tv);
539!
540! vim_free(fc);
541 }
542
543 /*
544*** ../vim-7.2.069/src/version.c Tue Dec 9 22:34:02 2008
545--- src/version.c Sun Dec 21 12:47:07 2008
546***************
547*** 678,679 ****
548--- 678,681 ----
549 { /* Add new patch number below this line */
550+ /**/
551+ 70,
552 /**/
553
554--
555Close your shells, or I'll kill -9 you
556Tomorrow I'll quota you
557Remember the disks'll always be full
558And then while I'm away
559I'll write ~ everyday
560And I'll send-pr all my buggings to you.
561 [ CVS log "Beatles style" for FreeBSD ports/INDEX, Satoshi Asami ]
562
563 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
564/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
565\\\ download, build and distribute -- http://www.A-A-P.org ///
566 \\\ help me help AIDS victims -- http://ICCF-Holland.org ///
This page took 0.135007 seconds and 4 git commands to generate.