X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.h;h=efba2b98bdf67eaac8113c8266a6d452a467f63e;hb=943795c2b00ef89ec677d4af7a0a6bfabab5c916;hp=c99d4790f7d1c03add3fc9703065fd23a0fc87d7;hpb=9b9d0b15bd9c5c0115200324ab9b04803069c7ce;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.h b/hv.h index c99d479..efba2b9 100644 --- a/hv.h +++ b/hv.h @@ -8,15 +8,17 @@ * */ -/* typedefs to eliminate some typing */ -typedef struct he HE; -typedef struct hek HEK; - /* entry in hash value chain */ struct he { + /* Keep hent_next first in this structure, because sv_free_arenas take + advantage of this to share code between the he arenas and the SV + 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 */ @@ -29,12 +31,17 @@ struct hek { is UTF-8 */ }; +struct shared_he { + struct he shared_he_he; + struct hek shared_he_hek; +}; /* Subject to change. Don't access this directly. */ 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 */ }; @@ -42,44 +49,45 @@ struct xpvhv_aux { /* hash structure: */ /* This structure must match the beginning of struct xpvmg in sv.h. */ struct xpvhv { - IV for_rent; + 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 { - struct { - void *xnv_p1; - union { - void *xnv_p2; - IV xnv_i2; /* how many elements in the array */ - } xnv_u2; - } xnv_s; - NV xnvu_nv; /* numeric value, if any */ - } xnv_u; - MAGIC* xmg_magic; /* magic for scalar array */ + IV xivu_iv; /* integer value or pv offset */ + UV xivu_uv; + void * xivu_p1; + I32 xivu_i32; + HEK * xivu_namehek; + } xiv_u; + 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 */ - /* list of pm's for this package is now stored in symtab magic. */ }; -#define xhv_aux xnv_u.xnv_s.xnv_p1 -#define xhv_keys xnv_u.xnv_s.xnv_u2.xnv_i2 +#define xhv_keys xiv_u.xivu_iv -#if !defined(PERL_EXPERIMENTAL_LAYOUT) +#if 0 typedef struct xpvhv xpvhv_allocated; #else typedef struct { STRLEN xhv_fill; /* how full xhv_array currently is */ STRLEN xhv_max; /* subscript of last element of xhv_array */ union { - NV xnvu_nv; /* numeric value, if any */ - struct { - void *xnv_p1; - union { - void *xnv_p2; - IV xnv_i2; /* how many elements in the array */ - } xnv_u2; - } xnv_s; - } xnv_u; - MAGIC* xmg_magic; /* magic for scalar array */ + IV xivu_iv; /* integer value or pv offset */ + UV xivu_uv; + void * xivu_p1; + I32 xivu_i32; + HEK * xivu_namehek; + } xiv_u; + 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 @@ -91,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 @@ -112,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; \ @@ -130,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; \ @@ -161,7 +169,8 @@ Null HV pointer. =head1 Hash Manipulation Functions =for apidoc Am|char*|HvNAME|HV* stash -Returns the package name of a stash. See C, C. +Returns the package name of a stash, or NULL if C isn't a stash. +See C, C. =for apidoc Am|void*|HeKEY|HE* he Returns the actual pointer stored in the key slot of the hash entry. The @@ -193,7 +202,7 @@ the length of hash keys. This is very similar to the C macro described elsewhere in this document. =for apidoc Am|SV*|HeSVKEY|HE* he -Returns the key as an C, or C if the hash entry does not +Returns the key as an C, or C if the hash entry does not contain an C key. =for apidoc Am|SV*|HeSVKEY_force|HE* he @@ -213,26 +222,27 @@ C. #define Nullhv Null(HV*) -#define HvARRAY(hv) (*(HE***)&((hv)->sv_u.svu_array)) +#define HvARRAY(hv) ((hv)->sv_u.svu_hash) #define HvFILL(hv) ((XPVHV*) SvANY(hv))->xhv_fill #define HvMAX(hv) ((XPVHV*) SvANY(hv))->xhv_max +/* This quite intentionally does no flag checking first. That's your + responsibility. */ +#define HvAUX(hv) ((struct xpvhv_aux*)&(HvARRAY(hv)[HvMAX(hv)+1])) #define HvRITER(hv) (*Perl_hv_riter_p(aTHX_ (HV*)(hv))) #define HvEITER(hv) (*Perl_hv_eiter_p(aTHX_ (HV*)(hv))) #define HvRITER_set(hv,r) Perl_hv_riter_set(aTHX_ (HV*)(hv), r) #define HvEITER_set(hv,e) Perl_hv_eiter_set(aTHX_ (HV*)(hv), e) -#define HvRITER_get(hv) (((XPVHV *)SvANY(hv))->xhv_aux ? \ - ((struct xpvhv_aux*)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_riter : -1) -#define HvEITER_get(hv) (((XPVHV *)SvANY(hv))->xhv_aux ? \ - ((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_eiter : 0) +#define HvRITER_get(hv) (SvOOK(hv) ? HvAUX(hv)->xhv_riter : -1) +#define HvEITER_get(hv) (SvOOK(hv) ? HvAUX(hv)->xhv_eiter : 0) #define HvNAME(hv) HvNAME_get(hv) /* FIXME - all of these should use a UTF8 aware API, which should also involve getting the length. */ /* This macro may go away without notice. */ -#define HvNAME_HEK(hv) (((XPVHV *)SvANY(hv))->xhv_aux && (((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_name) ? ((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_name: 0) -#define HvNAME_get(hv) (((XPVHV *)SvANY(hv))->xhv_aux ? \ - (((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_name) ? HEK_KEY(((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_name) : 0 : 0) -#define HvNAMELEN_get(hv) (((XPVHV *)SvANY(hv))->xhv_aux ? \ - (((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_name) ? HEK_LEN(((struct xpvhv_aux *)((XPVHV *)SvANY(hv))->xhv_aux)->xhv_name) : 0 : 0) +#define HvNAME_HEK(hv) (SvOOK(hv) ? HvAUX(hv)->xhv_name : 0) +#define HvNAME_get(hv) ((SvOOK(hv) && (HvAUX(hv)->xhv_name)) \ + ? HEK_KEY(HvAUX(hv)->xhv_name) : 0) +#define HvNAMELEN_get(hv) ((SvOOK(hv) && (HvAUX(hv)->xhv_name)) \ + ? HEK_LEN(HvAUX(hv)->xhv_name) : 0) /* the number of keys (including any placeholers) */ #define XHvTOTALKEYS(xhv) ((xhv)->xhv_keys) @@ -273,19 +283,6 @@ C. #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 @@ -297,16 +294,16 @@ C. #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) ? \ @@ -367,10 +364,20 @@ C. /* 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) +#define share_hek_hek(hek) \ + (++(((struct shared_he *)(((char *)hek) \ + - STRUCT_OFFSET(struct shared_he, \ + shared_he_hek))) \ + ->shared_he_he.he_valu.hent_refcount), \ + hek) + /* * Local variables: * c-indentation-style: bsd