summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-20 21:33:53 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-21 08:18:29 -0700
commitb7247a80ab6b02ec8a01b2c7c8d927ad173700ea (patch)
tree269850bf6f9a06ec8b0ce51d2b118db220518eaf /hv.c
parentc035a075a240f10383292128a8d3f3746c4ac857 (diff)
downloadperl-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.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/hv.c b/hv.c
index c040e257c1..d5dacab3db 100644
--- a/hv.c
+++ b/hv.c
@@ -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 **