static const char S_strtab_error[]
= "Cannot modify shared string table in hv_%s";
-STATIC void
-S_more_he(pTHX)
-{
- dVAR;
- /* We could generate this at compile time via (another) auxiliary C
- program? */
- const size_t arena_size = Perl_malloc_good_size(PERL_ARENA_SIZE);
- HE* he = (HE*) Perl_get_arena(aTHX_ arena_size, HE_SVSLOT);
- HE * const heend = &he[arena_size / sizeof(HE) - 1];
-
- PL_body_roots[HE_SVSLOT] = he;
- while (he < heend) {
- HeNEXT(he) = (HE*)(he + 1);
- he++;
- }
- HeNEXT(he) = 0;
-}
-
#ifdef PURIFY
#define new_HE() (HE*)safemalloc(sizeof(HE))
void ** const root = &PL_body_roots[HE_SVSLOT];
if (!*root)
- S_more_he(aTHX);
+ Perl_more_bodies(aTHX_ HE_SVSLOT, sizeof(HE), PERL_ARENA_SIZE);
he = (HE*) *root;
assert(he);
*root = HeNEXT(he);
if (!entry) /* non-existent */
continue;
bep = aep+oldsize;
- for (; entry; entry = *oentry) {
+ do {
if ((HeHASH(entry) & newsize) != (U32)i) {
*oentry = HeNEXT(entry);
HeNEXT(entry) = *bep;
*bep = entry;
right_length++;
- continue;
}
else {
oentry = &HeNEXT(entry);
left_length++;
}
- }
+ entry = *oentry;
+ } while (entry);
/* I think we don't actually need to keep track of the longest length,
merely flag if anything is too long. But for the moment while
developing this code I'll track it. */
if (!entry) /* non-existent */
continue;
- for (; entry; entry = *oentry) {
+ do {
register I32 j = (HeHASH(entry) & newsize);
if (j != i) {
*oentry = HeNEXT(entry);
HeNEXT(entry) = aep[j];
aep[j] = entry;
- continue;
}
else
oentry = &HeNEXT(entry);
- }
+ entry = *oentry;
+ } while (entry);
}
}
if (!entry)
return;
val = HeVAL(entry);
- if (HvNAME(hv) && anonymise_cv(HvNAME_HEK(hv), val) && GvCVu(val))
- mro_method_changed_in(hv);
+ if (val && isGV(val) && isGV_with_GP(val) && GvCVu(val) && HvNAME_get(hv))
+ mro_method_changed_in(hv); /* deletion of method from stash */
SvREFCNT_dec(val);
if (HeKLEN(entry) == HEf_SVKEY) {
SvREFCNT_dec(HeKEY_sv(entry));
del_HE(entry);
}
-static I32
-S_anonymise_cv(pTHX_ HEK *stash, SV *val)
-{
- CV *cv;
-
- PERL_ARGS_ASSERT_ANONYMISE_CV;
-
- if (val && isGV(val) && isGV_with_GP(val) && (cv = GvCV(val))) {
- if ((SV *)CvGV(cv) == val) {
- GV *anongv;
-
- if (stash) {
- SV *gvname = newSVhek(stash);
- sv_catpvs(gvname, "::__ANON__");
- anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
- SvREFCNT_dec(gvname);
- } else {
- anongv = gv_fetchpvs("__ANON__::__ANON__", GV_ADDMULTI,
- SVt_PVCV);
- }
- CvGV(cv) = anongv;
- CvANON_on(cv);
- return 1;
- }
- }
- return 0;
-}
void
Perl_hv_delayfree_ent(pTHX_ HV *hv, register HE *entry)
if (!orig_array)
return;
- if (HvNAME(hv) && orig_array != NULL) {
- /* symbol table: make all the contained subs ANON */
- STRLEN i;
- XPVHV *xhv = (XPVHV*)SvANY(hv);
-
- for (i = 0; i <= xhv->xhv_max; i++) {
- HE *entry = (HvARRAY(hv))[i];
- for (; entry; entry = HeNEXT(entry)) {
- SV *val = HeVAL(entry);
- /* we need to put the subs in the __ANON__ symtable, as
- * this one is being cleared. */
- anonymise_cv(NULL, val);
- }
- }
- }
-
if (SvOOK(hv)) {
/* If the hash is actually a symbol table with a name, look after the
name. */
HE *entry;
struct mro_meta *meta;
struct xpvhv_aux *iter = HvAUX(hv);
- /* If there are weak references to this HV, we need to avoid
- freeing them up here. In particular we need to keep the AV
- visible as what we're deleting might well have weak references
- back to this HV, so the for loop below may well trigger
- the removal of backreferences from this array. */
+ /* weak references: if called from sv_clear(), the backrefs
+ * should already have been killed; if there are any left, its
+ * because we're doing hv_clear() or hv_undef(), and the HV
+ * will continue to live.
+ * Because while freeing the entries we fake up a NULL HvARRAY
+ * (and hence HvAUX), we need to store the backref array
+ * somewhere else; but it still needs to be visible in case
+ * any the things we free happen to call sv_del_backref().
+ * We do this by storing it in magic instead.
+ * If, during the entry freeing, a destructor happens to add
+ * a new weak backref, then sv_add_backref will look in both
+ * places (magic in HvAUX) for the AV, but will create a new
+ * AV in HvAUX if it can't find one (if it finds it in magic,
+ * it moves it back into HvAUX. So at the end of the iteration
+ * we have to allow for this. */
+
if (iter->xhv_backreferences) {
- /* So donate them to regular backref magic to keep them safe.
- The sv_magic will increase the reference count of the AV,
- so we need to drop it first. */
- SvREFCNT_dec(iter->xhv_backreferences);
- if (AvFILLp(iter->xhv_backreferences) == -1) {
- /* Turns out that the array is empty. Just free it. */
+ if (SvTYPE(iter->xhv_backreferences) == SVt_PVAV) {
+ /* The sv_magic will increase the reference count of the AV,
+ so we need to drop it first. */
SvREFCNT_dec(iter->xhv_backreferences);
+ if (AvFILLp(iter->xhv_backreferences) == -1) {
+ /* Turns out that the array is empty. Just free it. */
+ SvREFCNT_dec(iter->xhv_backreferences);
- } else {
- sv_magic(MUTABLE_SV(hv),
- MUTABLE_SV(iter->xhv_backreferences),
- PERL_MAGIC_backref, NULL, 0);
+ } else {
+ sv_magic(MUTABLE_SV(hv),
+ MUTABLE_SV(iter->xhv_backreferences),
+ PERL_MAGIC_backref, NULL, 0);
+ }
+ }
+ else {
+ MAGIC *mg;
+ sv_magic(MUTABLE_SV(hv), NULL, PERL_MAGIC_backref, NULL, 0);
+ mg = mg_find(MUTABLE_SV(hv), PERL_MAGIC_backref);
+ mg->mg_obj = (SV*)iter->xhv_backreferences;
}
iter->xhv_backreferences = NULL;
}
}
/* make everyone else think the array is empty, so that the destructors
- * called for freed entries can't recusively mess with us */
+ * called for freed entries can't recursively mess with us */
HvARRAY(hv) = NULL;
((XPVHV*) SvANY(hv))->xhv_keys = 0;
if (av) {
HvAUX(hv)->xhv_backreferences = 0;
Perl_sv_kill_backrefs(aTHX_ MUTABLE_SV(hv), av);
- SvREFCNT_dec(av);
+ if (SvTYPE(av) == SVt_PVAV)
+ SvREFCNT_dec(av);
}
}