diff options
author | Nicholas Clark <nick@ccl4.org> | 2021-07-26 09:43:13 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2021-09-18 18:40:19 +0000 |
commit | d61c34dd2e02d6c4d8d1397b079542222fe6ea7e (patch) | |
tree | fe8316836910e373ce0a88ebb421e64aa8a99688 | |
parent | d15612fefdeea3e8baf64a5409a5385b54db76b1 (diff) | |
download | perl-d61c34dd2e02d6c4d8d1397b079542222fe6ea7e.tar.gz |
Move all the code that deletes the hash entry into one place
Move the code that removed the entry from the hash ahead of all the code
that post-processes that entry to update method caches.
The entry is now completely deleted from the hash before any needed MRO
related logic is triggered, and the code that is specific to the chosen hash
table implementation is now untangled from the MRO code.
-rw-r--r-- | hv.c | 57 |
1 files changed, 29 insertions, 28 deletions
@@ -1259,6 +1259,35 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, " a restricted hash"); } + /* + * If a restricted hash, rather than really deleting the entry, put + * a placeholder there. This marks the key as being "approved", so + * we can still access via not-really-existing key without raising + * an error. + */ + 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); + } + else { + if (SvOOK(hv) && HvLAZYDEL(hv) && + entry == HeNEXT(HvAUX(hv)->xhv_eiter)) + HeNEXT(HvAUX(hv)->xhv_eiter) = HeNEXT(entry); + hv_free_ent(hv, entry); + } + xhv->xhv_keys--; /* HvTOTALKEYS(hv)-- */ + if (xhv->xhv_keys == 0) + HvHASKFLAGS_off(hv); + } + /* If this is a stash and the key ends with ::, then someone is * deleting a package. */ @@ -1355,34 +1384,6 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, if (k_flags & HVhek_FREEKEY) Safefree(key); - /* - * If a restricted hash, rather than really deleting the entry, put - * a placeholder there. This marks the key as being "approved", so - * we can still access via not-really-existing key without raising - * an error. - */ - 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); - else { - if (SvOOK(hv) && HvLAZYDEL(hv) && - entry == HeNEXT(HvAUX(hv)->xhv_eiter)) - HeNEXT(HvAUX(hv)->xhv_eiter) = HeNEXT(entry); - hv_free_ent(hv, entry); - } - xhv->xhv_keys--; /* HvTOTALKEYS(hv)-- */ - if (xhv->xhv_keys == 0) - HvHASKFLAGS_off(hv); - } - if (sv) { /* deletion of method from stash */ if (isGV(sv) && isGV_with_GP(sv) && GvCVu(sv) |