Fix an error, spotted by Tim Bunce.
[p5sagit/p5-mst-13.2.git] / hv.h
diff --git a/hv.h b/hv.h
index 1ec5d56..9e31335 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 */
@@ -38,6 +41,7 @@ struct shared_he {
 */
 struct xpvhv_aux {
     HEK                *xhv_name;      /* name, if a symbol table */
+    AV         *xhv_backreferences; /* back references for weak references */
     HE         *xhv_eiter;     /* current entry of iterator */
     I32                xhv_riter;      /* current root of iterator */
 };
@@ -45,15 +49,23 @@ struct xpvhv_aux {
 /* hash structure: */
 /* This structure must match the beginning of struct xpvmg in sv.h. */
 struct xpvhv {
-    NV         xnv_nv;         /* numeric value, if any */
+    union {
+       NV      xnv_nv;         /* numeric value, if any */
+       HV *    xgv_stash;
+    }          xnv_u;
     STRLEN     xhv_fill;       /* how full xhv_array currently is */
     STRLEN     xhv_max;        /* subscript of last element of xhv_array */
     union {
        IV      xivu_iv;        /* integer value or pv offset */
        UV      xivu_uv;
        void *  xivu_p1;
+       I32     xivu_i32;
+       HEK *   xivu_namehek;
     }          xiv_u;
-    MAGIC*     xmg_magic;      /* magic for scalar array */
+    union {
+       MAGIC*  xmg_magic;      /* linked list of magicalness */
+       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
+    } xmg_u;
     HV*                xmg_stash;      /* class package */
 };
 
@@ -69,8 +81,13 @@ typedef struct {
        IV      xivu_iv;        /* integer value or pv offset */
        UV      xivu_uv;
        void *  xivu_p1;
+       I32     xivu_i32;
+       HEK *   xivu_namehek;
     }          xiv_u;
-    MAGIC*     xmg_magic;      /* magic for scalar array */
+    union {
+       MAGIC*  xmg_magic;      /* linked list of magicalness */
+       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
+    } xmg_u;
     HV*                xmg_stash;      /* class package */
 } xpvhv_allocated;
 #endif
@@ -82,7 +99,7 @@ typedef struct {
 /* The use of a temporary pointer and the casting games
  * is needed to serve the dual purposes of
  * (a) the hashed data being interpreted as "unsigned char" (new since 5.8,
- *     a "char" can be either signed or signed, depending on the compiler)
+ *     a "char" can be either signed or unsigned, depending on the compiler)
  * (b) catering for old code that uses a "char"
  *
  * The "hash seed" feature was added in Perl 5.8.1 to perturb the results
@@ -103,7 +120,7 @@ typedef struct {
 #endif
 #define PERL_HASH(hash,str,len) \
      STMT_START        { \
-       register const char *s_PeRlHaSh_tmp = str; \
+       register const char * const s_PeRlHaSh_tmp = str; \
        register const unsigned char *s_PeRlHaSh = (const unsigned char *)s_PeRlHaSh_tmp; \
        register I32 i_PeRlHaSh = len; \
        register U32 hash_PeRlHaSh = PERL_HASH_SEED; \
@@ -121,7 +138,7 @@ typedef struct {
 #ifdef PERL_HASH_INTERNAL_ACCESS
 #define PERL_HASH_INTERNAL(hash,str,len) \
      STMT_START        { \
-       register const char *s_PeRlHaSh_tmp = str; \
+       register const char * const s_PeRlHaSh_tmp = str; \
        register const unsigned char *s_PeRlHaSh = (const unsigned char *)s_PeRlHaSh_tmp; \
        register I32 i_PeRlHaSh = len; \
        register U32 hash_PeRlHaSh = PL_rehash_seed; \
@@ -185,7 +202,7 @@ the length of hash keys. This is very similar to the C<SvPV()> macro
 described elsewhere in this document.
 
 =for apidoc Am|SV*|HeSVKEY|HE* he
-Returns the key as an C<SV*>, or C<Nullsv> if the hash entry does not
+Returns the key as an C<SV*>, or C<NULL> if the hash entry does not
 contain an C<SV*> key.
 
 =for apidoc Am|SV*|HeSVKEY_force|HE* he
@@ -266,19 +283,6 @@ C<SV*>.
 #define HvREHASH_on(hv)                (SvFLAGS(hv) |= SVphv_REHASH)
 #define HvREHASH_off(hv)       (SvFLAGS(hv) &= ~SVphv_REHASH)
 
-/* Maybe amagical: */
-/* #define HV_AMAGICmb(hv)      (SvFLAGS(hv) & (SVpgv_badAM | SVpgv_AM)) */
-
-#define HV_AMAGIC(hv)        (SvFLAGS(hv) &   SVpgv_AM)
-#define HV_AMAGIC_on(hv)     (SvFLAGS(hv) |=  SVpgv_AM)
-#define HV_AMAGIC_off(hv)    (SvFLAGS(hv) &= ~SVpgv_AM)
-
-/*
-#define HV_AMAGICbad(hv)     (SvFLAGS(hv) & SVpgv_badAM)
-#define HV_badAMAGIC_on(hv)  (SvFLAGS(hv) |= SVpgv_badAM)
-#define HV_badAMAGIC_off(hv) (SvFLAGS(hv) &= ~SVpgv_badAM)
-*/
-
 #define Nullhe Null(HE*)
 #define HeNEXT(he)             (he)->hent_next
 #define HeKEY_hek(he)          (he)->hent_hek
@@ -290,16 +294,16 @@ 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) :                \
                                 (((lp = HeKLEN(he)) >= 0) ?            \
-                                 HeKEY(he) : Nullch))
+                                 HeKEY(he) : NULL))
 
 #define HeSVKEY(he)            ((HeKEY(he) &&                          \
                                  HeKLEN(he) == HEf_SVKEY) ?            \
-                                HeKEY_sv(he) : Nullsv)
+                                HeKEY_sv(he) : NULL)
 
 #define HeSVKEY_force(he)      (HeKEY(he) ?                            \
                                 ((HeKLEN(he) == HEf_SVKEY) ?           \
@@ -360,6 +364,9 @@ C<SV*>.
 /* Flags for hv_iternext_flags.  */
 #define HV_ITERNEXT_WANTPLACEHOLDERS   0x01    /* Don't skip placeholders.  */
 
+#define hv_iternext(hv)        hv_iternext_flags(hv, 0)
+#define hv_magic(hv, gv, how) sv_magic((SV*)(hv), (SV*)(gv), how, NULL, 0)
+
 /* available as a function in hv.c */
 #define Perl_sharepvn(sv, len, hash) HEK_KEY(share_hek(sv, len, hash))
 #define sharepvn(sv, len, hash)             Perl_sharepvn(sv, len, hash)
@@ -368,9 +375,63 @@ 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)
 
+/* This refcounted he structure is used for storing the hints used for lexical
+   pragmas. Without threads, it's basically struct he + refcount.
+   With threads, life gets more complex as the structure needs to be shared
+   between threads (because it hangs from OPs, which are shared), hence the
+   alternate definition and mutex.  */
+
+#ifdef PERL_CORE
+
+/* Gosh. This really isn't a good name any longer.  */
+struct refcounted_he {
+    struct refcounted_he *refcounted_he_next;  /* next entry in chain */
+#ifdef USE_ITHREADS
+    U32                   refcounted_he_hash;
+    U32                   refcounted_he_keylen;
+#else
+    HEK                  *refcounted_he_hek;   /* hint key */
+#endif
+    U32                          refcounted_he_refcnt; /* reference count */
+    union {
+       IV                refcounted_he_u_iv;
+       UV                refcounted_he_u_uv;
+       STRLEN            refcounted_he_u_len;
+    } refcounted_he_val;
+    /* First byte is flags. Then NUL-terminated value. Then for ithreads,
+       non-NUL terminated key.  */
+    char                  refcounted_he_data[1];
+};
+
+/* Flag bits are HVhek_UTF8, HVhek_WASUTF8, then */
+#define HVrhek_undef   0x00 /* Value is undef. */
+#define HVrhek_PV      0x10 /* Value is a string. */
+#define HVrhek_IV      0x20 /* Value is IV/UV. */
+#define HVrhek_delete  0x30 /* Value is placeholder - signifies delete. */
+#define HVrhek_typemask        0x30
+#define HVrhek_UTF8    0x40 /* string value is utf8. */
+#define HVrhek_UV      0x40 /* integer value is UV. */
+
+#  ifdef USE_ITHREADS
+#    define HINTS_REFCNT_LOCK          MUTEX_LOCK(&PL_hints_mutex)
+#    define HINTS_REFCNT_UNLOCK                MUTEX_UNLOCK(&PL_hints_mutex)
+#  else
+#    define HINTS_REFCNT_LOCK          NOOP
+#    define HINTS_REFCNT_UNLOCK                NOOP
+#  endif
+#endif
+
+#ifdef USE_ITHREADS
+#  define HINTS_REFCNT_INIT            MUTEX_INIT(&PL_hints_mutex)
+#  define HINTS_REFCNT_TERM            MUTEX_DESTROY(&PL_hints_mutex)
+#else
+#  define HINTS_REFCNT_INIT            NOOP
+#  define HINTS_REFCNT_TERM            NOOP
+#endif
+
 /*
  * Local variables:
  * c-indentation-style: bsd