[perl #36037] Perl 5.8.7-RC1 build problems on LynxOS
[p5sagit/p5-mst-13.2.git] / hv.c
diff --git a/hv.c b/hv.c
index e14f7ab..21e7ac3 100644 (file)
--- 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;
@@ -797,6 +828,7 @@ S_hv_magic_check(pTHX_ HV *hv, bool *needs_copy, bool *needs_store)
            case PERL_MAGIC_tied:
            case PERL_MAGIC_sig:
                *needs_store = FALSE;
+               return; /* We've set all there is to set. */
            }
        }
        mg = mg->mg_moremagic;
@@ -1348,7 +1380,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 +1628,8 @@ S_hfreeentries(pTHX_ HV *hv)
            HvLAZYDEL_off(hv);
            hv_free_ent(hv, entry);
        }
+       if (iter->xhv_name)
+           unshare_hek_or_pvn(iter->xhv_name, 0, 0, 0);
        Safefree(iter);
        ((XPVHV*) SvANY(hv))->xhv_aux = 0;
     }
@@ -1621,9 +1655,8 @@ Perl_hv_undef(pTHX_ HV *hv)
     hfreeentries(hv);
     Safefree(HvARRAY(hv));
     if ((name = HvNAME_get(hv))) {
-       /* FIXME - strlen HvNAME  */
         if(PL_stashcache)
-           hv_delete(PL_stashcache, name, strlen(name), G_DISCARD);
+           hv_delete(PL_stashcache, name, HvNAMELEN_get(hv), G_DISCARD);
        Perl_hv_name_set(aTHX_ hv, 0, 0, 0);
     }
     xhv->xhv_max   = 7;        /* HvMAX(hv) = 7 (it's a normal hash) */
@@ -1635,7 +1668,7 @@ Perl_hv_undef(pTHX_ HV *hv)
 }
 
 struct xpvhv_aux*
-S_hv_auxinit(aTHX) {
+S_hv_auxinit(pTHX) {
     struct xpvhv_aux *iter;
 
     New(0, iter, 1, struct xpvhv_aux);
@@ -1755,30 +1788,24 @@ Perl_hv_eiter_set(pTHX_ HV *hv, HE *eiter) {
     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)
+Perl_hv_name_set(pTHX_ HV *hv, const char *name, I32 len, int flags)
 {
     struct xpvhv_aux *iter = ((XPVHV *)SvANY(hv))->xhv_aux;
+    U32 hash;
 
-    if (!iter) {
+    if (iter) {
+       if (iter->xhv_name) {
+           unshare_hek_or_pvn(iter->xhv_name, 0, 0, 0);
+       }
+    } else {
        if (name == 0)
            return;
 
        ((XPVHV *)SvANY(hv))->xhv_aux = iter = S_hv_auxinit(aTHX);
     }
-    iter->xhv_name = savepvn(name, len);
+    PERL_HASH(hash, name, len);
+    iter->xhv_name = name ? share_hek(name, len, hash) : 0;
 }
 
 /*
@@ -2203,10 +2230,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 +2287,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 *