diff options
author | Nicholas Clark <nick@ccl4.org> | 2021-07-25 20:12:25 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2021-09-18 18:40:19 +0000 |
commit | 73ace1cb5078023d3dca765f0f10329b8606fc05 (patch) | |
tree | 603228c3caeafb05a20e7fd743d05617c1230123 /hv.c | |
parent | 6a3871b339dd83437e4d00d00f6fd5e3e4069cec (diff) | |
download | perl-73ace1cb5078023d3dca765f0f10329b8606fc05.tar.gz |
Call mro_method_changed_in() later in hv_delete_common()
Move the call as late as possible - just before the deleted hash key is
freed if G_DISCARD is set. In particular, move it *after* the HE is
freed.
Move the code that sets HeVAL() to &PL_sv_placeholder into the if block that
handles restricted hashes - no need to set this on normal hashes, as the
structure is about to be freed anyway.
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 19 |
1 files changed, 11 insertions, 8 deletions
@@ -1354,13 +1354,6 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, Safefree(key); sv = d_flags & G_DISCARD ? HeVAL(entry) : sv_2mortal(HeVAL(entry)); - HeVAL(entry) = &PL_sv_placeholder; - if (sv) { - /* deletion of method from stash */ - if (isGV(sv) && isGV_with_GP(sv) && GvCVu(sv) - && HvENAME_get(hv)) - mro_method_changed_in(hv); - } /* * If a restricted hash, rather than really deleting the entry, put @@ -1368,11 +1361,14 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, * we can still access via not-really-existing key without raising * an error. */ - if (SvREADONLY(hv)) + if (SvREADONLY(hv)) { /* We'll be saving this slot, so the number of allocated keys * doesn't go down, but the number placeholders goes up */ + HeVAL(entry) = &PL_sv_placeholder; HvPLACEHOLDERS(hv)++; + } else { + HeVAL(entry) = NULL; *oentry = HeNEXT(entry); if (SvOOK(hv) && entry == HvAUX(hv)->xhv_eiter /* HvEITER(hv) */) HvLAZYDEL_on(hv); @@ -1387,6 +1383,13 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, HvHASKFLAGS_off(hv); } + if (sv) { + /* deletion of method from stash */ + if (isGV(sv) && isGV_with_GP(sv) && GvCVu(sv) + && HvENAME_get(hv)) + mro_method_changed_in(hv); + } + if (d_flags & G_DISCARD) { SvREFCNT_dec(sv); sv = NULL; |