From 978a498e17ec54b6f1fc65f3375a62a68f321f99 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Wed, 28 Nov 2012 08:36:34 -0800 Subject: Reset method caches when GPs are shared MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new MRO stuff in 5.10 made PL_sub_generation++ mostly unnecessary, and almost all uses of it were replaced with mro_method_changed_in. There is only one problem: That doesn’t actually work properly. After glob-to-glob assignment (*foo = *bar), both globs share the same GP (glob pointer, or list of glob slots). But there is no list of GVs associated with any GP. So there is no way, given a GV whose GP is shared, to find out what other classes might need their method caches reset. sub B::b { "b" } *A::b = *B::b; @C::ISA = "A"; print C->b, "\n"; # should print "b" eval 'sub B::b { "c" }'; print C->b, "\n"; # should print "c" __END__ $ perl5.8.9 foo b c $ perl5.10.0 foo b b And it continues up to 5.16.x. If a GP is shared, then those places where mro_method_changed_in is called after the GP has been modified must do PL_sub_generation++ instead if the GP is shared, which can be detected through its refer- ence count. --- sv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sv.c') diff --git a/sv.c b/sv.c index a2d0cbc204..8570efb401 100644 --- a/sv.c +++ b/sv.c @@ -3823,7 +3823,7 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr) } GvCVGEN(dstr) = 0; /* Switch off cacheness. */ GvASSUMECV_on(dstr); - if(GvSTASH(dstr)) mro_method_changed_in(GvSTASH(dstr)); /* sub foo { 1 } sub bar { 2 } *bar = \&foo */ + if(GvSTASH(dstr)) gv_method_changed(dstr); /* sub foo { 1 } sub bar { 2 } *bar = \&foo */ } *location = SvREFCNT_inc_simple_NN(sref); if (import_flag && !(GvFLAGS(dstr) & import_flag) -- cgit v1.2.1