X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=71009c9e20d44095bce676fff4ddbb9d88830890;hb=44a8e56aa037ed0f03f0506f6f85f5ed290c78e1;hp=065012302b5df5df45f9d25cabc87bd415ebcb2c;hpb=36477c247f3c188fb8cc7e276c87b739d3e6ab7c;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index 0650123..71009c9 100644 --- a/hv.c +++ b/hv.c @@ -168,20 +168,20 @@ register U32 hash; return 0; if (SvRMAGICAL(hv) && mg_find((SV*)hv,'P')) { - char *k; - HEK *hek; + static HE mh; - New(54, k, HEK_BASESIZE + sizeof(SV*), char); - hek = (HEK*)k; sv = sv_newmortal(); keysv = sv_2mortal(newSVsv(keysv)); mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY); - entry = &He; - HeVAL(entry) = sv; - HeKEY_hek(entry) = hek; - HeSVKEY_set(entry, keysv); - HeKLEN(entry) = HEf_SVKEY; /* hent_key is holding an SV* */ - return entry; + if (!HeKEY_hek(&mh)) { + char *k; + New(54, k, HEK_BASESIZE + sizeof(SV*), char); + HeKEY_hek(&mh) = (HEK*)k; + HeKLEN(&mh) = HEf_SVKEY; /* key will always hold an SV* */ + } + HeSVKEY_set(&mh, keysv); + HeVAL(&mh) = sv; + return &mh; } xhv = (XPVHV*)SvANY(hv); @@ -248,14 +248,14 @@ register U32 hash; xhv = (XPVHV*)SvANY(hv); if (SvMAGICAL(hv)) { mg_copy((SV*)hv, val, key, klen); -#ifndef OVERLOAD - if (!xhv->xhv_array) - return 0; -#else - if (!xhv->xhv_array && (SvMAGIC(hv)->mg_type != 'A' - || SvMAGIC(hv)->mg_moremagic)) - return 0; + if (!xhv->xhv_array + && (SvMAGIC(hv)->mg_moremagic + || (SvMAGIC(hv)->mg_type != 'E' +#ifdef OVERLOAD + && SvMAGIC(hv)->mg_type != 'A' #endif /* OVERLOAD */ + ))) + return 0; } if (!hash) PERL_HASH(hash, key, klen); @@ -318,14 +318,14 @@ register U32 hash; if (SvMAGICAL(hv)) { keysv = sv_2mortal(newSVsv(keysv)); mg_copy((SV*)hv, val, (char*)keysv, HEf_SVKEY); -#ifndef OVERLOAD - if (!xhv->xhv_array) - return Nullhe; -#else - if (!xhv->xhv_array && (SvMAGIC(hv)->mg_type != 'A' - || SvMAGIC(hv)->mg_moremagic)) - return Nullhe; + if (!xhv->xhv_array + && (SvMAGIC(hv)->mg_moremagic + || (SvMAGIC(hv)->mg_type != 'E' +#ifdef OVERLOAD + && SvMAGIC(hv)->mg_type != 'A' #endif /* OVERLOAD */ + ))) + return Nullhe; } key = SvPV(keysv, klen); @@ -423,7 +423,7 @@ I32 flags; if (entry == xhv->xhv_eiter) HvLAZYDEL_on(hv); else - he_free(entry, HvSHAREKEYS(hv)); + he_free(hv, entry); --xhv->xhv_keys; return sv; } @@ -485,7 +485,7 @@ U32 hash; if (entry == xhv->xhv_eiter) HvLAZYDEL_on(hv); else - he_free(entry, HvSHAREKEYS(hv)); + he_free(hv, entry); --xhv->xhv_keys; return sv; } @@ -746,17 +746,20 @@ newHV() } void -he_free(hent, shared) +he_free(hv, hent) +HV *hv; register HE *hent; -I32 shared; { if (!hent) return; + if (isGV(HeVAL(hent)) && GvCVu(HeVAL(hent)) && HvNAME(hv)) + sub_generation++; /* may be deletion of method from stash */ SvREFCNT_dec(HeVAL(hent)); if (HeKLEN(hent) == HEf_SVKEY) { SvREFCNT_dec(HeKEY_sv(hent)); Safefree(HeKEY_hek(hent)); - } else if (shared) + } + else if (HvSHAREKEYS(hv)) unshare_hek(HeKEY_hek(hent)); else Safefree(HeKEY_hek(hent)); @@ -764,17 +767,20 @@ I32 shared; } void -he_delayfree(hent, shared) +he_delayfree(hv, hent) +HV *hv; register HE *hent; -I32 shared; { if (!hent) return; + if (isGV(HeVAL(hent)) && GvCVu(HeVAL(hent)) && HvNAME(hv)) + sub_generation++; /* may be deletion of method from stash */ sv_2mortal(HeVAL(hent)); /* free between statements */ if (HeKLEN(hent) == HEf_SVKEY) { sv_2mortal(HeKEY_sv(hent)); Safefree(HeKEY_hek(hent)); - } else if (shared) + } + else if (HvSHAREKEYS(hv)) unshare_hek(HeKEY_hek(hent)); else Safefree(HeKEY_hek(hent)); @@ -808,7 +814,6 @@ HV *hv; register HE *ohent = Null(HE*); I32 riter; I32 max; - I32 shared; if (!hv) return; @@ -819,12 +824,11 @@ HV *hv; max = HvMAX(hv); array = HvARRAY(hv); hent = array[0]; - shared = HvSHAREKEYS(hv); for (;;) { if (hent) { ohent = hent; hent = HeNEXT(hent); - he_free(ohent, shared); + he_free(hv, ohent); } if (!hent) { if (++riter > max) @@ -869,7 +873,7 @@ HV *hv; #endif if (entry && HvLAZYDEL(hv)) { /* was deleted earlier? */ HvLAZYDEL_off(hv); - he_free(entry, HvSHAREKEYS(hv)); + he_free(hv, entry); } xhv->xhv_riter = -1; xhv->xhv_eiter = Null(HE*); @@ -936,7 +940,7 @@ HV *hv; if (oldentry && HvLAZYDEL(hv)) { /* was deleted earlier? */ HvLAZYDEL_off(hv); - he_free(oldentry, HvSHAREKEYS(hv)); + he_free(hv, oldentry); } xhv->xhv_eiter = entry;