summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-11-28 18:04:01 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-11-29 09:11:31 -0800
commit4e52a9b69e39f85d6a5d7ac598c61ff0b00f94ee (patch)
tree0ad7b7828f9733b88b28a3fed6799beb1492f4af /scope.c
parent3d460042b1251a4b5e3b583fa6be358554dd3bcc (diff)
downloadperl-4e52a9b69e39f85d6a5d7ac598c61ff0b00f94ee.tar.gz
Clear method caches when unwinding local *foo=*method
It was already working for those cases where *foo contained a sub before and after localisation. For those cases where *foo had no sub but localised assignment gave it one, method caches were not being reset on scope exit. case SAVEt_GP in scope.c:leave_scope needs to look at both GPs (glob pointer, or list of glob slots), both from before and after the unlo- calisation. If either has a sub, method caches need to be cleared. This does not yet fix local *foo = sub {}, but I added a to-do test for it. (This is more complicated, as localisation happens in two seperate steps, the glob slot localisation storing no pointers to the glob itself on the savestack.)
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/scope.c b/scope.c
index 31b990dec5..f96aa45ad3 100644
--- a/scope.c
+++ b/scope.c
@@ -865,14 +865,18 @@ Perl_leave_scope(pTHX_ I32 base)
case SAVEt_GP: /* scalar reference */
ptr = SSPOPPTR;
gv = MUTABLE_GV(SSPOPPTR);
- gp_free(gv);
- GvGP_set(gv, (GP*)ptr);
- if ((hv=GvSTASH(gv)) && HvENAME_get(hv)) {
+ {
+ /* possibly taking a method out of circulation */
+ const bool had_method = !!GvCVu(gv);
+ gp_free(gv);
+ GvGP_set(gv, (GP*)ptr);
+ if ((hv=GvSTASH(gv)) && HvENAME_get(hv)) {
if (GvNAMELEN(gv) == 3 && strnEQ(GvNAME(gv), "ISA", 3))
mro_isa_changed_in(hv);
- else if (GvCVu(gv))
+ else if (had_method || GvCVu(gv))
/* putting a method back into circulation ("local")*/
gv_method_changed(gv);
+ }
}
SvREFCNT_dec(gv);
break;