summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
authorsyber <syber@crazypanda.ru>2014-08-28 01:05:41 +0400
committerDavid Mitchell <davem@iabyn.com>2014-09-02 12:20:32 +0100
commita3d47e0d2ac20034d8d96f777e886b55ab96dd0f (patch)
tree79799d457b9d0d506791e2703c9f38aee3883445 /scope.c
parentfa542f558f44c8c868faa064d630855ce315e339 (diff)
downloadperl-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.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/scope.c b/scope.c
index 66589abc5b..50036d0b78 100644
--- a/scope.c
+++ b/scope.c
@@ -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);
}