diff options
author | Tony Cook <tony@develop-help.com> | 2016-02-10 14:30:08 +1100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2016-02-10 14:30:44 +1100 |
commit | 958cdeac409681891afe77bf60db047296523465 (patch) | |
tree | 81526b189a59bea3f61e76d2497a838c3e174c26 /sv.c | |
parent | 7db8c4f1f19e6f855107ec990507a1a9cb0f59a6 (diff) | |
download | perl-958cdeac409681891afe77bf60db047296523465.tar.gz |
[perl #127494] don't cache AUTOLOAD as DESTROY
Otherwise S_curse() would need to do all the work gv_autoload_pvn()
already does to set up to call AUTOLOAD() (setting $AUTOLOAD etc.)
Instead, by not caching it, we ensure gv_autoload_pvn() is called
each time to perform the required setup.
This has a performance cost over adding that code to S_curse(), but the
cost of actually running the AUTOLOAD sub is likely to drown that out,
and is easily avoided by adding "sub DESTROY {}" to the module.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 37 |
1 files changed, 30 insertions, 7 deletions
@@ -125,6 +125,9 @@ # define ASSERT_UTF8_CACHE(cache) NOOP #endif +static const char S_destroy[] = "DESTROY"; +#define S_destroy_len (sizeof(S_destroy)-1) + /* ============================================================================ =head1 Allocation and deallocation of SVs. @@ -6791,13 +6794,33 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) { (void *)destructor, HvNAME(stash)) ); } else { - GV * const gv = - gv_fetchmethod_pvn_flags(stash, "DESTROY", 7, GV_AUTOLOAD); - if (gv) destructor = GvCV(gv); - meta->destroy_gen = PL_sub_generation; - meta->destroy = destructor; - DEBUG_o( Perl_deb(aTHX_ "Set cached DESTROY method %p for %s\n", - (void *)destructor, HvNAME(stash)) ); + bool autoload = FALSE; + GV *gv = + gv_fetchmeth_pvn(stash, S_destroy, S_destroy_len, -1, 0); + if (gv) + destructor = GvCV(gv); + if (!destructor) { + gv = gv_autoload_pvn(stash, S_destroy, S_destroy_len, + GV_AUTOLOAD_ISMETHOD); + if (gv) + destructor = GvCV(gv); + if (destructor) + autoload = TRUE; + } + /* we don't cache AUTOLOAD for DESTROY, since this code + would then need to set $__PACKAGE__::AUTOLOAD, or the + equivalent for XS AUTOLOADs */ + if (!autoload) { + meta->destroy_gen = PL_sub_generation; + meta->destroy = destructor; + + DEBUG_o( Perl_deb(aTHX_ "Set cached DESTROY method %p for %s\n", + (void *)destructor, HvNAME(stash)) ); + } + else { + DEBUG_o( Perl_deb(aTHX_ "Not caching AUTOLOAD for DESTROY method for %s\n", + HvNAME(stash)) ); + } } assert(!destructor || SvTYPE(destructor) == SVt_PVCV); if (destructor |