X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=08ca8d058e9863827175a65b1181c0fb01ade511;hb=4c8a458a2f2be4d98cd2b8873f15b800e9382262;hp=ee3a67eba69af9d5d47e2c23c32498e57a42173e;hpb=c3acb9e0760135dfd888c0ee1b415777d784aabc;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index ee3a67e..08ca8d0 100644 --- a/hv.c +++ b/hv.c @@ -179,7 +179,7 @@ Perl_he_dup(pTHX_ const HE *e, bool shared, CLONE_PARAMS* param) char *k; Newx(k, HEK_BASESIZE + sizeof(const SV *), char); HeKEY_hek(ret) = (HEK*)k; - HeKEY_sv(ret) = SvREFCNT_inc(sv_dup(HeKEY_sv(e), param)); + HeKEY_sv(ret) = sv_dup_inc(HeKEY_sv(e), param); } else if (shared) { /* This is hek_dup inlined, which seems to be important for speed @@ -202,7 +202,7 @@ Perl_he_dup(pTHX_ const HE *e, bool shared, CLONE_PARAMS* param) else HeKEY_hek(ret) = save_hek_flags(HeKEY(e), HeKLEN(e), HeHASH(e), HeKFLAGS(e)); - HeVAL(ret) = SvREFCNT_inc(sv_dup(HeVAL(e), param)); + HeVAL(ret) = sv_dup_inc(HeVAL(e), param); return ret; } #endif /* USE_ITHREADS */ @@ -817,8 +817,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, xhv->xhv_keys++; /* HvTOTALKEYS(hv)++ */ if (!counter) { /* initial entry? */ - xhv->xhv_fill++; /* HvFILL(hv)++ */ - } else if (xhv->xhv_keys > (IV)xhv->xhv_max) { + } else if (xhv->xhv_keys > xhv->xhv_max) { hsplit(hv); } else if(!HvREHASH(hv)) { U32 n_links = 1; @@ -887,7 +886,7 @@ Perl_hv_scalar(pTHX_ HV *hv) } sv = sv_newmortal(); - if (HvFILL((const HV *)hv)) + if (HvTOTALKEYS((const HV *)hv)) Perl_sv_setpvf(aTHX_ sv, "%ld/%ld", (long)HvFILL(hv), (long)HvMAX(hv) + 1); else @@ -1055,9 +1054,6 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, HvPLACEHOLDERS(hv)++; } else { *oentry = HeNEXT(entry); - if(!*first_entry) { - xhv->xhv_fill--; /* HvFILL(hv)-- */ - } if (SvOOK(hv) && entry == HvAUX(hv)->xhv_eiter /* HvEITER(hv) */) HvLAZYDEL_on(hv); else @@ -1156,8 +1152,6 @@ S_hsplit(pTHX_ HV *hv) if ((HeHASH(entry) & newsize) != (U32)i) { *oentry = HeNEXT(entry); HeNEXT(entry) = *bep; - if (!*bep) - xhv->xhv_fill++; /* HvFILL(hv)++ */ *bep = entry; right_length++; continue; @@ -1167,8 +1161,6 @@ S_hsplit(pTHX_ HV *hv) left_length++; } } - if (!*aep) /* everything moved */ - xhv->xhv_fill--; /* HvFILL(hv)-- */ /* I think we don't actually need to keep track of the longest length, merely flag if anything is too long. But for the moment while developing this code I'll track it. */ @@ -1204,7 +1196,6 @@ S_hsplit(pTHX_ HV *hv) was_shared = HvSHAREKEYS(hv); - xhv->xhv_fill = 0; HvSHAREKEYS_off(hv); HvREHASH_on(hv); @@ -1239,8 +1230,6 @@ S_hsplit(pTHX_ HV *hv) /* Copy oentry to the correct new chain. */ bep = ((HE**)a) + (hash & (I32) xhv->xhv_max); - if (!*bep) - xhv->xhv_fill++; /* HvFILL(hv)++ */ HeNEXT(entry) = *bep; *bep = entry; @@ -1317,7 +1306,7 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax) } xhv->xhv_max = --newsize; /* HvMAX(hv) = --newsize */ HvARRAY(hv) = (HE **) a; - if (!xhv->xhv_fill /* !HvFILL(hv) */) /* skip rest if no entries */ + if (!xhv->xhv_keys /* !HvTOTALKEYS(hv) */) /* skip rest if no entries */ return; aep = (HE**)a; @@ -1330,26 +1319,24 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax) if (j != i) { j -= i; *oentry = HeNEXT(entry); - if (!(HeNEXT(entry) = aep[j])) - xhv->xhv_fill++; /* HvFILL(hv)++ */ + HeNEXT(entry) = aep[j]; aep[j] = entry; continue; } else oentry = &HeNEXT(entry); } - if (!*aep) /* everything moved */ - xhv->xhv_fill--; /* HvFILL(hv)-- */ } } HV * Perl_newHVhv(pTHX_ HV *ohv) { + dVAR; HV * const hv = newHV(); - STRLEN hv_max, hv_fill; + STRLEN hv_max; - if (!ohv || (hv_fill = HvFILL(ohv)) == 0) + if (!ohv || !HvTOTALKEYS(ohv)) return hv; hv_max = HvMAX(ohv); @@ -1395,7 +1382,6 @@ Perl_newHVhv(pTHX_ HV *ohv) } HvMAX(hv) = hv_max; - HvFILL(hv) = hv_fill; HvTOTALKEYS(hv) = HvTOTALKEYS(ohv); HvARRAY(hv) = ents; } /* not magical */ @@ -1404,6 +1390,7 @@ Perl_newHVhv(pTHX_ HV *ohv) HE *entry; const I32 riter = HvRITER_get(ohv); HE * const eiter = HvEITER_get(ohv); + STRLEN hv_fill = HvFILL(ohv); /* Can we use fewer buckets? (hv_max is always 2^n-1) */ while (hv_max && hv_max + 1 >= hv_fill * 2) @@ -1430,10 +1417,10 @@ HV * Perl_hv_copy_hints_hv(pTHX_ HV *const ohv) { HV * const hv = newHV(); - STRLEN hv_fill; - if (ohv && (hv_fill = HvFILL(ohv))) { + if (ohv && HvTOTALKEYS(ohv)) { STRLEN hv_max = HvMAX(ohv); + STRLEN hv_fill = HvFILL(ohv); HE *entry; const I32 riter = HvRITER_get(ohv); HE * const eiter = HvEITER_get(ohv); @@ -1637,8 +1624,6 @@ S_clear_placeholders(pTHX_ HV *hv, U32 items) while ((entry = *oentry)) { if (HeVAL(entry) == &PL_sv_placeholder) { *oentry = HeNEXT(entry); - if (first && !*oentry) - HvFILL(hv)--; /* This linked list is now empty. */ if (entry == HvEITER_get(hv)) HvLAZYDEL_on(hv); else @@ -1781,7 +1766,6 @@ S_hfreeentries(pTHX_ HV *hv) /* make everyone else think the array is empty, so that the destructors * called for freed entries can't recusively mess with us */ HvARRAY(hv) = NULL; - HvFILL(hv) = 0; ((XPVHV*) SvANY(hv))->xhv_keys = 0; @@ -1875,6 +1859,38 @@ Perl_hv_undef(pTHX_ HV *hv) mg_clear(MUTABLE_SV(hv)); } +/* +=for apidoc hv_fill + +Returns the number of hash buckets that happen to be in use. This function is +wrapped by the macro C. + +Previously this value was stored in the HV structure, rather than being +calculated on demand. + +=cut +*/ + +STRLEN +Perl_hv_fill(pTHX_ HV const *const hv) +{ + STRLEN count = 0; + HE **ents = HvARRAY(hv); + + PERL_ARGS_ASSERT_HV_FILL; + + if (ents) { + HE *const *const last = ents + HvMAX(hv); + count = last + 1 - ents; + + do { + if (!*ents) + --count; + } while (++ents <= last); + } + return count; +} + static struct xpvhv_aux* S_hv_auxinit(HV *hv) { struct xpvhv_aux *iter; @@ -2149,8 +2165,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) HeSVKEY_set(entry, SvREFCNT_inc_simple_NN(key)); return entry; /* beware, hent_val is not set */ } - if (HeVAL(entry)) - SvREFCNT_dec(HeVAL(entry)); + SvREFCNT_dec(HeVAL(entry)); Safefree(HeKEY_hek(entry)); del_HE(entry); iter->xhv_eiter = NULL; /* HvEITER(hv) = NULL */ @@ -2427,21 +2442,17 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash) if (entry) { if (--entry->he_valu.hent_refcount == 0) { *oentry = HeNEXT(entry); - if (!*first) { - /* There are now no entries in our slot. */ - xhv->xhv_fill--; /* HvFILL(hv)-- */ - } Safefree(entry); xhv->xhv_keys--; /* HvTOTALKEYS(hv)-- */ } } - if (!entry && ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ packWARN(WARN_INTERNAL), - "Attempt to free non-existent shared string '%s'%s" - pTHX__FORMAT, - hek ? HEK_KEY(hek) : str, - ((k_flags & HVhek_UTF8) ? " (utf8)" : "") pTHX__VALUE); + if (!entry) + Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL), + "Attempt to free non-existent shared string '%s'%s" + pTHX__FORMAT, + hek ? HEK_KEY(hek) : str, + ((k_flags & HVhek_UTF8) ? " (utf8)" : "") pTHX__VALUE); if (k_flags & HVhek_FREEKEY) Safefree(str); } @@ -2550,8 +2561,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) xhv->xhv_keys++; /* HvTOTALKEYS(hv)++ */ if (!next) { /* initial entry? */ - xhv->xhv_fill++; /* HvFILL(hv)++ */ - } else if (xhv->xhv_keys > (IV)xhv->xhv_max /* HvKEYS(hv) > HvMAX(hv) */) { + } else if (xhv->xhv_keys > xhv->xhv_max /* HvKEYS(hv) > HvMAX(hv) */) { hsplit(PL_strtab); } } @@ -2732,10 +2742,6 @@ Perl_refcounted_he_chain_2hv(pTHX_ const struct refcounted_he *chain) /* Link it into the chain. */ HeNEXT(entry) = *oentry; - if (!HeNEXT(entry)) { - /* initial entry. */ - HvFILL(hv)++; - } *oentry = entry; HvTOTALKEYS(hv)++; @@ -2972,6 +2978,8 @@ Perl_refcounted_he_free(pTHX_ struct refcounted_he *he) { } } +/* pp_entereval is aware that labels are stored with a key ':' at the top of + the linked list. */ const char * Perl_fetch_cop_label(pTHX_ struct refcounted_he *const chain, STRLEN *len, U32 *flags) {