From d61c34dd2e02d6c4d8d1397b079542222fe6ea7e Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Mon, 26 Jul 2021 09:43:13 +0000 Subject: 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. --- hv.c | 57 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/hv.c b/hv.c index cd962f6e34..4c47b6fcbe 100644 --- a/hv.c +++ b/hv.c @@ -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) -- cgit v1.2.1