summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2008-08-21 00:02:57 +0000
committerDave Mitchell <davem@fdisolutions.com>2008-08-21 00:02:57 +0000
commitfd996479e27a404cbaed7b3ad029feb14440afb0 (patch)
tree401fe37f7b7686312295c89bba1178bcff95b849
parent41fae7a143a727427be3286c0c9dea8033177568 (diff)
downloadperl-fd996479e27a404cbaed7b3ad029feb14440afb0.tar.gz
better document how the weakref backrefs array is refcounted
p4raw-id: //depot/perl@34211
-rw-r--r--sv.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/sv.c b/sv.c
index 6957382ed8..f721e6f551 100644
--- a/sv.c
+++ b/sv.c
@@ -5007,6 +5007,24 @@ Perl_sv_rvweaken(pTHX_ SV *const sv)
* back-reference to sv onto the array associated with the backref magic.
*/
+/* A discussion about the backreferences array and its refcount:
+ *
+ * The AV holding the backreferences is pointed to either as the mg_obj of
+ * PERL_MAGIC_backref, or in the specific case of a HV that has the hv_aux
+ * structure, from the xhv_backreferences field. (A HV without hv_aux will
+ * have the standard magic instead.) The array is created with a refcount
+ * of 2. This means that if during global destruction the array gets
+ * picked on first to have its refcount decremented by the random zapper,
+ * it won't actually be freed, meaning it's still theere for when its
+ * parent gets freed.
+ * When the parent SV is freed, in the case of magic, the magic is freed,
+ * Perl_magic_killbackrefs is called which decrements one refcount, then
+ * mg_obj is freed which kills the second count.
+ * In the vase of a HV being freed, one ref is removed by
+ * Perl_hv_kill_backrefs, the other by Perl_sv_kill_backrefs, which it
+ * calls.
+ */
+
void
Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv)
{
@@ -5035,7 +5053,7 @@ Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv)
} else {
av = newAV();
AvREAL_off(av);
- SvREFCNT_inc_simple_void(av);
+ SvREFCNT_inc_simple_void(av); /* see discussion above */
}
*avp = av;
}
@@ -5048,9 +5066,7 @@ Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv)
av = newAV();
AvREAL_off(av);
sv_magic(tsv, (SV*)av, PERL_MAGIC_backref, NULL, 0);
- /* av now has a refcnt of 2, which avoids it getting freed
- * before us during global cleanup. The extra ref is removed
- * by magic_killbackrefs() when tsv is being freed */
+ /* av now has a refcnt of 2; see discussion above */
}
}
if (AvFILLp(av) >= AvMAX(av)) {