Blob Blame History Raw
diff -up perl-5.8.8/sv.c.U31996 perl-5.8.8/sv.c
--- perl-5.8.8/sv.c.U31996	2008-08-27 10:04:08.000000000 -0400
+++ perl-5.8.8/sv.c	2008-08-27 10:07:51.000000000 -0400
@@ -8016,6 +8016,55 @@ S_reset_amagic(pTHX_ SV *rv, const bool 
 	/* There was only 1 reference to this object.  */
 	return;
     }
+    /* References to objects may be via RVs, or anything else that can hold
+       a reference count (AVs, HVs, GVs, and arbitrary C code)
+       Object-ness can only be accessed via true RVs, including the overloading
+       part of object-ness, so for that part it doesn't matter that the
+       overloading flag (pre 5.10) is on the reference. But the overloading
+       mechanism itself checks the referent, the object itself, hence they
+       can get out of sync.
+
+       We'll assume two common cases - either we got here through a real
+       reference, and the referent is a value in the pad of the current
+       subroutine (hence a reference count of 2 or more), during construction
+       of the reference, or that there is a second (or more) reference to
+       the object (but no arrays, hashes, pads, typeglobs or other things)
+       pointing to it.
+
+       The first case is likely to involve quite a small search.
+       The second case is O(n) on the number of SVs, but we can make it
+       terminate early if we find every reference is accounted for by an RV.
+       [Terminating early is still O(n), but with a smaller constant.]
+    */
+    {
+	/* So before trying the large O(n) linear search of all SVs, start by
+	   seeing if we can find the other references in the current pad.
+	   This avoids the big search for constructions such as
+	   my $string = ...;
+	   my $obj = bless \$string, $class;
+	   which modules like URI use.  */
+
+	U32 how_many_in_pad = how_many;
+	CV *const current_sub = find_runcv(NULL);
+	AV *const padlist = CvPADLIST(current_sub);
+	AV *const curpad = (AV*) AvARRAY(padlist)[CvDEPTH(current_sub)];
+	SV ** const start = AvARRAY(curpad);
+	SV ** end = start + AvFILLp(curpad);
+
+	while (end >= start) {
+	    SV *const sv = *end--;
+	    if (sv == target) {
+		if (--how_many_in_pad == 0) {
+		    /* We have found them all.  */
+		    return;
+		}
+	    }
+	}
+    }
+
+    /* Right, didn't find all the other referneces were lexicals or temporaries
+       in the pad, so need to do an exhaustive search to find all references.
+    */
 
     for (sva = PL_sv_arenaroot; sva; sva = (SV*)SvANY(sva)) {
 	register const SV * const svend = &sva[SvREFCNT(sva)];
@@ -8037,6 +8086,10 @@ S_reset_amagic(pTHX_ SV *rv, const bool 
 	    }
 	}
     }
+
+    /* Can get here if the object happens to be lexical somewhere else, a
+       global, an element in an array or hash, etc. But we will have found all
+       the references.  */
 }
 
 /*