Use a union for storing the shared hash key reference count, rather
Nicholas Clark [Mon, 30 Jan 2006 12:59:12 +0000 (12:59 +0000)]
than messy pointer hacks.

p4raw-id: //depot/perl@27000

ext/XS/APItest/APItest.xs
hv.c
hv.h
perl.c

index c2a6478..c8391c6 100644 (file)
@@ -86,7 +86,7 @@ test_freeent(freeent_function *f) {
 
     test_scalar = newSV(0);
     SvREFCNT_inc(test_scalar);
-    victim->hent_val = test_scalar;
+    HeVAL(victim) = test_scalar;
 
     /* Need this little game else we free the temps on the return stack.  */
     results[0] = SvREFCNT(test_scalar);
diff --git a/hv.c b/hv.c
index c458f56..0ab2558 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -2279,8 +2279,8 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash)
        assert (he->shared_he_he.hent_hek == hek);
 
        LOCK_STRTAB_MUTEX;
-       if (he->shared_he_he.hent_val - 1) {
-           --he->shared_he_he.hent_val;
+       if (he->shared_he_he.he_valu.hent_refcount - 1) {
+           --he->shared_he_he.he_valu.hent_refcount;
            UNLOCK_STRTAB_MUTEX;
            return;
        }
@@ -2299,7 +2299,7 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash)
             k_flags |= HVhek_WASUTF8 | HVhek_FREEKEY;
     }
 
-    /* what follows is the moral equivalent of:
+    /* what follows was the moral equivalent of:
     if ((Svp = hv_fetch(PL_strtab, tmpsv, FALSE, hash))) {
        if (--*Svp == Nullsv)
            hv_delete(PL_strtab, str, len, G_DISCARD, hash);
@@ -2333,7 +2333,7 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash)
     }
 
     if (found) {
-        if (--HeVAL(entry) == Nullsv) {
+        if (--he->shared_he_he.he_valu.hent_refcount == 0) {
             *oentry = HeNEXT(entry);
             if (!*first) {
                /* There are now no entries in our slot.  */
@@ -2449,7 +2449,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags)
        /* Still "point" to the HEK, so that other code need not know what
           we're up to.  */
        HeKEY_hek(entry) = hek;
-       HeVAL(entry) = Nullsv;
+       entry->he_valu.hent_refcount = 0;
        HeNEXT(entry) = next;
        *head = entry;
 
@@ -2461,7 +2461,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags)
        }
     }
 
-    ++HeVAL(entry);                            /* use value slot as REFCNT */
+    ++entry->he_valu.hent_refcount;
     UNLOCK_STRTAB_MUTEX;
 
     if (flags & HVhek_FREEKEY)
diff --git a/hv.h b/hv.h
index d0ac0e8..fd0cf2e 100644 (file)
--- a/hv.h
+++ b/hv.h
@@ -15,7 +15,10 @@ struct he {
        body arenas  */
     HE         *hent_next;     /* next entry in chain */
     HEK                *hent_hek;      /* hash key */
-    SV         *hent_val;      /* scalar value that was hashed */
+    union {
+       SV      *hent_val;      /* scalar value that was hashed */
+       Size_t  hent_refcount;  /* references for this shared hash key */
+    } he_valu;
 };
 
 /* hash key -- defined separately for use as shared pointer */
@@ -291,7 +294,7 @@ C<SV*>.
 #define HeKREHASH(he)  HEK_REHASH(HeKEY_hek(he))
 #define HeKLEN_UTF8(he)  (HeKUTF8(he) ? -HeKLEN(he) : HeKLEN(he))
 #define HeKFLAGS(he)  HEK_FLAGS(HeKEY_hek(he))
-#define HeVAL(he)              (he)->hent_val
+#define HeVAL(he)              (he)->he_valu.hent_val
 #define HeHASH(he)             HEK_HASH(HeKEY_hek(he))
 #define HePV(he,lp)            ((HeKLEN(he) == HEf_SVKEY) ?            \
                                 SvPV(HeKEY_sv(he),lp) :                \
@@ -372,7 +375,7 @@ C<SV*>.
     (++(((struct shared_he *)(((char *)hek)                            \
                              - STRUCT_OFFSET(struct shared_he,         \
                                              shared_he_hek)))          \
-       ->shared_he_he.hent_val),                                       \
+       ->shared_he_he.he_valu.hent_refcount),                          \
      hek)
 
 /*
diff --git a/perl.c b/perl.c
index 82960f3..e9f7795 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -1100,7 +1100,7 @@ perl_destruct(pTHXx)
                HE * const next = HeNEXT(hent);
                Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
                     "Unbalanced string table refcount: (%ld) for \"%s\"",
-                    (long)(HeVAL(hent) - Nullsv), HeKEY(hent));
+                    (long)hent->he_valu.hent_refcount, HeKEY(hent));
                Safefree(hent);
                hent = next;
            }