X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=e14f7abb2f715b6768c0f9dfcd6dd55555ec7814;hb=a560f29b68cee2c6b71ff8f85b84ebab612b34b0;hp=3f100e60a011675e3c0757664dc43ed8614f366c;hpb=8d2f45362e368d7dd455b476c924dcbcc02d845b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index 3f100e6..e14f7ab 100644 --- a/hv.c +++ b/hv.c @@ -542,7 +542,7 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, } TAINT_IF(save_taint); - if (!xhv->xhv_array /* !HvARRAY(hv) */ && !needs_store) { + if (!HvARRAY(hv) && !needs_store) { if (flags & HVhek_FREEKEY) Safefree(key); return Nullhe; @@ -568,15 +568,15 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, } /* ISSTORE */ } /* SvMAGICAL */ - if (!xhv->xhv_array /* !HvARRAY(hv) */) { + if (!HvARRAY(hv)) { if ((action & (HV_FETCH_LVALUE | HV_FETCH_ISSTORE)) #ifdef DYNAMIC_ENV_FETCH /* if it's an %ENV lookup, we may get it on the fly */ || (SvRMAGICAL((SV*)hv) && mg_find((SV*)hv, PERL_MAGIC_env)) #endif ) - Newz(503, xhv->xhv_array /* HvARRAY(hv) */, + Newz(503, HvARRAY(hv), PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */), - char); + HE*); #ifdef DYNAMIC_ENV_FETCH else if (action & HV_FETCH_ISEXISTS) { /* for an %ENV exists, if we do an insert it's by a recursive @@ -626,12 +626,11 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, n_links = 0; #ifdef DYNAMIC_ENV_FETCH - if (!xhv->xhv_array /* !HvARRAY(hv) */) entry = Null(HE*); + if (!HvARRAY(hv)) entry = Null(HE*); else #endif { - /* entry = (HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */ - entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; + entry = (HvARRAY(hv))[hash & (I32) HvMAX(hv)]; } for (; entry; ++n_links, entry = HeNEXT(entry)) { if (HeHASH(entry) != hash) /* strings can't be equal */ @@ -680,11 +679,11 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, } /* LVAL fetch which actaully needs a store. */ val = NEWSV(61,0); - xhv->xhv_placeholders--; + HvPLACEHOLDERS(hv)--; } else { /* store */ if (val != &PL_sv_placeholder) - xhv->xhv_placeholders--; + HvPLACEHOLDERS(hv)--; } HeVAL(entry) = val; } else if (action & HV_FETCH_ISSTORE) { @@ -741,16 +740,16 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, /* Welcome to hv_store... */ - if (!xhv->xhv_array) { + if (!HvARRAY(hv)) { /* Not sure if we can get here. I think the only case of oentry being NULL is for %ENV with dynamic env fetch. But that should disappear with magic in the previous code. */ - Newz(503, xhv->xhv_array /* HvARRAY(hv) */, + Newz(503, HvARRAY(hv), PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */), - char); + HE*); } - oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; + oentry = &(HvARRAY(hv))[hash & (I32) xhv->xhv_max]; entry = new_HE(); /* share_hek_flags will do the free for us. This might be considered @@ -764,7 +763,7 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, *oentry = entry; if (val == &PL_sv_placeholder) - xhv->xhv_placeholders++; + HvPLACEHOLDERS(hv)++; if (masked_flags & HVhek_ENABLEHVKFLAGS) HvHASKFLAGS_on(hv); @@ -941,7 +940,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, } } xhv = (XPVHV*)SvANY(hv); - if (!xhv->xhv_array /* !HvARRAY(hv) */) + if (!HvARRAY(hv)) return Nullsv; if (is_utf8) { @@ -975,8 +974,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, masked_flags = (k_flags & HVhek_MASK); - /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */ - oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; + oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; entry = *oentry; i = 1; for (; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) { @@ -1022,12 +1020,13 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, HeVAL(entry) = &PL_sv_placeholder; /* We'll be saving this slot, so the number of allocated keys * doesn't go down, but the number placeholders goes up */ - xhv->xhv_placeholders++; /* HvPLACEHOLDERS(hv)++ */ + HvPLACEHOLDERS(hv)++; } else { *oentry = HeNEXT(entry); if (i && !*oentry) xhv->xhv_fill--; /* HvFILL(hv)-- */ - if (entry == xhv->xhv_eiter /* HvEITER(hv) */) + if (xhv->xhv_aux && entry + == ((struct xpvhv_aux *)xhv->xhv_aux)->xhv_eiter /* HvEITER(hv) */) HvLAZYDEL_on(hv); else hv_free_ent(hv, entry); @@ -1055,7 +1054,7 @@ S_hsplit(pTHX_ HV *hv) const I32 oldsize = (I32) xhv->xhv_max+1; /* HvMAX(hv)+1 (sick) */ register I32 newsize = oldsize * 2; register I32 i; - register char *a = xhv->xhv_array; /* HvARRAY(hv) */ + char *a = (char*) HvARRAY(hv); register HE **aep; register HE **oentry; int longest_chain = 0; @@ -1085,19 +1084,19 @@ S_hsplit(pTHX_ HV *hv) PL_nomemok = FALSE; return; } - Copy(xhv->xhv_array /* HvARRAY(hv) */, a, oldsize * sizeof(HE*), char); + Copy(HvARRAY(hv), a, oldsize * sizeof(HE*), char); if (oldsize >= 64) { - offer_nice_chunk(xhv->xhv_array /* HvARRAY(hv) */, + offer_nice_chunk(HvARRAY(hv), PERL_HV_ARRAY_ALLOC_BYTES(oldsize)); } else - Safefree(xhv->xhv_array /* HvARRAY(hv) */); + Safefree(HvARRAY(hv)); #endif PL_nomemok = FALSE; Zero(&a[oldsize * sizeof(HE*)], (newsize-oldsize) * sizeof(HE*), char); /* zero 2nd half*/ xhv->xhv_max = --newsize; /* HvMAX(hv) = --newsize */ - xhv->xhv_array = a; /* HvARRAY(hv) = a */ + HvARRAY(hv) = (HE**) a; aep = (HE**)a; for (i=0; ixhv_array; + aep = HvARRAY(hv); for (i=0; ixhv_array); - xhv->xhv_array = a; /* HvARRAY(hv) = a */ + Safefree (HvARRAY(hv)); + HvARRAY(hv) = (HE **)a; } void @@ -1226,7 +1225,7 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax) if (newsize < newmax) return; /* overflow detection */ - a = xhv->xhv_array; /* HvARRAY(hv) */ + a = (char *) HvARRAY(hv); if (a) { PL_nomemok = TRUE; #if defined(STRANGE_MALLOC) || defined(MYMALLOC) @@ -1241,13 +1240,13 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax) PL_nomemok = FALSE; return; } - Copy(xhv->xhv_array /* HvARRAY(hv) */, a, oldsize * sizeof(HE*), char); + Copy(HvARRAY(hv), a, oldsize * sizeof(HE*), char); if (oldsize >= 64) { - offer_nice_chunk(xhv->xhv_array /* HvARRAY(hv) */, + offer_nice_chunk(HvARRAY(hv), PERL_HV_ARRAY_ALLOC_BYTES(oldsize)); } else - Safefree(xhv->xhv_array /* HvARRAY(hv) */); + Safefree(HvARRAY(hv)); #endif PL_nomemok = FALSE; Zero(&a[oldsize * sizeof(HE*)], (newsize-oldsize) * sizeof(HE*), char); /* zero 2nd half*/ @@ -1256,7 +1255,7 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax) Newz(0, a, PERL_HV_ARRAY_ALLOC_BYTES(newsize), char); } xhv->xhv_max = --newsize; /* HvMAX(hv) = --newsize */ - xhv->xhv_array = a; /* HvARRAY(hv) = a */ + HvARRAY(hv) = (HE **) a; if (!xhv->xhv_fill /* !HvFILL(hv) */) /* skip rest if no entries */ return; @@ -1307,7 +1306,7 @@ Perl_newHV(pTHX) xhv->xhv_max = 7; /* HvMAX(hv) = 7 (start with 8 buckets) */ xhv->xhv_fill = 0; /* HvFILL(hv) = 0 */ - (void)hv_iterinit(hv); /* so each() will start off right */ + xhv->xhv_aux = 0; return hv; } @@ -1368,8 +1367,8 @@ Perl_newHVhv(pTHX_ HV *ohv) else { /* Iterate over ohv, copying keys and values one at a time. */ HE *entry; - const I32 riter = HvRITER(ohv); - HE * const eiter = HvEITER(ohv); + const I32 riter = HvRITER_get(ohv); + HE * const eiter = HvEITER_get(ohv); /* Can we use fewer buckets? (hv_max is always 2^n-1) */ while (hv_max && hv_max + 1 >= hv_fill * 2) @@ -1382,8 +1381,8 @@ Perl_newHVhv(pTHX_ HV *ohv) newSVsv(HeVAL(entry)), HeHASH(entry), HeKFLAGS(entry)); } - HvRITER(ohv) = riter; - HvEITER(ohv) = eiter; + HvRITER_set(ohv, riter); + HvEITER_set(ohv, eiter); } return hv; @@ -1397,7 +1396,7 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry) if (!entry) return; val = HeVAL(entry); - if (val && isGV(val) && GvCVu(val) && HvNAME(hv)) + if (val && isGV(val) && GvCVu(val) && HvNAME_get(hv)) PL_sub_generation++; /* may be deletion of method from stash */ SvREFCNT_dec(val); if (HeKLEN(entry) == HEf_SVKEY) { @@ -1416,7 +1415,7 @@ Perl_hv_delayfree_ent(pTHX_ HV *hv, register HE *entry) { if (!entry) return; - if (isGV(HeVAL(entry)) && GvCVu(HeVAL(entry)) && HvNAME(hv)) + if (isGV(HeVAL(entry)) && GvCVu(HeVAL(entry)) && HvNAME_get(hv)) PL_sub_generation++; /* may be deletion of method from stash */ sv_2mortal(HeVAL(entry)); /* free between statements */ if (HeKLEN(entry) == HEf_SVKEY) { @@ -1450,11 +1449,11 @@ Perl_hv_clear(pTHX_ HV *hv) xhv = (XPVHV*)SvANY(hv); - if (SvREADONLY(hv) && xhv->xhv_array != NULL) { + if (SvREADONLY(hv) && HvARRAY(hv) != NULL) { /* restricted hash: convert all keys to placeholders */ I32 i; for (i = 0; i <= (I32) xhv->xhv_max; i++) { - HE *entry = ((HE**)xhv->xhv_array)[i]; + HE *entry = (HvARRAY(hv))[i]; for (; entry; entry = HeNEXT(entry)) { /* not already placeholder */ if (HeVAL(entry) != &PL_sv_placeholder) { @@ -1466,7 +1465,7 @@ Perl_hv_clear(pTHX_ HV *hv) } SvREFCNT_dec(HeVAL(entry)); HeVAL(entry) = &PL_sv_placeholder; - xhv->xhv_placeholders++; /* HvPLACEHOLDERS(hv)++ */ + HvPLACEHOLDERS(hv)++; } } } @@ -1474,9 +1473,9 @@ Perl_hv_clear(pTHX_ HV *hv) } hfreeentries(hv); - xhv->xhv_placeholders = 0; /* HvPLACEHOLDERS(hv) = 0 */ - if (xhv->xhv_array /* HvARRAY(hv) */) - (void)memzero(xhv->xhv_array /* HvARRAY(hv) */, + HvPLACEHOLDERS_set(hv, 0); + if (HvARRAY(hv)) + (void)memzero(HvARRAY(hv), (xhv->xhv_max+1 /* HvMAX(hv)+1 */) * sizeof(HE*)); if (SvRMAGICAL(hv)) @@ -1485,7 +1484,9 @@ Perl_hv_clear(pTHX_ HV *hv) HvHASKFLAGS_off(hv); HvREHASH_off(hv); reset: - HvEITER(hv) = NULL; + if (xhv->xhv_aux) { + HvEITER_set(hv, NULL); + } } /* @@ -1526,7 +1527,7 @@ Perl_hv_clear_placeholders(pTHX_ HV *hv) *oentry = HeNEXT(entry); if (first && !*oentry) HvFILL(hv)--; /* This linked list is now empty. */ - if (HvEITER(hv)) + if (HvEITER_get(hv)) HvLAZYDEL_on(hv); else hv_free_ent(hv, entry); @@ -1557,6 +1558,7 @@ S_hfreeentries(pTHX_ HV *hv) register HE *entry; I32 riter; I32 max; + struct xpvhv_aux *iter; if (!hv) return; @@ -1586,7 +1588,17 @@ S_hfreeentries(pTHX_ HV *hv) } } HvARRAY(hv) = array; - (void)hv_iterinit(hv); + + iter = ((XPVHV*) SvANY(hv))->xhv_aux; + if (iter) { + entry = iter->xhv_eiter; /* HvEITER(hv) */ + if (entry && HvLAZYDEL(hv)) { /* was deleted earlier? */ + HvLAZYDEL_off(hv); + hv_free_ent(hv, entry); + } + Safefree(iter); + ((XPVHV*) SvANY(hv))->xhv_aux = 0; + } } /* @@ -1601,26 +1613,40 @@ void Perl_hv_undef(pTHX_ HV *hv) { register XPVHV* xhv; + const char *name; if (!hv) return; DEBUG_A(Perl_hv_assert(aTHX_ hv)); xhv = (XPVHV*)SvANY(hv); hfreeentries(hv); - Safefree(xhv->xhv_array /* HvARRAY(hv) */); - if (HvNAME(hv)) { + Safefree(HvARRAY(hv)); + if ((name = HvNAME_get(hv))) { + /* FIXME - strlen HvNAME */ if(PL_stashcache) - hv_delete(PL_stashcache, HvNAME(hv), strlen(HvNAME(hv)), G_DISCARD); - Safefree(HvNAME(hv)); - HvNAME(hv) = 0; + hv_delete(PL_stashcache, name, strlen(name), G_DISCARD); + Perl_hv_name_set(aTHX_ hv, 0, 0, 0); } xhv->xhv_max = 7; /* HvMAX(hv) = 7 (it's a normal hash) */ - xhv->xhv_array = 0; /* HvARRAY(hv) = 0 */ - xhv->xhv_placeholders = 0; /* HvPLACEHOLDERS(hv) = 0 */ + HvARRAY(hv) = 0; + HvPLACEHOLDERS_set(hv, 0); if (SvRMAGICAL(hv)) mg_clear((SV*)hv); } +struct xpvhv_aux* +S_hv_auxinit(aTHX) { + struct xpvhv_aux *iter; + + New(0, iter, 1, struct xpvhv_aux); + + iter->xhv_riter = -1; /* HvRITER(hv) = -1 */ + iter->xhv_eiter = Null(HE*); /* HvEITER(hv) = Null(HE*) */ + iter->xhv_name = 0; + + return iter; +} + /* =for apidoc hv_iterinit @@ -1641,20 +1667,120 @@ Perl_hv_iterinit(pTHX_ HV *hv) { register XPVHV* xhv; HE *entry; + struct xpvhv_aux *iter; if (!hv) Perl_croak(aTHX_ "Bad hash"); xhv = (XPVHV*)SvANY(hv); - entry = xhv->xhv_eiter; /* HvEITER(hv) */ - if (entry && HvLAZYDEL(hv)) { /* was deleted earlier? */ - HvLAZYDEL_off(hv); - hv_free_ent(hv, entry); + + iter = xhv->xhv_aux; + if (iter) { + entry = iter->xhv_eiter; /* HvEITER(hv) */ + if (entry && HvLAZYDEL(hv)) { /* was deleted earlier? */ + HvLAZYDEL_off(hv); + hv_free_ent(hv, entry); + } + iter->xhv_riter = -1; /* HvRITER(hv) = -1 */ + iter->xhv_eiter = Null(HE*); /* HvEITER(hv) = Null(HE*) */ + } else { + xhv->xhv_aux = S_hv_auxinit(aTHX); } - xhv->xhv_riter = -1; /* HvRITER(hv) = -1 */ - xhv->xhv_eiter = Null(HE*); /* HvEITER(hv) = Null(HE*) */ + /* used to be xhv->xhv_fill before 5.004_65 */ return XHvTOTALKEYS(xhv); } + +I32 * +Perl_hv_riter_p(pTHX_ HV *hv) { + struct xpvhv_aux *iter; + + if (!hv) + Perl_croak(aTHX_ "Bad hash"); + + iter = ((XPVHV *)SvANY(hv))->xhv_aux; + if (!iter) { + ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX); + } + return &(iter->xhv_riter); +} + +HE ** +Perl_hv_eiter_p(pTHX_ HV *hv) { + struct xpvhv_aux *iter; + + if (!hv) + Perl_croak(aTHX_ "Bad hash"); + + iter = ((XPVHV *)SvANY(hv))->xhv_aux; + if (!iter) { + ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX); + } + return &(iter->xhv_eiter); +} + +void +Perl_hv_riter_set(pTHX_ HV *hv, I32 riter) { + struct xpvhv_aux *iter; + + if (!hv) + Perl_croak(aTHX_ "Bad hash"); + + + iter = ((XPVHV *)SvANY(hv))->xhv_aux; + if (!iter) { + if (riter == -1) + return; + + ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX); + } + iter->xhv_riter = riter; +} + +void +Perl_hv_eiter_set(pTHX_ HV *hv, HE *eiter) { + struct xpvhv_aux *iter; + + if (!hv) + Perl_croak(aTHX_ "Bad hash"); + + iter = ((XPVHV *)SvANY(hv))->xhv_aux; + if (!iter) { + /* 0 is the default so don't go malloc()ing a new structure just to + hold 0. */ + if (!eiter) + return; + + ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX); + } + iter->xhv_eiter = eiter; +} + + +char ** +Perl_hv_name_p(pTHX_ HV *hv) +{ + struct xpvhv_aux *iter = ((XPVHV *)SvANY(hv))->xhv_aux; + + if (!iter) { + ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX); + } + return &(iter->xhv_name); +} + +void +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 (name == 0) + return; + + ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX); + } + iter->xhv_name = savepvn(name, len); +} + /* =for apidoc hv_iternext @@ -1700,11 +1826,22 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) register HE *entry; HE *oldentry; MAGIC* mg; + struct xpvhv_aux *iter; if (!hv) Perl_croak(aTHX_ "Bad hash"); xhv = (XPVHV*)SvANY(hv); - oldentry = entry = xhv->xhv_eiter; /* HvEITER(hv) */ + iter = xhv->xhv_aux; + + if (!iter) { + /* Too many things (well, pp_each at least) merrily assume that you can + call iv_iternext without calling hv_iterinit, so we'll have to deal + with it. */ + hv_iterinit(hv); + iter = ((XPVHV *)SvANY(hv))->xhv_aux; + } + + oldentry = entry = iter->xhv_eiter; /* HvEITER(hv) */ if ((mg = SvTIED_mg((SV*)hv, PERL_MAGIC_tied))) { SV *key = sv_newmortal(); @@ -1717,7 +1854,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) HEK *hek; /* one HE per MAGICAL hash */ - xhv->xhv_eiter = entry = new_HE(); /* HvEITER(hv) = new_HE() */ + iter->xhv_eiter = entry = new_HE(); /* HvEITER(hv) = new_HE() */ Zero(entry, 1, HE); Newz(54, k, HEK_BASESIZE + sizeof(SV*), char); hek = (HEK*)k; @@ -1734,7 +1871,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) SvREFCNT_dec(HeVAL(entry)); Safefree(HeKEY_hek(entry)); del_HE(entry); - xhv->xhv_eiter = Null(HE*); /* HvEITER(hv) = Null(HE*) */ + iter->xhv_eiter = Null(HE*); /* HvEITER(hv) = Null(HE*) */ return Null(HE*); } #ifdef DYNAMIC_ENV_FETCH /* set up %ENV for iteration */ @@ -1742,10 +1879,13 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) prime_env_iter(); #endif - if (!xhv->xhv_array /* !HvARRAY(hv) */) - Newz(506, xhv->xhv_array /* HvARRAY(hv) */, + if (!HvARRAY(hv)) { + char *darray; + Newz(506, darray, PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */), char); + HvARRAY(hv) = (HE**) darray; + } /* At start of hash, entry is NULL. */ if (entry) { @@ -1763,14 +1903,13 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) while (!entry) { /* OK. Come to the end of the current list. Grab the next one. */ - xhv->xhv_riter++; /* HvRITER(hv)++ */ - if (xhv->xhv_riter > (I32)xhv->xhv_max /* HvRITER(hv) > HvMAX(hv) */) { + iter->xhv_riter++; /* HvRITER(hv)++ */ + if (iter->xhv_riter > (I32)xhv->xhv_max /* HvRITER(hv) > HvMAX(hv) */) { /* There is no next one. End of the hash. */ - xhv->xhv_riter = -1; /* HvRITER(hv) = -1 */ + iter->xhv_riter = -1; /* HvRITER(hv) = -1 */ break; } - /* entry = (HvARRAY(hv))[HvRITER(hv)]; */ - entry = ((HE**)xhv->xhv_array)[xhv->xhv_riter]; + entry = (HvARRAY(hv))[iter->xhv_riter]; if (!(flags & HV_ITERNEXT_WANTPLACEHOLDERS)) { /* If we have an entry, but it's a placeholder, don't count it. @@ -1791,7 +1930,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) /*if (HvREHASH(hv) && entry && !HeKREHASH(entry)) PerlIO_printf(PerlIO_stderr(), "Awooga %p %p\n", hv, entry);*/ - xhv->xhv_eiter = entry; /* HvEITER(hv) = entry */ + iter->xhv_eiter = entry; /* HvEITER(hv) = entry */ return entry; } @@ -1990,8 +2129,7 @@ S_unshare_hek_or_pvn(pTHX_ HEK *hek, const char *str, I32 len, U32 hash) xhv = (XPVHV*)SvANY(PL_strtab); /* assert(xhv_array != 0) */ LOCK_STRTAB_MUTEX; - /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */ - oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; + oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)]; if (hek) { for (entry = *oentry; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) { if (HeKEY_hek(entry) != hek) @@ -2089,8 +2227,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) xhv = (XPVHV*)SvANY(PL_strtab); /* assert(xhv_array != 0) */ LOCK_STRTAB_MUTEX; - /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */ - oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; + oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)]; for (entry = *oentry; entry; i=0, entry = HeNEXT(entry)) { if (HeHASH(entry) != hash) /* strings can't be equal */ continue; @@ -2126,6 +2263,46 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) return HeKEY_hek(entry); } +I32 * +Perl_hv_placeholders_p(pTHX_ HV *hv) +{ + dVAR; + MAGIC *mg = mg_find((SV*)hv, PERL_MAGIC_rhash); + + if (!mg) { + mg = sv_magicext((SV*)hv, 0, PERL_MAGIC_rhash, 0, 0, 0); + + if (!mg) { + Perl_die(aTHX_ "panic: hv_placeholders_p"); + } + } + return &(mg->mg_len); +} + + +I32 +Perl_hv_placeholders_get(pTHX_ HV *hv) +{ + dVAR; + MAGIC *mg = mg_find((SV*)hv, PERL_MAGIC_rhash); + + return mg ? mg->mg_len : 0; +} + +void +Perl_hv_placeholders_set(pTHX_ HV *hv, I32 ph) +{ + dVAR; + MAGIC *mg = mg_find((SV*)hv, PERL_MAGIC_rhash); + + if (mg) { + mg->mg_len = ph; + } else if (ph) { + if (!sv_magicext((SV*)hv, 0, PERL_MAGIC_rhash, 0, 0, ph)) + Perl_die(aTHX_ "panic: hv_placeholders_set"); + } + /* else we don't need to add magic to record 0 placeholders. */ +} /* =for apidoc hv_assert @@ -2144,8 +2321,8 @@ Perl_hv_assert(pTHX_ HV *hv) int placeholders = 0; int real = 0; int bad = 0; - const I32 riter = HvRITER(hv); - HE *eiter = HvEITER(hv); + const I32 riter = HvRITER_get(hv); + HE *eiter = HvEITER_get(hv); (void)hv_iterinit(hv); @@ -2193,8 +2370,8 @@ Perl_hv_assert(pTHX_ HV *hv) if (bad) { sv_dump((SV *)hv); } - HvRITER(hv) = riter; /* Restore hash iterator state */ - HvEITER(hv) = eiter; + HvRITER_set(hv, riter); /* Restore hash iterator state */ + HvEITER_set(hv, eiter); } /*