summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2021-07-26 09:43:13 +0000
committerNicholas Clark <nick@ccl4.org>2021-09-18 18:40:19 +0000
commitd61c34dd2e02d6c4d8d1397b079542222fe6ea7e (patch)
treefe8316836910e373ce0a88ebb421e64aa8a99688
parentd15612fefdeea3e8baf64a5409a5385b54db76b1 (diff)
downloadperl-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.c57
1 files 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)