X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=5086b83a92f9c04cea0bdf5bd40c740caf10a2e5;hb=c4a9c09d5b30a93b6241aff3c9915e33e4e41eeb;hp=2996a8e88b79bcddf15ba5818f800092ca76e172;hpb=5f52a9a9d70e7135bcdcd2ce1817c062e8272518;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index 2996a8e..5086b83 100644 --- a/hv.c +++ b/hv.c @@ -123,6 +123,23 @@ Perl_free_tied_hv_pool(pTHX) } #if defined(USE_ITHREADS) +HEK * +Perl_hek_dup(pTHX_ HEK *source, CLONE_PARAMS* param) +{ + HE *shared = (HE*)ptr_table_fetch(PL_shared_hek_table, source); + + if (shared) { + /* We already shared this hash key. */ + ++HeVAL(shared); + } + else { + shared = share_hek_flags(HEK_KEY(source), HEK_LEN(source), + HEK_HASH(source), HEK_FLAGS(source)); + ptr_table_store(PL_shared_hek_table, source, shared); + } + return HeKEY_hek(shared); +} + HE * Perl_he_dup(pTHX_ HE *e, bool shared, CLONE_PARAMS* param) { @@ -146,9 +163,23 @@ Perl_he_dup(pTHX_ HE *e, bool shared, CLONE_PARAMS* param) HeKEY_hek(ret) = (HEK*)k; HeKEY_sv(ret) = SvREFCNT_inc(sv_dup(HeKEY_sv(e), param)); } - else if (shared) - HeKEY_hek(ret) = share_hek_flags(HeKEY(e), HeKLEN(e), HeHASH(e), - HeKFLAGS(e)); + else if (shared) { + /* This is hek_dup inlined, which seems to be important for speed + reasons. */ + HEK *source = HeKEY_hek(e); + HE *shared = (HE*)ptr_table_fetch(PL_shared_hek_table, source); + + if (shared) { + /* We already shared this hash key. */ + ++HeVAL(shared); + } + else { + shared = share_hek_flags(HEK_KEY(source), HEK_LEN(source), + HEK_HASH(source), HEK_FLAGS(source)); + ptr_table_store(PL_shared_hek_table, source, shared); + } + HeKEY_hek(ret) = HeKEY_hek(shared); + } else HeKEY_hek(ret) = save_hek_flags(HeKEY(e), HeKLEN(e), HeHASH(e), HeKFLAGS(e)); @@ -652,8 +683,8 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, /* Need to swap the key we have for a key with the flags we need. As keys are shared we can't just write to the flag, so we share the new one, unshare the old one. */ - HEK *new_hek = share_hek_flags(key, klen, hash, - masked_flags); + HEK *new_hek = HeKEY_hek(share_hek_flags(key, klen, hash, + masked_flags)); unshare_hek (HeKEY_hek(entry)); HeKEY_hek(entry) = new_hek; } @@ -755,7 +786,7 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, /* share_hek_flags will do the free for us. This might be considered bad API design. */ if (HvSHAREKEYS(hv)) - HeKEY_hek(entry) = share_hek_flags(key, klen, hash, flags); + HeKEY_hek(entry) = HeKEY_hek(share_hek_flags(key, klen, hash, flags)); else /* gotta do the real thing */ HeKEY_hek(entry) = save_hek_flags(key, klen, hash, flags); HeVAL(entry) = val; @@ -1348,7 +1379,7 @@ Perl_newHVhv(pTHX_ HV *ohv) ent = new_HE(); HeVAL(ent) = newSVsv(HeVAL(oent)); HeKEY_hek(ent) - = shared ? share_hek_flags(key, len, hash, flags) + = shared ? HeKEY_hek(share_hek_flags(key, len, hash, flags)) : save_hek_flags(key, len, hash, flags); if (prev) HeNEXT(prev) = ent; @@ -1596,6 +1627,7 @@ S_hfreeentries(pTHX_ HV *hv) HvLAZYDEL_off(hv); hv_free_ent(hv, entry); } + Safefree(iter->xhv_name); Safefree(iter); ((XPVHV*) SvANY(hv))->xhv_aux = 0; } @@ -1772,7 +1804,9 @@ Perl_hv_name_set(pTHX_ HV *hv, const char *name, STRLEN len, int flags) { struct xpvhv_aux *iter = ((XPVHV *)SvANY(hv))->xhv_aux; - if (!iter) { + if (iter) { + Safefree(iter->xhv_name); + } else { if (name == 0) return; @@ -2203,10 +2237,10 @@ Perl_share_hek(pTHX_ const char *str, I32 len, register U32 hash) flags |= HVhek_WASUTF8 | HVhek_FREEKEY; } - return share_hek_flags (str, len, hash, flags); + return HeKEY_hek(share_hek_flags (str, len, hash, flags)); } -STATIC HEK * +STATIC HE * S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) { register XPVHV* xhv; @@ -2260,7 +2294,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) if (flags & HVhek_FREEKEY) Safefree(str); - return HeKEY_hek(entry); + return entry; } I32 *