This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
avoid local *f = \&foo resetting the method cache
authorsyber <syber@crazypanda.ru>
Wed, 27 Aug 2014 21:05:41 +0000 (01:05 +0400)
committerDavid Mitchell <davem@iabyn.com>
Tue, 2 Sep 2014 11:20:32 +0000 (12:20 +0100)
commita3d47e0d2ac20034d8d96f777e886b55ab96dd0f
tree79799d457b9d0d506791e2703c9f38aee3883445
parentfa542f558f44c8c868faa064d630855ce315e339
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
scope.c
sv.c