diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-10-20 21:33:53 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-10-21 08:18:29 -0700 |
commit | b7247a80ab6b02ec8a01b2c7c8d927ad173700ea (patch) | |
tree | 269850bf6f9a06ec8b0ce51d2b118db220518eaf /hv.c | |
parent | c035a075a240f10383292128a8d3f3746c4ac857 (diff) | |
download | perl-b7247a80ab6b02ec8a01b2c7c8d927ad173700ea.tar.gz |
Allow stashes to have multiple names
This commits modifies the HvAUX structure as follows: A new field is
added, named xhv_name_count, indicating the number of names. If it is
zero (the default and most common case), then xhv_name is a HEK * as
usual. If it is non-zero, then xhv_name actually holds a pointer to an
array of HEK*s, the first being the default or ‘canonical’ name.
This code is a little repetitious, but more refactorings are to come,
so it is too soon to turn these repetitions into macros.
This is yet another commit in preparation for fixing [perl #75176].
Basically, whenever a stash is deleted from its containing stash, if
it has an alias elsewhere, it needs to assume the new name (of that
alias; so it needs to know its other names already) and update isarev
entries. Forthcoming commits will do that.
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 27 |
1 files changed, 24 insertions, 3 deletions
@@ -1621,6 +1621,7 @@ S_hfreeentries(pTHX_ HV *hv) /* This is the array that we're going to restore */ HE **const orig_array = HvARRAY(hv); HEK *name; + U32 name_count; int attempts = 100; PERL_ARGS_ASSERT_HFREEENTRIES; @@ -1634,9 +1635,11 @@ S_hfreeentries(pTHX_ HV *hv) struct xpvhv_aux *iter = HvAUX(hv); name = iter->xhv_name; + name_count = iter->xhv_name_count; iter->xhv_name = NULL; } else { name = NULL; + name_count = 0; } /* orig_array remains unchanged throughout the loop. If after freeing all @@ -1768,7 +1771,14 @@ S_hfreeentries(pTHX_ HV *hv) assert(HvARRAY(hv)); if (HvAUX(hv)->xhv_name) { - unshare_hek_or_pvn(HvAUX(hv)->xhv_name, 0, 0, 0); + if(HvAUX(hv)->xhv_name_count) { + HEK ** const name = (HEK **)HvAUX(hv)->xhv_name; + HEK **hekp = name + HvAUX(hv)->xhv_name_count; + while(hekp-- > name) + unshare_hek_or_pvn(*hekp, 0, 0, 0); + Safefree(name); + } + else unshare_hek_or_pvn(HvAUX(hv)->xhv_name, 0, 0, 0); } } @@ -1784,8 +1794,10 @@ S_hfreeentries(pTHX_ HV *hv) /* We have restored the original array. If name is non-NULL, then the original array had an aux structure at the end. So this is valid: */ + struct xpvhv_aux * const aux = HvAUX(hv); SvFLAGS(hv) |= SVf_OOK; - HvAUX(hv)->xhv_name = name; + aux->xhv_name = name; + aux->xhv_name_count = name_count; } } @@ -1883,6 +1895,7 @@ S_hv_auxinit(HV *hv) { iter->xhv_riter = -1; /* HvRITER(hv) = -1 */ iter->xhv_eiter = NULL; /* HvEITER(hv) = NULL */ iter->xhv_name = 0; + iter->xhv_name_count = 0; iter->xhv_backreferences = 0; iter->xhv_mro_meta = NULL; return iter; @@ -2014,7 +2027,14 @@ Perl_hv_name_set(pTHX_ HV *hv, const char *name, U32 len, U32 flags) if (SvOOK(hv)) { iter = HvAUX(hv); if (iter->xhv_name) { - unshare_hek_or_pvn(iter->xhv_name, 0, 0, 0); + if(iter->xhv_name_count) { + HEK ** const name = (HEK **)HvAUX(hv)->xhv_name; + HEK **hekp = name + HvAUX(hv)->xhv_name_count; + while(hekp-- > name) + unshare_hek_or_pvn(*hekp, 0, 0, 0); + Safefree(name); + } + else unshare_hek_or_pvn(iter->xhv_name, 0, 0, 0); } } else { if (name == 0) @@ -2024,6 +2044,7 @@ Perl_hv_name_set(pTHX_ HV *hv, const char *name, U32 len, U32 flags) } PERL_HASH(hash, name, len); iter->xhv_name = name ? share_hek(name, len, hash) : NULL; + iter->xhv_name_count = 0; } AV ** |