diff options
author | Nicholas Clark <nick@ccl4.org> | 2021-07-24 16:20:56 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2021-07-26 07:06:00 +0000 |
commit | c23e25b4e677ccabda2bc164083171818f764db0 (patch) | |
tree | c43ae37d25b547e3eebd27dfef9ea99fb4fe7be0 /hv.c | |
parent | f1c1602aa05e6e31a961fec177e6d315ca1db236 (diff) | |
download | perl-c23e25b4e677ccabda2bc164083171818f764db0.tar.gz |
S_clear_placeholders() should call HvHASKFLAGS_off() if no keys remain.
This isn't essential - HvHASKFLAGS() set when there are no keys with flags
merely disables some potential optimisations. (The other way round - not
being set when keys have flags would be a bug).
This is a regression I introduced in Feb 2004 with commit d36773897a6f30fc:
hv_clear_placeholders now manipulates the linked lists directly, rather
than using the iterator interface and calling hv_delete
This will allow hv_delete to be simplified to remove most of the
special casing related to placeholders.
However several people have looked at the code since then and no-one has
realised that with the logic as-was, this call had to be unreachable.
Also avoid calling HvPLACEHOLDERS_get() twice - each caller has already
done this, so pass the value in.
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 15 |
1 files changed, 6 insertions, 9 deletions
@@ -1882,14 +1882,14 @@ Perl_hv_clear_placeholders(pTHX_ HV *hv) } static void -S_clear_placeholders(pTHX_ HV *hv, U32 items) +S_clear_placeholders(pTHX_ HV *hv, const U32 placeholders) { I32 i; + U32 to_find = placeholders; PERL_ARGS_ASSERT_CLEAR_PLACEHOLDERS; - if (items == 0) - return; + assert(to_find); i = HvMAX(hv); do { @@ -1909,12 +1909,10 @@ S_clear_placeholders(pTHX_ HV *hv, U32 items) hv_free_ent(hv, entry); } - if (--items == 0) { + if (--to_find == 0) { /* Finished. */ - I32 placeholders = HvPLACEHOLDERS_get(hv); HvTOTALKEYS(hv) -= (IV)placeholders; - /* HvUSEDKEYS expanded */ - if ((HvTOTALKEYS(hv) - placeholders) == 0) + if (HvTOTALKEYS(hv) == 0) HvHASKFLAGS_off(hv); HvPLACEHOLDERS_set(hv, 0); return; @@ -1925,7 +1923,7 @@ S_clear_placeholders(pTHX_ HV *hv, U32 items) } } while (--i >= 0); /* You can't get here, hence assertion should always fail. */ - assert (items == 0); + assert (to_find == 0); NOT_REACHED; /* NOTREACHED */ } @@ -3343,7 +3341,6 @@ Perl_refcounted_he_chain_2hv(pTHX_ const struct refcounted_he *chain, U32 flags) if (placeholders) { clear_placeholders(hv, placeholders); - HvTOTALKEYS(hv) -= placeholders; } /* We could check in the loop to see if we encounter any keys with key |