In perl.git, the branch yves/hv_h_split has been updated <http://perl5.git.perl.org/perl.git/commitdiff/a0ba399bd37fba040ebbc38d1c847d7f215c891a?hp=157df282bcc1926b9b40c77a97fff630df25f3b3>
- Log ----------------------------------------------------------------- commit a0ba399bd37fba040ebbc38d1c847d7f215c891a Author: Yves Orton <[email protected]> Date: Fri Feb 22 21:18:04 2013 +0100 Only realloc in hv_auxinit if we arent SvOOK already. Once we set SvOOK we should not need to realloc again. M hv.c commit 9efe2e8ad6aa060aea83b4608c1a3da5f43715e8 Author: Yves Orton <[email protected]> Date: Fri Feb 22 21:17:03 2013 +0100 make sure we set HvRAND whenever we set HvARRAY Defines HvARRAY_set(hv, array) which sets both properly. M hv.c M hv.h ----------------------------------------------------------------------- Summary of changes: hv.c | 57 ++++++++++++++++++++++++++++----------------------------- hv.h | 6 ++++++ 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/hv.c b/hv.c index 1dfaa1c..dd96be9 100644 --- a/hv.c +++ b/hv.c @@ -577,7 +577,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, Newxz(array, PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */), char); - HvARRAY(hv) = (HE**)array; + HvARRAY_set(hv,array); } #ifdef DYNAMIC_ENV_FETCH else if (action & HV_FETCH_ISEXISTS) { @@ -765,7 +765,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, Newxz(array, PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */), char); - HvARRAY(hv) = (HE**)array; + HvARRAY_set(hv,array); } oentry = &(HvARRAY(hv))[hash & (I32) xhv->xhv_max]; @@ -792,9 +792,6 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, * We rotate the HvRAND(hv) each time we use it, so that each * insert potentially gets a different result. */ - if (!HvRAND(hv)) { - HvRAND(hv)= ptr_hash((PTRV)HvARRAY(hv)); - } if (!*oentry || HvRAND(hv) & 1) { HeNEXT(entry) = *oentry; *oentry = entry; @@ -1146,17 +1143,20 @@ S_hsplit(pTHX_ HV *hv, STRLEN const oldsize, STRLEN newsize) PL_nomemok = FALSE; Zero(&a[oldsize * sizeof(HE*)], (newsize-oldsize) * sizeof(HE*), char); /* zero 2nd half*/ HvMAX(hv) = --newsize; - HvARRAY(hv) = (HE**) a; - - if (!HvTOTALKEYS(hv)) /* skip rest if no entries */ - return; - + HvARRAY_set(hv, a); /* the idea of this is that we create a "random" value by hashing the address of * the array, we then use the low bit to decide if we insert at the top, or insert * second from top. After each such insert we rotate the hashed value. So we can * use the same hashed value over and over, and in normal build environments use - * very few ops to do so. ROTL32() should produce a single machine operation. */ - HvRAND(hv)= bucket_rand= ptr_hash((PTRV)a); + * very few ops to do so. ROTL32() should produce a single machine operation. + * + * See definition of HvARRAY_set(); + * + */ + bucket_rand= HvRAND(hv); + + if (!HvTOTALKEYS(hv)) /* skip rest if no entries */ + return; aep = (HE**)a; do { @@ -1214,7 +1214,7 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax) } else { Newxz(a, PERL_HV_ARRAY_ALLOC_BYTES(newsize), char); xhv->xhv_max = --newsize; - HvARRAY(hv) = (HE **) a; + HvARRAY_set(hv,a); } } @@ -1272,7 +1272,7 @@ Perl_newHVhv(pTHX_ HV *ohv) HvMAX(hv) = hv_max; HvTOTALKEYS(hv) = HvTOTALKEYS(ohv); - HvARRAY(hv) = ents; + HvARRAY_set(hv,ents); } /* not magical */ else { /* Iterate over ohv, copying keys and values one at a time. */ @@ -1742,7 +1742,8 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags) if (!SvOOK(hv)) { Safefree(HvARRAY(hv)); xhv->xhv_max = 7; /* HvMAX(hv) = 7 (it's a normal hash) */ - HvARRAY(hv) = 0; + HvARRAY(hv) = NULL; + HvRAND(hv) = 0; } /* if we're freeing the HV, the SvMAGIC field has been reused for * other purposes, and so there can't be any placeholder magic */ @@ -1827,20 +1828,18 @@ S_hv_auxinit(HV *hv) { PERL_ARGS_ASSERT_HV_AUXINIT; - if (!HvARRAY(hv)) { - Newxz(array, PERL_HV_ARRAY_ALLOC_BYTES(HvMAX(hv) + 1) - + sizeof(struct xpvhv_aux), char); - } else { - array = (char *) HvARRAY(hv); - Renew(array, PERL_HV_ARRAY_ALLOC_BYTES(HvMAX(hv) + 1) - + sizeof(struct xpvhv_aux), char); - } - if (!HvRAND(hv)) { - HvRAND(hv)= ptr_hash((PTRV)array); + if (!SvOOK(hv)) { + if (!HvARRAY(hv)) { + Newxz(array, PERL_HV_ARRAY_ALLOC_BYTES(HvMAX(hv) + 1) + + sizeof(struct xpvhv_aux), char); + } else { + array = (char *) HvARRAY(hv); + Renew(array, PERL_HV_ARRAY_ALLOC_BYTES(HvMAX(hv) + 1) + + sizeof(struct xpvhv_aux), char); + } + HvARRAY_set(hv, array); + SvOOK_on(hv); } - - HvARRAY(hv) = (HE**) array; - SvOOK_on(hv); iter = HvAUX(hv); iter->xhv_riter = -1; /* HvRITER(hv) = -1 */ @@ -2834,7 +2833,7 @@ Perl_refcounted_he_chain_2hv(pTHX_ const struct refcounted_he *chain, U32 flags) if (!HvARRAY(hv)) { char *array; Newxz(array, PERL_HV_ARRAY_ALLOC_BYTES(max + 1), char); - HvARRAY(hv) = (HE**)array; + HvARRAY_set(hv, array); } placeholders = 0; diff --git a/hv.h b/hv.h index ebd6ca5..ff3a02d 100644 --- a/hv.h +++ b/hv.h @@ -216,6 +216,12 @@ C<SV*>. #define HvFILL(hv) Perl_hv_fill(aTHX_ (const HV *)(hv)) #define HvMAX(hv) ((XPVHV*) SvANY(hv))->xhv_max #define HvRAND(hv) ((XPVHV*) SvANY(hv))->xhv_rand + +#define HvARRAY_set(hv,a) STMT_START { \ + HvARRAY(hv)= (HE **)a; \ + HvRAND(hv)= ptr_hash((PTRV)a); \ +} STMT_END + /* This quite intentionally does no flag checking first. That's your responsibility. */ #define HvAUX(hv) ((struct xpvhv_aux*)&(HvARRAY(hv)[HvMAX(hv)+1])) -- Perl5 Master Repository
