Document why it's a bad plan to move the backreferences array from
Nicholas Clark [Fri, 30 Dec 2005 16:53:39 +0000 (16:53 +0000)]
the magic structure to the hv_aux structure during backreference
deletion. Add an optimisation for an empty backreference array.

p4raw-id: //depot/perl@26542

hv.c
sv.c

diff --git a/hv.c b/hv.c
index e560ba7..27c4bec 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -1664,11 +1664,16 @@ S_hfreeentries(pTHX_ HV *hv)
     if (iter) {
        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.  */
+              sv_magic will increase the reference count of the AV, so we
+              need to drop it first. */
            SvREFCNT_dec(iter->xhv_backreferences);
-           sv_magic((SV*)hv, (SV*)iter->xhv_backreferences,
-                    PERL_MAGIC_backref, NULL, 0);
+           if (AvFILLp(iter->xhv_backreferences) == -1) {
+               /* Turns out that the array is empty. Just free it.  */
+               SvREFCNT_dec(iter->xhv_backreferences);
+           } else {
+               sv_magic((SV*)hv, (SV*)iter->xhv_backreferences,
+                        PERL_MAGIC_backref, NULL, 0);
+           }
            iter->xhv_backreferences = 0;
        }
     }
diff --git a/sv.c b/sv.c
index 3e3bb18..5372215 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -4409,6 +4409,10 @@ S_sv_del_backref(pTHX_ SV *tsv, SV *sv)
 
     if (SvTYPE(tsv) == SVt_PVHV && SvOOK(tsv)) {
        av = *Perl_hv_backreferences_p(aTHX_ (HV*)tsv);
+       /* We mustn't attempt to "fix up" the hash here by moving the
+          backreference array back to the hv_aux structure, as that is stored
+          in the main HvARRAY(), and hfreentries assumes that no-one
+          reallocates HvARRAY() while it is running.  */
     }
     if (!av) {
        const MAGIC *const mg