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. 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,
+ /* 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) {
av = *avp;
if (!av) {
- /* There is no AV in the offical place - try a fixup. */
+ /* There is no AV in the official place - try a fixup. */
MAGIC *const mg = mg_find(tsv, PERL_MAGIC_backref);
if (mg) {
/* Aha. They've got it stowed in magic. Bring it back. */
av = MUTABLE_AV(mg->mg_obj);
- /* Stop mg_free decreasing the refernce count. */
+ /* Stop mg_free decreasing the reference count. */
mg->mg_obj = NULL;
/* Stop mg_free even calling the destructor, given that
there's no AV to free up. */