summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2016-02-10 14:30:08 +1100
committerTony Cook <tony@develop-help.com>2016-02-10 14:30:44 +1100
commit958cdeac409681891afe77bf60db047296523465 (patch)
tree81526b189a59bea3f61e76d2497a838c3e174c26 /sv.c
parent7db8c4f1f19e6f855107ec990507a1a9cb0f59a6 (diff)
downloadperl-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.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/sv.c b/sv.c
index 1650ed5179..2b17a8622e 100644
--- a/sv.c
+++ b/sv.c
@@ -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