diff options
author | syber <syber@crazypanda.ru> | 2014-08-28 01:05:41 +0400 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-09-02 12:20:32 +0100 |
commit | a3d47e0d2ac20034d8d96f777e886b55ab96dd0f (patch) | |
tree | 79799d457b9d0d506791e2703c9f38aee3883445 /scope.c | |
parent | fa542f558f44c8c868faa064d630855ce315e339 (diff) | |
download | perl-a3d47e0d2ac20034d8d96f777e886b55ab96dd0f.tar.gz |
avoid local *f = \&foo resetting the method cache
{
local *MyClass::func = sub {...}; # LINE A
...
} # LINE B
This example caused global method cache reset at both lines A and B
because glob_assign_ref and leave_scope thought that GV's GP refcnt was 2
(because of saving to Save Stack).
Issue has been fixed.
SAVEt_GVSLOT (on leave_scope) now requires refcnt > 2 to reset cache
globally). Additionally, glob_assign_ref when GvINTRO is set temporarily
decrements gp's refcnt by 1. This handles all common cases, however there
are still uncommon use cases when perl still resets cache globally, for
example:
{
local *MyClass::func = sub {...}; # OK
*MyClass::func = sub {...}; # OOPS :(
} # OK
or
{
local *MyClass::func = sub {...}; # OK
{
local *MyClass::func = sub {...}; # OOPS :(
} # OOPS :(
} # OK
* OOPS is a line where global cache reset occurs
* OK - one package cache reset
Diffstat (limited to 'scope.c')
-rw-r--r-- | scope.c | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -846,7 +846,7 @@ Perl_leave_scope(pTHX_ I32 base) { if ((char *)svp < (char *)GvGP(ARG2_GV) || (char *)svp > (char *)GvGP(ARG2_GV) + sizeof(struct gp) - || GvREFCNT(ARG2_GV) > 1) + || GvREFCNT(ARG2_GV) > 2) /* "> 2" to ignore savestack's ref */ PL_sub_generation++; else mro_method_changed_in(hv); } |