To: vim_dev@googlegroups.com Subject: Patch 8.1.0190 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0190 Problem: Perl refcounts are wrong. Solution: Improve refcounting. Add a test. (Damien) Files: src/if_perl.xs, src/testdir/test_perl.vim *** ../vim-8.1.0189/src/if_perl.xs 2018-07-08 17:18:58.416462371 +0200 --- src/if_perl.xs 2018-07-16 17:34:41.750473682 +0200 *************** *** 845,850 **** --- 845,858 ---- return sv_bless(rv, gv_stashpv("VIBUF", TRUE)); } + #if 0 + SV *__sv_save[1024]; + int __sv_save_ix; + # define D_Save_Sv(sv) do { if (__sv_save_ix < 1024) __sv_save[__sv_save_ix++] = (sv); } while (0) + #else + # define D_Save_Sv(sv) NOOP + #endif + /* * perl_win_free * Remove all references to the window to be destroyed *************** *** 852,868 **** void perl_win_free(win_T *wp) { ! if (wp->w_perl_private) ! sv_setiv((SV *)wp->w_perl_private, 0); ! return; } void perl_buf_free(buf_T *bp) { ! if (bp->b_perl_private) ! sv_setiv((SV *)bp->b_perl_private, 0); ! return; } #ifndef PROTO --- 860,886 ---- void perl_win_free(win_T *wp) { ! if (wp->w_perl_private && perl_interp != NULL) ! { ! SV *sv = (SV*)wp->w_perl_private; ! D_Save_Sv(sv); ! sv_setiv(sv, 0); ! SvREFCNT_dec(sv); ! } ! wp->w_perl_private = NULL; } void perl_buf_free(buf_T *bp) { ! if (bp->b_perl_private && perl_interp != NULL) ! { ! SV *sv = (SV *)bp->b_perl_private; ! D_Save_Sv(sv); ! sv_setiv(sv, 0); ! SvREFCNT_dec(sv); ! } ! bp->b_perl_private = NULL; } #ifndef PROTO *************** *** 885,896 **** # endif { SV *rv; if (iv == 0) rv = newWINrv(newSV(0), curwin); else rv = newBUFrv(newSV(0), curbuf); ! sv_setsv(sv, rv); ! SvREFCNT_dec(SvRV(rv)); return 0; } #endif /* !PROTO */ --- 903,921 ---- # endif { SV *rv; + if (iv == 0) rv = newWINrv(newSV(0), curwin); else rv = newBUFrv(newSV(0), curbuf); ! ! if (SvRV(sv) == SvRV(rv)) ! SvREFCNT_dec(SvRV(rv)); ! else /* XXX: Not sure if the `else` condition are right ! * Test_SvREFCNT() pass in all case. ! */ ! sv_setsv(sv, rv); ! return 0; } #endif /* !PROTO */ *************** *** 1539,1545 **** else { FOR_ALL_BUFFERS(vimbuf) ! XPUSHs(newBUFrv(newSV(0), vimbuf)); } } else --- 1564,1570 ---- else { FOR_ALL_BUFFERS(vimbuf) ! XPUSHs(sv_2mortal(newBUFrv(newSV(0), vimbuf))); } } else *************** *** 1564,1570 **** { vimbuf = buflist_findnr(b); if (vimbuf) ! XPUSHs(newBUFrv(newSV(0), vimbuf)); } } } --- 1589,1595 ---- { vimbuf = buflist_findnr(b); if (vimbuf) ! XPUSHs(sv_2mortal(newBUFrv(newSV(0), vimbuf))); } } } *************** *** 1584,1590 **** else { FOR_ALL_WINDOWS(vimwin) ! XPUSHs(newWINrv(newSV(0), vimwin)); } } else --- 1609,1615 ---- else { FOR_ALL_WINDOWS(vimwin) ! XPUSHs(sv_2mortal(newWINrv(newSV(0), vimwin))); } } else *************** *** 1594,1600 **** w = (int) SvIV(ST(i)); vimwin = win_find_nr(w); if (vimwin) ! XPUSHs(newWINrv(newSV(0), vimwin)); } } --- 1619,1625 ---- w = (int) SvIV(ST(i)); vimwin = win_find_nr(w); if (vimwin) ! XPUSHs(sv_2mortal(newWINrv(newSV(0), vimwin))); } } *** ../vim-8.1.0189/src/testdir/test_perl.vim 2017-03-18 19:45:55.000000000 +0100 --- src/testdir/test_perl.vim 2018-07-16 17:34:41.754473657 +0200 *************** *** 219,238 **** call assert_equal(['&VIM::Msg', 'STDOUT', 'STDERR'], split(l:out, "\n")) endfunc ! func Test_SvREFCNT() new t perl <<--perl my ($b, $w); ! $b = $curbuf for 0 .. 10; ! $w = $curwin for 0 .. 10; VIM::DoCommand('bw! t'); if (exists &Internals::SvREFCNT) { my $cb = Internals::SvREFCNT($$b); my $cw = Internals::SvREFCNT($$w); ! VIM::Eval("assert_equal(2, $cb)"); ! VIM::Eval("assert_equal(2, $cw)"); } VIM::Eval("assert_false($$b)"); VIM::Eval("assert_false($$w)"); --perl endfunc --- 219,260 ---- call assert_equal(['&VIM::Msg', 'STDOUT', 'STDERR'], split(l:out, "\n")) endfunc ! " Run first to get a clean namespace ! func Test_000_SvREFCNT() ! for i in range(10) ! exec 'new X'.i ! endfor new t perl <<--perl + #line 5 "Test_000_SvREFCNT()" my ($b, $w); ! ! $b = $curbuf for 0 .. 100; ! $w = $curwin for 0 .. 100; ! () = VIM::Buffers for 0 .. 100; ! () = VIM::Windows for 0 .. 100; ! VIM::DoCommand('bw! t'); if (exists &Internals::SvREFCNT) { my $cb = Internals::SvREFCNT($$b); my $cw = Internals::SvREFCNT($$w); ! VIM::Eval("assert_equal(2, $cb, 'T1')"); ! VIM::Eval("assert_equal(2, $cw, 'T2')"); ! foreach ( VIM::Buffers, VIM::Windows ) { ! my $c = Internals::SvREFCNT($_); ! VIM::Eval("assert_equal(2, $c, 'T3')"); ! $c = Internals::SvREFCNT($$_); ! # Why only one ref? ! # Look wrong but work. Maybe not portable... ! VIM::Eval("assert_equal(1, $c, 'T4')"); ! } ! $cb = Internals::SvREFCNT($$curbuf); ! $cw = Internals::SvREFCNT($$curwin); ! VIM::Eval("assert_equal(3, $cb, 'T5')"); ! VIM::Eval("assert_equal(3, $cw, 'T6')"); } VIM::Eval("assert_false($$b)"); VIM::Eval("assert_false($$w)"); --perl + %bw! endfunc *** ../vim-8.1.0189/src/version.c 2018-07-15 20:26:37.418459878 +0200 --- src/version.c 2018-07-16 17:37:41.017344049 +0200 *************** *** 791,792 **** --- 791,794 ---- { /* Add new patch number below this line */ + /**/ + 190, /**/ -- hundred-and-one symptoms of being an internet addict: 255. You work for a newspaper and your editor asks you to write an article about Internet addiction...in the "first person." /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///