This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
TODO tests for avoid needless use of UTF8=1 format [RT#56336]
[perl5.git] / hv.c
diff --git a/hv.c b/hv.c
index 244feb6..d29c49c 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -40,24 +40,6 @@ holds the key and hash value.
 static const char S_strtab_error[]
     = "Cannot modify shared string table in hv_%s";
 
-STATIC void
-S_more_he(pTHX)
-{
-    dVAR;
-    /* We could generate this at compile time via (another) auxiliary C
-       program?  */
-    const size_t arena_size = Perl_malloc_good_size(PERL_ARENA_SIZE);
-    HE* he = (HE*) Perl_get_arena(aTHX_ arena_size, HE_SVSLOT);
-    HE * const heend = &he[arena_size / sizeof(HE) - 1];
-
-    PL_body_roots[HE_SVSLOT] = he;
-    while (he < heend) {
-       HeNEXT(he) = (HE*)(he + 1);
-       he++;
-    }
-    HeNEXT(he) = 0;
-}
-
 #ifdef PURIFY
 
 #define new_HE() (HE*)safemalloc(sizeof(HE))
@@ -73,7 +55,7 @@ S_new_he(pTHX)
     void ** const root = &PL_body_roots[HE_SVSLOT];
 
     if (!*root)
-       S_more_he(aTHX);
+       Perl_more_bodies(aTHX_ HE_SVSLOT, sizeof(HE), PERL_ARENA_SIZE);
     he = (HE*) *root;
     assert(he);
     *root = HeNEXT(he);
@@ -179,7 +161,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 +184,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,7 +799,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
 
        xhv->xhv_keys++; /* HvTOTALKEYS(hv)++ */
        if (!counter) {                         /* initial entry? */
-       } 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;
@@ -1085,7 +1067,6 @@ S_hsplit(pTHX_ HV *hv)
     register I32 i;
     char *a = (char*) HvARRAY(hv);
     register HE **aep;
-    register HE **oentry;
     int longest_chain = 0;
     int was_shared;
 
@@ -1142,25 +1123,26 @@ S_hsplit(pTHX_ HV *hv)
     for (i=0; i<oldsize; i++,aep++) {
        int left_length = 0;
        int right_length = 0;
-       register HE *entry;
+       HE **oentry = aep;
+       HE *entry = *aep;
        register HE **bep;
 
-       if (!*aep)                              /* non-existent */
+       if (!entry)                             /* non-existent */
            continue;
        bep = aep+oldsize;
-       for (oentry = aep, entry = *aep; entry; entry = *oentry) {
+       do {
            if ((HeHASH(entry) & newsize) != (U32)i) {
                *oentry = HeNEXT(entry);
                HeNEXT(entry) = *bep;
                *bep = entry;
                right_length++;
-               continue;
            }
            else {
                oentry = &HeNEXT(entry);
                left_length++;
            }
-       }
+           entry = *oentry;
+       } while (entry);
        /* 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.  */
@@ -1250,8 +1232,6 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
     register I32 i;
     register char *a;
     register HE **aep;
-    register HE *entry;
-    register HE **oentry;
 
     PERL_ARGS_ASSERT_HV_KSPLIT;
 
@@ -1311,9 +1291,12 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
 
     aep = (HE**)a;
     for (i=0; i<oldsize; i++,aep++) {
-       if (!*aep)                              /* non-existent */
+       HE **oentry = aep;
+       HE *entry = *aep;
+
+       if (!entry)                             /* non-existent */
            continue;
-       for (oentry = aep, entry = *aep; entry; entry = *oentry) {
+       do {
            register I32 j = (HeHASH(entry) & newsize);
 
            if (j != i) {
@@ -1321,11 +1304,11 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
                *oentry = HeNEXT(entry);
                HeNEXT(entry) = aep[j];
                aep[j] = entry;
-               continue;
            }
            else
                oentry = &HeNEXT(entry);
-       }
+           entry = *oentry;
+       } while (entry);
     }
 }
 
@@ -1457,8 +1440,8 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry)
     if (!entry)
        return;
     val = HeVAL(entry);
-    if (HvNAME(hv) && anonymise_cv(HvNAME_HEK(hv), val) && GvCVu(val))
-       mro_method_changed_in(hv);
+    if (val && isGV(val) && isGV_with_GP(val) && GvCVu(val) && HvNAME_get(hv))
+        mro_method_changed_in(hv);     /* deletion of method from stash */
     SvREFCNT_dec(val);
     if (HeKLEN(entry) == HEf_SVKEY) {
        SvREFCNT_dec(HeKEY_sv(entry));
@@ -1471,33 +1454,6 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry)
     del_HE(entry);
 }
 
-static I32
-S_anonymise_cv(pTHX_ HEK *stash, SV *val)
-{
-    CV *cv;
-
-    PERL_ARGS_ASSERT_ANONYMISE_CV;
-
-    if (val && isGV(val) && isGV_with_GP(val) && (cv = GvCV(val))) {
-       if ((SV *)CvGV(cv) == val) {
-           GV *anongv;
-
-           if (stash) {
-               SV *gvname = newSVhek(stash);
-               sv_catpvs(gvname, "::__ANON__");
-               anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
-               SvREFCNT_dec(gvname);
-           } else {
-               anongv = gv_fetchpvs("__ANON__::__ANON__", GV_ADDMULTI,
-                                    SVt_PVCV);
-           }
-           CvGV(cv) = anongv;
-           CvANON_on(cv);
-           return 1;
-       }
-    }
-    return 0;
-}
 
 void
 Perl_hv_delayfree_ent(pTHX_ HV *hv, register HE *entry)
@@ -1661,22 +1617,6 @@ S_hfreeentries(pTHX_ HV *hv)
     if (!orig_array)
        return;
 
-    if (HvNAME(hv) && orig_array != NULL) {
-       /* symbol table: make all the contained subs ANON */
-       STRLEN i;
-       XPVHV *xhv = (XPVHV*)SvANY(hv);
-
-       for (i = 0; i <= xhv->xhv_max; i++) {
-           HE *entry = (HvARRAY(hv))[i];
-           for (; entry; entry = HeNEXT(entry)) {
-               SV *val = HeVAL(entry);
-               /* we need to put the subs in the __ANON__ symtable, as
-                * this one is being cleared. */
-               anonymise_cv(NULL, val);
-           }
-       }
-    }
-
     if (SvOOK(hv)) {
        /* If the hash is actually a symbol table with a name, look after the
           name.  */
@@ -1708,25 +1648,43 @@ S_hfreeentries(pTHX_ HV *hv)
            HE *entry;
             struct mro_meta *meta;
            struct xpvhv_aux *iter = HvAUX(hv);
-           /* If there are weak references to this HV, we need to avoid
-              freeing them up here.  In particular we need to keep the AV
-              visible as what we're deleting might well have weak references
-              back to this HV, so the for loop below may well trigger
-              the removal of backreferences from this array.  */
+           /* weak references: if called from sv_clear(), the backrefs
+            * should already have been killed; if there are any left, its
+            * because we're doing hv_clear() or hv_undef(), and the HV
+            * will continue to live.
+            * Because while freeing the entries we fake up a NULL HvARRAY
+            * (and hence HvAUX), we need to store the backref array
+            * somewhere else; but it still needs to be visible in case
+            * any the things we free happen to call sv_del_backref().
+            * We do this by storing it in magic instead.
+            * If, during the entry freeing, a destructor happens to add
+            * a new weak backref, then sv_add_backref will look in both
+            * places (magic in HvAUX) for the AV, but will create a new
+            * AV in HvAUX if it can't find one (if it finds it in magic,
+            * it moves it back into HvAUX. So at the end of the iteration
+            * we have to allow for this. */
+
 
            if (iter->xhv_backreferences) {
-               /* So donate them to regular backref magic to keep them safe.
-                  The sv_magic will increase the reference count of the AV,
-                  so we need to drop it first. */
-               SvREFCNT_dec(iter->xhv_backreferences);
-               if (AvFILLp(iter->xhv_backreferences) == -1) {
-                   /* Turns out that the array is empty. Just free it.  */
+               if (SvTYPE(iter->xhv_backreferences) == SVt_PVAV) {
+                   /* The sv_magic will increase the reference count of the AV,
+                      so we need to drop it first. */
                    SvREFCNT_dec(iter->xhv_backreferences);
+                   if (AvFILLp(iter->xhv_backreferences) == -1) {
+                       /* Turns out that the array is empty. Just free it.  */
+                       SvREFCNT_dec(iter->xhv_backreferences);
 
-               } else {
-                   sv_magic(MUTABLE_SV(hv),
-                            MUTABLE_SV(iter->xhv_backreferences),
-                            PERL_MAGIC_backref, NULL, 0);
+                   } else {
+                       sv_magic(MUTABLE_SV(hv),
+                                MUTABLE_SV(iter->xhv_backreferences),
+                                PERL_MAGIC_backref, NULL, 0);
+                   }
+               }
+               else {
+                   MAGIC *mg;
+                   sv_magic(MUTABLE_SV(hv), NULL, PERL_MAGIC_backref, NULL, 0);
+                   mg = mg_find(MUTABLE_SV(hv), PERL_MAGIC_backref);
+                   mg->mg_obj = (SV*)iter->xhv_backreferences;
                }
                iter->xhv_backreferences = NULL;
            }
@@ -1764,7 +1722,7 @@ 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 */
+        * called for freed entries can't recursively mess with us */
        HvARRAY(hv) = NULL;
        ((XPVHV*) SvANY(hv))->xhv_keys = 0;
 
@@ -1880,12 +1838,13 @@ Perl_hv_fill(pTHX_ HV const *const hv)
     PERL_ARGS_ASSERT_HV_FILL;
 
     if (ents) {
-       HE *const *const end = ents + HvMAX(hv);
+       HE *const *const last = ents + HvMAX(hv);
+       count = last + 1 - ents;
 
        do {
-           if (*ents)
-               ++count;
-       } while (++ents <= end);
+           if (!*ents)
+               --count;
+       } while (++ents <= last);
     }
     return count;
 }
@@ -2080,7 +2039,8 @@ Perl_hv_kill_backrefs(pTHX_ HV *hv) {
     if (av) {
        HvAUX(hv)->xhv_backreferences = 0;
        Perl_sv_kill_backrefs(aTHX_ MUTABLE_SV(hv), av);
-       SvREFCNT_dec(av);
+       if (SvTYPE(av) == SVt_PVAV)
+           SvREFCNT_dec(av);
     }
 }
 
@@ -2560,7 +2520,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? */
-       } 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);
        }
     }