| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 1 | /* | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 2 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 3 |   Reference Cycle Garbage Collection | 
 | 4 |   ================================== | 
 | 5 |  | 
| Neil Schemenauer | b2c2c9e | 2000-10-04 16:34:09 +0000 | [diff] [blame] | 6 |   Neil Schemenauer <nas@arctrix.com> | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 7 |  | 
 | 8 |   Based on a post on the python-dev list.  Ideas from Guido van Rossum, | 
 | 9 |   Eric Tiedemann, and various others. | 
 | 10 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 11 |   http://www.arctrix.com/nas/python/gc/ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 12 |   http://www.python.org/pipermail/python-dev/2000-March/003869.html | 
 | 13 |   http://www.python.org/pipermail/python-dev/2000-March/004010.html | 
 | 14 |   http://www.python.org/pipermail/python-dev/2000-March/004022.html | 
 | 15 |  | 
 | 16 |   For a highlevel view of the collection process, read the collect | 
 | 17 |   function. | 
 | 18 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 19 | */ | 
 | 20 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 21 | #include "Python.h" | 
 | 22 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 23 | /* Get an object's GC head */ | 
 | 24 | #define AS_GC(o) ((PyGC_Head *)(o)-1) | 
 | 25 |  | 
 | 26 | /* Get the object given the GC head */ | 
 | 27 | #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) | 
 | 28 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 29 | /*** Global GC state ***/ | 
 | 30 |  | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 31 | struct gc_generation { | 
 | 32 | 	PyGC_Head head; | 
 | 33 | 	int threshold; /* collection threshold */ | 
 | 34 | 	int count; /* count of allocations or collections of younger | 
 | 35 | 		      generations */ | 
 | 36 | }; | 
 | 37 |  | 
 | 38 | #define NUM_GENERATIONS 3 | 
 | 39 | #define GEN_HEAD(n) (&generations[n].head) | 
 | 40 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 41 | /* linked lists of container objects */ | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 42 | static struct gc_generation generations[NUM_GENERATIONS] = { | 
 | 43 | 	/* PyGC_Head,				threshold,	count */ | 
 | 44 | 	{{{GEN_HEAD(0), GEN_HEAD(0), 0}},	700,		0}, | 
 | 45 | 	{{{GEN_HEAD(1), GEN_HEAD(1), 0}},	10,		0}, | 
 | 46 | 	{{{GEN_HEAD(2), GEN_HEAD(2), 0}},	10,		0}, | 
 | 47 | }; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 48 |  | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 49 | PyGC_Head *_PyGC_generation0 = GEN_HEAD(0); | 
 | 50 |  | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 51 | static int enabled = 1; /* automatic collection enabled? */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 52 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 53 | /* true if we are currently running the collector */ | 
 | 54 | static int collecting; | 
 | 55 |  | 
| Tim Peters | 6fc13d9 | 2002-07-02 18:12:35 +0000 | [diff] [blame] | 56 | /* list of uncollectable objects */ | 
 | 57 | static PyObject *garbage; | 
 | 58 |  | 
 | 59 | /* Python string to use if unhandled exception occurs */ | 
 | 60 | static PyObject *gc_str; | 
 | 61 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 62 | /* set for debugging information */ | 
 | 63 | #define DEBUG_STATS		(1<<0) /* print collection statistics */ | 
 | 64 | #define DEBUG_COLLECTABLE	(1<<1) /* print collectable objects */ | 
 | 65 | #define DEBUG_UNCOLLECTABLE	(1<<2) /* print uncollectable objects */ | 
 | 66 | #define DEBUG_INSTANCES		(1<<3) /* print instances */ | 
 | 67 | #define DEBUG_OBJECTS		(1<<4) /* print other objects */ | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 68 | #define DEBUG_SAVEALL		(1<<5) /* save all garbage in gc.garbage */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 69 | #define DEBUG_LEAK		DEBUG_COLLECTABLE | \ | 
 | 70 | 				DEBUG_UNCOLLECTABLE | \ | 
 | 71 | 				DEBUG_INSTANCES | \ | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 72 | 				DEBUG_OBJECTS | \ | 
 | 73 | 				DEBUG_SAVEALL | 
| Jeremy Hylton | b709df3 | 2000-09-01 02:47:25 +0000 | [diff] [blame] | 74 | static int debug; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 75 |  | 
| Tim Peters | 6fc13d9 | 2002-07-02 18:12:35 +0000 | [diff] [blame] | 76 | /*-------------------------------------------------------------------------- | 
 | 77 | gc_refs values. | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 78 |  | 
| Tim Peters | 6fc13d9 | 2002-07-02 18:12:35 +0000 | [diff] [blame] | 79 | Between collections, every gc'ed object has one of two gc_refs values: | 
 | 80 |  | 
 | 81 | GC_UNTRACKED | 
 | 82 |     The initial state; objects returned by PyObject_GC_Malloc are in this | 
 | 83 |     state.  The object doesn't live in any generation list, and its | 
 | 84 |     tp_traverse slot must not be called. | 
 | 85 |  | 
 | 86 | GC_REACHABLE | 
 | 87 |     The object lives in some generation list, and its tp_traverse is safe to | 
 | 88 |     call.  An object transitions to GC_REACHABLE when PyObject_GC_Track | 
 | 89 |     is called. | 
 | 90 |  | 
 | 91 | During a collection, gc_refs can temporarily take on other states: | 
 | 92 |  | 
 | 93 | >= 0 | 
 | 94 |     At the start of a collection, update_refs() copies the true refcount | 
 | 95 |     to gc_refs, for each object in the generation being collected. | 
 | 96 |     subtract_refs() then adjusts gc_refs so that it equals the number of | 
 | 97 |     times an object is referenced directly from outside the generation | 
 | 98 |     being collected. | 
 | 99 |     gc_refs reamins >= 0 throughout these steps. | 
 | 100 |  | 
 | 101 | GC_TENTATIVELY_UNREACHABLE | 
 | 102 |     move_unreachable() then moves objects not reachable (whether directly or | 
 | 103 |     indirectly) from outside the generation into an "unreachable" set. | 
 | 104 |     Objects that are found to be reachable have gc_refs set to GC_REACHABLE | 
 | 105 |     again.  Objects that are found to be unreachable have gc_refs set to | 
 | 106 |     GC_TENTATIVELY_UNREACHABLE.  It's "tentatively" because the pass doing | 
 | 107 |     this can't be sure until it ends, and GC_TENTATIVELY_UNREACHABLE may | 
 | 108 |     transition back to GC_REACHABLE. | 
 | 109 |  | 
 | 110 |     Only objects with GC_TENTATIVELY_UNREACHABLE still set are candidates | 
 | 111 |     for collection.  If it's decided not to collect such an object (e.g., | 
 | 112 |     it has a __del__ method), its gc_refs is restored to GC_REACHABLE again. | 
 | 113 | ---------------------------------------------------------------------------- | 
 | 114 | */ | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 115 | #define GC_UNTRACKED			_PyGC_REFS_UNTRACKED | 
 | 116 | #define GC_REACHABLE			_PyGC_REFS_REACHABLE | 
 | 117 | #define GC_TENTATIVELY_UNREACHABLE	_PyGC_REFS_TENTATIVELY_UNREACHABLE | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 118 |  | 
| Tim Peters | 6fc13d9 | 2002-07-02 18:12:35 +0000 | [diff] [blame] | 119 | #define IS_TRACKED(o) ((AS_GC(o))->gc.gc_refs != GC_UNTRACKED) | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 120 | #define IS_REACHABLE(o) ((AS_GC(o))->gc.gc_refs == GC_REACHABLE) | 
 | 121 | #define IS_TENTATIVELY_UNREACHABLE(o) ( \ | 
 | 122 | 	(AS_GC(o))->gc.gc_refs == GC_TENTATIVELY_UNREACHABLE) | 
| Neil Schemenauer | a2b11ec | 2002-05-21 15:53:24 +0000 | [diff] [blame] | 123 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 124 | /*** list functions ***/ | 
 | 125 |  | 
 | 126 | static void | 
 | 127 | gc_list_init(PyGC_Head *list) | 
 | 128 | { | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 129 | 	list->gc.gc_prev = list; | 
 | 130 | 	list->gc.gc_next = list; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 131 | } | 
 | 132 |  | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 133 | static int | 
 | 134 | gc_list_is_empty(PyGC_Head *list) | 
 | 135 | { | 
 | 136 | 	return (list->gc.gc_next == list); | 
 | 137 | } | 
 | 138 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 139 | static void | 
 | 140 | gc_list_append(PyGC_Head *node, PyGC_Head *list) | 
 | 141 | { | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 142 | 	node->gc.gc_next = list; | 
 | 143 | 	node->gc.gc_prev = list->gc.gc_prev; | 
 | 144 | 	node->gc.gc_prev->gc.gc_next = node; | 
 | 145 | 	list->gc.gc_prev = node; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 146 | } | 
 | 147 |  | 
 | 148 | static void | 
 | 149 | gc_list_remove(PyGC_Head *node) | 
 | 150 | { | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 151 | 	node->gc.gc_prev->gc.gc_next = node->gc.gc_next; | 
 | 152 | 	node->gc.gc_next->gc.gc_prev = node->gc.gc_prev; | 
 | 153 | 	node->gc.gc_next = NULL; /* object is not currently tracked */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 154 | } | 
 | 155 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 156 | /* append a list onto another list, from becomes an empty list */ | 
 | 157 | static void | 
 | 158 | gc_list_merge(PyGC_Head *from, PyGC_Head *to) | 
 | 159 | { | 
 | 160 | 	PyGC_Head *tail; | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 161 | 	if (!gc_list_is_empty(from)) { | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 162 | 		tail = to->gc.gc_prev; | 
 | 163 | 		tail->gc.gc_next = from->gc.gc_next; | 
 | 164 | 		tail->gc.gc_next->gc.gc_prev = tail; | 
 | 165 | 		to->gc.gc_prev = from->gc.gc_prev; | 
 | 166 | 		to->gc.gc_prev->gc.gc_next = to; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 167 | 	} | 
 | 168 | 	gc_list_init(from); | 
 | 169 | } | 
 | 170 |  | 
 | 171 | static long | 
 | 172 | gc_list_size(PyGC_Head *list) | 
 | 173 | { | 
 | 174 | 	PyGC_Head *gc; | 
 | 175 | 	long n = 0; | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 176 | 	for (gc = list->gc.gc_next; gc != list; gc = gc->gc.gc_next) { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 177 | 		n++; | 
 | 178 | 	} | 
 | 179 | 	return n; | 
 | 180 | } | 
 | 181 |  | 
 | 182 | /*** end of list stuff ***/ | 
 | 183 |  | 
 | 184 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 185 | /* Set all gc_refs = ob_refcnt.  After this, gc_refs is > 0 for all objects | 
 | 186 |  * in containers, and is GC_REACHABLE for all tracked gc objects not in | 
 | 187 |  * containers. | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 188 |  */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 189 | static void | 
 | 190 | update_refs(PyGC_Head *containers) | 
 | 191 | { | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 192 | 	PyGC_Head *gc = containers->gc.gc_next; | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 193 | 	for (; gc != containers; gc = gc->gc.gc_next) { | 
 | 194 | 		assert(gc->gc.gc_refs == GC_REACHABLE); | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 195 | 		gc->gc.gc_refs = FROM_GC(gc)->ob_refcnt; | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 196 | 	} | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 197 | } | 
 | 198 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 199 | /* A traversal callback for subtract_refs. */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 200 | static int | 
 | 201 | visit_decref(PyObject *op, void *data) | 
 | 202 | { | 
| Tim Peters | 93cd83e | 2002-06-30 21:31:03 +0000 | [diff] [blame] | 203 |         assert(op != NULL); | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 204 | 	if (PyObject_IS_GC(op)) { | 
 | 205 | 		PyGC_Head *gc = AS_GC(op); | 
 | 206 | 		/* We're only interested in gc_refs for objects in the | 
 | 207 | 		 * generation being collected, which can be recognized | 
 | 208 | 		 * because only they have positive gc_refs. | 
 | 209 | 		 */ | 
| Tim Peters | aab713b | 2002-07-02 22:15:28 +0000 | [diff] [blame] | 210 | 		assert(gc->gc.gc_refs != 0); /* else refcount was too small */ | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 211 | 		if (gc->gc.gc_refs > 0) | 
 | 212 | 			gc->gc.gc_refs--; | 
 | 213 | 	} | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 214 | 	return 0; | 
 | 215 | } | 
 | 216 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 217 | /* Subtract internal references from gc_refs.  After this, gc_refs is >= 0 | 
 | 218 |  * for all objects in containers, and is GC_REACHABLE for all tracked gc | 
 | 219 |  * objects not in containers.  The ones with gc_refs > 0 are directly | 
 | 220 |  * reachable from outside containers, and so can't be collected. | 
 | 221 |  */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 222 | static void | 
 | 223 | subtract_refs(PyGC_Head *containers) | 
 | 224 | { | 
 | 225 | 	traverseproc traverse; | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 226 | 	PyGC_Head *gc = containers->gc.gc_next; | 
 | 227 | 	for (; gc != containers; gc=gc->gc.gc_next) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 228 | 		traverse = FROM_GC(gc)->ob_type->tp_traverse; | 
 | 229 | 		(void) traverse(FROM_GC(gc), | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 230 | 			       (visitproc)visit_decref, | 
 | 231 | 			       NULL); | 
 | 232 | 	} | 
 | 233 | } | 
 | 234 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 235 | /* A traversal callback for move_unreachable. */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 236 | static int | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 237 | visit_reachable(PyObject *op, PyGC_Head *reachable) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 238 | { | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 239 | 	if (PyObject_IS_GC(op)) { | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 240 | 		PyGC_Head *gc = AS_GC(op); | 
 | 241 | 		const int gc_refs = gc->gc.gc_refs; | 
 | 242 |  | 
 | 243 | 		if (gc_refs == 0) { | 
 | 244 | 			/* This is in move_unreachable's 'young' list, but | 
 | 245 | 			 * the traversal hasn't yet gotten to it.  All | 
 | 246 | 			 * we need to do is tell move_unreachable that it's | 
 | 247 | 			 * reachable. | 
 | 248 | 			 */ | 
 | 249 | 			gc->gc.gc_refs = 1; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 250 | 		} | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 251 | 		else if (gc_refs == GC_TENTATIVELY_UNREACHABLE) { | 
 | 252 | 			/* This had gc_refs = 0 when move_unreachable got | 
 | 253 | 			 * to it, but turns out it's reachable after all. | 
 | 254 | 			 * Move it back to move_unreachable's 'young' list, | 
 | 255 | 			 * and move_unreachable will eventually get to it | 
 | 256 | 			 * again. | 
 | 257 | 			 */ | 
 | 258 | 			gc_list_remove(gc); | 
 | 259 | 			gc_list_append(gc, reachable); | 
 | 260 | 			gc->gc.gc_refs = 1; | 
 | 261 | 		} | 
 | 262 | 		/* Else there's nothing to do. | 
 | 263 | 		 * If gc_refs > 0, it must be in move_unreachable's 'young' | 
 | 264 | 		 * list, and move_unreachable will eventually get to it. | 
 | 265 | 		 * If gc_refs == GC_REACHABLE, it's either in some other | 
 | 266 | 		 * generation so we don't care about it, or move_unreachable | 
| Tim Peters | 6fc13d9 | 2002-07-02 18:12:35 +0000 | [diff] [blame] | 267 | 		 * already dealt with it. | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 268 | 		 * If gc_refs == GC_UNTRACKED, it must be ignored. | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 269 | 		 */ | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 270 | 		 else { | 
 | 271 | 		 	assert(gc_refs > 0 | 
 | 272 | 		 	       || gc_refs == GC_REACHABLE | 
 | 273 | 		 	       || gc_refs == GC_UNTRACKED); | 
 | 274 | 		 } | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 275 | 	} | 
 | 276 | 	return 0; | 
 | 277 | } | 
 | 278 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 279 | /* Move the unreachable objects from young to unreachable.  After this, | 
 | 280 |  * all objects in young have gc_refs = GC_REACHABLE, and all objects in | 
 | 281 |  * unreachable have gc_refs = GC_TENTATIVELY_UNREACHABLE.  All tracked | 
 | 282 |  * gc objects not in young or unreachable still have gc_refs = GC_REACHABLE. | 
 | 283 |  * All objects in young after this are directly or indirectly reachable | 
 | 284 |  * from outside the original young; and all objects in unreachable are | 
 | 285 |  * not. | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 286 |  */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 287 | static void | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 288 | move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 289 | { | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 290 | 	PyGC_Head *gc = young->gc.gc_next; | 
 | 291 |  | 
 | 292 | 	/* Invariants:  all objects "to the left" of us in young have gc_refs | 
 | 293 | 	 * = GC_REACHABLE, and are indeed reachable (directly or indirectly) | 
 | 294 | 	 * from outside the young list as it was at entry.  All other objects | 
 | 295 | 	 * from the original young "to the left" of us are in unreachable now, | 
 | 296 | 	 * and have gc_refs = GC_TENTATIVELY_UNREACHABLE.  All objects to the | 
 | 297 | 	 * left of us in 'young' now have been scanned, and no objects here | 
 | 298 | 	 * or to the right have been scanned yet. | 
 | 299 | 	 */ | 
 | 300 |  | 
 | 301 | 	while (gc != young) { | 
 | 302 | 		PyGC_Head *next; | 
 | 303 |  | 
| Tim Peters | 6fc13d9 | 2002-07-02 18:12:35 +0000 | [diff] [blame] | 304 | 		if (gc->gc.gc_refs) { | 
 | 305 |                         /* gc is definitely reachable from outside the | 
 | 306 |                          * original 'young'.  Mark it as such, and traverse | 
 | 307 |                          * its pointers to find any other objects that may | 
 | 308 |                          * be directly reachable from it.  Note that the | 
 | 309 |                          * call to tp_traverse may append objects to young, | 
 | 310 |                          * so we have to wait until it returns to determine | 
 | 311 |                          * the next object to visit. | 
 | 312 |                          */ | 
 | 313 |                         PyObject *op = FROM_GC(gc); | 
 | 314 |                         traverseproc traverse = op->ob_type->tp_traverse; | 
 | 315 |                         assert(gc->gc.gc_refs > 0); | 
 | 316 |                         gc->gc.gc_refs = GC_REACHABLE; | 
 | 317 |                         (void) traverse(op, | 
 | 318 |                                         (visitproc)visit_reachable, | 
 | 319 |                                         (void *)young); | 
 | 320 |                         next = gc->gc.gc_next; | 
 | 321 | 		} | 
 | 322 | 		else { | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 323 | 			/* This *may* be unreachable.  To make progress, | 
 | 324 | 			 * assume it is.  gc isn't directly reachable from | 
 | 325 | 			 * any object we've already traversed, but may be | 
 | 326 | 			 * reachable from an object we haven't gotten to yet. | 
 | 327 | 			 * visit_reachable will eventually move gc back into | 
 | 328 | 			 * young if that's so, and we'll see it again. | 
 | 329 | 			 */ | 
 | 330 | 			next = gc->gc.gc_next; | 
 | 331 | 			gc_list_remove(gc); | 
 | 332 | 			gc_list_append(gc, unreachable); | 
 | 333 | 			gc->gc.gc_refs = GC_TENTATIVELY_UNREACHABLE; | 
 | 334 | 		} | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 335 | 		gc = next; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 336 | 	} | 
 | 337 | } | 
 | 338 |  | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 339 | /* return true if object has a finalization method */ | 
| Neil Schemenauer | a765c12 | 2001-11-01 17:35:23 +0000 | [diff] [blame] | 340 | static int | 
 | 341 | has_finalizer(PyObject *op) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 342 | { | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 343 | 	static PyObject *delstr = NULL; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 344 | 	if (delstr == NULL) { | 
 | 345 | 		delstr = PyString_InternFromString("__del__"); | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 346 | 		if (delstr == NULL) | 
 | 347 | 			Py_FatalError("PyGC: can't initialize __del__ string"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 348 | 	} | 
| Tim Peters | db86561 | 2001-11-01 19:35:45 +0000 | [diff] [blame] | 349 | 	return (PyInstance_Check(op) || | 
 | 350 | 	        PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE)) | 
 | 351 | 	       && PyObject_HasAttr(op, delstr); | 
| Neil Schemenauer | a765c12 | 2001-11-01 17:35:23 +0000 | [diff] [blame] | 352 | } | 
 | 353 |  | 
 | 354 | /* Move all objects with finalizers (instances with __del__) */ | 
 | 355 | static void | 
 | 356 | move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) | 
 | 357 | { | 
 | 358 | 	PyGC_Head *next; | 
 | 359 | 	PyGC_Head *gc = unreachable->gc.gc_next; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 360 | 	for (; gc != unreachable; gc=next) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 361 | 		PyObject *op = FROM_GC(gc); | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 362 | 		next = gc->gc.gc_next; | 
| Neil Schemenauer | a765c12 | 2001-11-01 17:35:23 +0000 | [diff] [blame] | 363 | 		if (has_finalizer(op)) { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 364 | 			gc_list_remove(gc); | 
 | 365 | 			gc_list_append(gc, finalizers); | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 366 | 			gc->gc.gc_refs = GC_REACHABLE; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 367 | 		} | 
 | 368 | 	} | 
 | 369 | } | 
 | 370 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 371 | /* A traversal callback for move_finalizer_reachable. */ | 
 | 372 | static int | 
 | 373 | visit_move(PyObject *op, PyGC_Head *tolist) | 
 | 374 | { | 
 | 375 | 	if (PyObject_IS_GC(op)) { | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 376 | 		if (IS_TENTATIVELY_UNREACHABLE(op)) { | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 377 | 			PyGC_Head *gc = AS_GC(op); | 
 | 378 | 			gc_list_remove(gc); | 
 | 379 | 			gc_list_append(gc, tolist); | 
 | 380 | 			gc->gc.gc_refs = GC_REACHABLE; | 
 | 381 | 		} | 
 | 382 | 	} | 
 | 383 | 	return 0; | 
 | 384 | } | 
 | 385 |  | 
 | 386 | /* Move objects that are reachable from finalizers, from the unreachable set | 
 | 387 |  * into the finalizers set. | 
 | 388 |  */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 389 | static void | 
 | 390 | move_finalizer_reachable(PyGC_Head *finalizers) | 
 | 391 | { | 
 | 392 | 	traverseproc traverse; | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 393 | 	PyGC_Head *gc = finalizers->gc.gc_next; | 
 | 394 | 	for (; gc != finalizers; gc=gc->gc.gc_next) { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 395 | 		/* careful, finalizers list is growing here */ | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 396 | 		traverse = FROM_GC(gc)->ob_type->tp_traverse; | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 397 | 		(void) traverse(FROM_GC(gc), | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 398 | 			       (visitproc)visit_move, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 399 | 			       (void *)finalizers); | 
 | 400 | 	} | 
 | 401 | } | 
 | 402 |  | 
 | 403 | static void | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 404 | debug_instance(char *msg, PyInstanceObject *inst) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 405 | { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 406 | 	char *cname; | 
| Neil Schemenauer | a765c12 | 2001-11-01 17:35:23 +0000 | [diff] [blame] | 407 | 	/* simple version of instance_repr */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 408 | 	PyObject *classname = inst->in_class->cl_name; | 
 | 409 | 	if (classname != NULL && PyString_Check(classname)) | 
 | 410 | 		cname = PyString_AsString(classname); | 
 | 411 | 	else | 
 | 412 | 		cname = "?"; | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 413 | 	PySys_WriteStderr("gc: %.100s <%.100s instance at %p>\n", | 
 | 414 | 			  msg, cname, inst); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 415 | } | 
 | 416 |  | 
 | 417 | static void | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 418 | debug_cycle(char *msg, PyObject *op) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 419 | { | 
 | 420 | 	if ((debug & DEBUG_INSTANCES) && PyInstance_Check(op)) { | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 421 | 		debug_instance(msg, (PyInstanceObject *)op); | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 422 | 	} | 
 | 423 | 	else if (debug & DEBUG_OBJECTS) { | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 424 | 		PySys_WriteStderr("gc: %.100s <%.100s %p>\n", | 
 | 425 | 				  msg, op->ob_type->tp_name, op); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 426 | 	} | 
 | 427 | } | 
 | 428 |  | 
 | 429 | /* Handle uncollectable garbage (cycles with finalizers). */ | 
 | 430 | static void | 
 | 431 | handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old) | 
 | 432 | { | 
 | 433 | 	PyGC_Head *gc; | 
 | 434 | 	if (garbage == NULL) { | 
 | 435 | 		garbage = PyList_New(0); | 
 | 436 | 	} | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 437 | 	for (gc = finalizers->gc.gc_next; gc != finalizers; | 
 | 438 | 			gc = finalizers->gc.gc_next) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 439 | 		PyObject *op = FROM_GC(gc); | 
| Neil Schemenauer | a765c12 | 2001-11-01 17:35:23 +0000 | [diff] [blame] | 440 | 		if ((debug & DEBUG_SAVEALL) || has_finalizer(op)) { | 
 | 441 | 			/* If SAVEALL is not set then just append objects with | 
 | 442 | 			 * finalizers to the list of garbage.  All objects in | 
 | 443 | 			 * the finalizers list are reachable from those | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 444 | 			 * objects. | 
 | 445 | 			 */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 446 | 			PyList_Append(garbage, op); | 
 | 447 | 		} | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 448 | 		/* object is now reachable again */ | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 449 | 		assert(IS_REACHABLE(op)); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 450 | 		gc_list_remove(gc); | 
 | 451 | 		gc_list_append(gc, old); | 
 | 452 | 	} | 
 | 453 | } | 
 | 454 |  | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 455 | /* Break reference cycles by clearing the containers involved.	This is | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 456 |  * tricky business as the lists can be changing and we don't know which | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 457 |  * objects may be freed.  It is possible I screwed something up here. | 
 | 458 |  */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 459 | static void | 
 | 460 | delete_garbage(PyGC_Head *unreachable, PyGC_Head *old) | 
 | 461 | { | 
 | 462 | 	inquiry clear; | 
 | 463 |  | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 464 | 	while (!gc_list_is_empty(unreachable)) { | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 465 | 		PyGC_Head *gc = unreachable->gc.gc_next; | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 466 | 		PyObject *op = FROM_GC(gc); | 
| Tim Peters | 8839617 | 2002-06-30 17:56:40 +0000 | [diff] [blame] | 467 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 468 | 		assert(IS_TENTATIVELY_UNREACHABLE(op)); | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 469 | 		if (debug & DEBUG_SAVEALL) { | 
 | 470 | 			PyList_Append(garbage, op); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 471 | 		} | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 472 | 		else { | 
 | 473 | 			if ((clear = op->ob_type->tp_clear) != NULL) { | 
 | 474 | 				Py_INCREF(op); | 
| Jeremy Hylton | 8a13518 | 2002-06-06 23:23:55 +0000 | [diff] [blame] | 475 | 				clear(op); | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 476 | 				Py_DECREF(op); | 
 | 477 | 			} | 
 | 478 | 		} | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 479 | 		if (unreachable->gc.gc_next == gc) { | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 480 | 			/* object is still alive, move it, it may die later */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 481 | 			gc_list_remove(gc); | 
 | 482 | 			gc_list_append(gc, old); | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 483 | 			gc->gc.gc_refs = GC_REACHABLE; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 484 | 		} | 
 | 485 | 	} | 
 | 486 | } | 
 | 487 |  | 
 | 488 | /* This is the main function.  Read this to understand how the | 
 | 489 |  * collection process works. */ | 
 | 490 | static long | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 491 | collect(int generation) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 492 | { | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 493 | 	int i; | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 494 | 	long m = 0;	/* # objects collected */ | 
 | 495 | 	long n = 0;	/* # unreachable objects that couldn't be collected */ | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 496 | 	PyGC_Head *young; /* the generation we are examining */ | 
 | 497 | 	PyGC_Head *old; /* next older generation */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 498 | 	PyGC_Head unreachable; | 
 | 499 | 	PyGC_Head finalizers; | 
 | 500 | 	PyGC_Head *gc; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 501 |  | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 502 | 	if (debug & DEBUG_STATS) { | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 503 | 		PySys_WriteStderr("gc: collecting generation %d...\n", | 
 | 504 | 				  generation); | 
 | 505 | 		PySys_WriteStderr("gc: objects in each generation:"); | 
 | 506 | 		for (i = 0; i < NUM_GENERATIONS; i++) { | 
 | 507 | 			PySys_WriteStderr(" %ld", gc_list_size(GEN_HEAD(i))); | 
 | 508 | 		} | 
 | 509 | 		PySys_WriteStderr("\n"); | 
 | 510 | 	} | 
 | 511 |  | 
 | 512 | 	/* update collection and allocation counters */ | 
 | 513 | 	if (generation+1 < NUM_GENERATIONS) | 
 | 514 | 		generations[generation+1].count += 1; | 
 | 515 | 	for (i = 0; i <= generation; i++) | 
| Neil Schemenauer | c905164 | 2002-06-28 19:16:04 +0000 | [diff] [blame] | 516 | 		generations[i].count = 0; | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 517 |  | 
 | 518 | 	/* merge younger generations with one we are currently collecting */ | 
 | 519 | 	for (i = 0; i < generation; i++) { | 
 | 520 | 		gc_list_merge(GEN_HEAD(i), GEN_HEAD(generation)); | 
 | 521 | 	} | 
 | 522 |  | 
 | 523 | 	/* handy references */ | 
 | 524 | 	young = GEN_HEAD(generation); | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 525 | 	if (generation < NUM_GENERATIONS-1) | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 526 | 		old = GEN_HEAD(generation+1); | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 527 | 	else | 
 | 528 | 		old = young; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 529 |  | 
 | 530 | 	/* Using ob_refcnt and gc_refs, calculate which objects in the | 
 | 531 | 	 * container set are reachable from outside the set (ie. have a | 
 | 532 | 	 * refcount greater than 0 when all the references within the | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 533 | 	 * set are taken into account | 
 | 534 | 	 */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 535 | 	update_refs(young); | 
 | 536 | 	subtract_refs(young); | 
 | 537 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 538 | 	/* Leave everything reachable from outside young in young, and move | 
 | 539 | 	 * everything else (in young) to unreachable. | 
 | 540 | 	 * NOTE:  This used to move the reachable objects into a reachable | 
 | 541 | 	 * set instead.  But most things usually turn out to be reachable, | 
 | 542 | 	 * so it's more efficient to move the unreachable things. | 
 | 543 | 	 */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 544 | 	gc_list_init(&unreachable); | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 545 | 	move_unreachable(young, &unreachable); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 546 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 547 | 	/* Move reachable objects to next generation. */ | 
 | 548 | 	if (young != old) | 
 | 549 | 		gc_list_merge(young, old); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 550 |  | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 551 | 	/* All objects in unreachable are trash, but objects reachable from | 
 | 552 | 	 * finalizers can't safely be deleted.  Python programmers should take | 
 | 553 | 	 * care not to create such things.  For Python, finalizers means | 
 | 554 | 	 * instance objects with __del__ methods. | 
 | 555 | 	 */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 556 | 	gc_list_init(&finalizers); | 
 | 557 | 	move_finalizers(&unreachable, &finalizers); | 
 | 558 | 	move_finalizer_reachable(&finalizers); | 
 | 559 |  | 
 | 560 | 	/* Collect statistics on collectable objects found and print | 
 | 561 | 	 * debugging information. */ | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 562 | 	for (gc = unreachable.gc.gc_next; gc != &unreachable; | 
 | 563 | 			gc = gc->gc.gc_next) { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 564 | 		m++; | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 565 | 		if (debug & DEBUG_COLLECTABLE) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 566 | 			debug_cycle("collectable", FROM_GC(gc)); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 567 | 		} | 
 | 568 | 	} | 
| Tim Peters | 19b74c7 | 2002-07-01 03:52:19 +0000 | [diff] [blame] | 569 | 	/* Call tp_clear on objects in the collectable set.  This will cause | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 570 | 	 * the reference cycles to be broken. It may also cause some objects in | 
 | 571 | 	 * finalizers to be freed */ | 
 | 572 | 	delete_garbage(&unreachable, old); | 
 | 573 |  | 
 | 574 | 	/* Collect statistics on uncollectable objects found and print | 
 | 575 | 	 * debugging information. */ | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 576 | 	for (gc = finalizers.gc.gc_next; gc != &finalizers; | 
 | 577 | 			gc = gc->gc.gc_next) { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 578 | 		n++; | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 579 | 		if (debug & DEBUG_UNCOLLECTABLE) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 580 | 			debug_cycle("uncollectable", FROM_GC(gc)); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 581 | 		} | 
 | 582 | 	} | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 583 | 	if (debug & DEBUG_STATS) { | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 584 | 		if (m == 0 && n == 0) { | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 585 | 			PySys_WriteStderr("gc: done.\n"); | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 586 | 		} | 
 | 587 | 		else { | 
| Jeremy Hylton | 0625777 | 2000-08-31 15:10:24 +0000 | [diff] [blame] | 588 | 			PySys_WriteStderr( | 
 | 589 | 			    "gc: done, %ld unreachable, %ld uncollectable.\n", | 
 | 590 | 			    n+m, n); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 591 | 		} | 
 | 592 | 	} | 
 | 593 |  | 
 | 594 | 	/* Append instances in the uncollectable set to a Python | 
 | 595 | 	 * reachable list of garbage.  The programmer has to deal with | 
 | 596 | 	 * this if they insist on creating this type of structure. */ | 
 | 597 | 	handle_finalizers(&finalizers, old); | 
 | 598 |  | 
| Jeremy Hylton | b709df3 | 2000-09-01 02:47:25 +0000 | [diff] [blame] | 599 | 	if (PyErr_Occurred()) { | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 600 | 		if (gc_str == NULL) { | 
 | 601 | 		    gc_str = PyString_FromString("garbage collection"); | 
 | 602 | 		} | 
| Jeremy Hylton | b709df3 | 2000-09-01 02:47:25 +0000 | [diff] [blame] | 603 | 		PyErr_WriteUnraisable(gc_str); | 
 | 604 | 		Py_FatalError("unexpected exception during garbage collection"); | 
 | 605 | 	} | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 606 | 	return n+m; | 
 | 607 | } | 
 | 608 |  | 
 | 609 | static long | 
 | 610 | collect_generations(void) | 
 | 611 | { | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 612 | 	int i; | 
| Vladimir Marangozov | b16714b | 2000-07-10 05:37:39 +0000 | [diff] [blame] | 613 | 	long n = 0; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 614 |  | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 615 | 	/* Find the oldest generation (higest numbered) where the count | 
 | 616 | 	 * exceeds the threshold.  Objects in the that generation and | 
 | 617 | 	 * generations younger than it will be collected. */ | 
 | 618 | 	for (i = NUM_GENERATIONS-1; i >= 0; i--) { | 
 | 619 | 		if (generations[i].count > generations[i].threshold) { | 
 | 620 | 			n = collect(i); | 
 | 621 | 			break; | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 622 | 		} | 
 | 623 | 	} | 
 | 624 | 	return n; | 
 | 625 | } | 
 | 626 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 627 | PyDoc_STRVAR(gc_enable__doc__, | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 628 | "enable() -> None\n" | 
 | 629 | "\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 630 | "Enable automatic garbage collection.\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 631 |  | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 632 | static PyObject * | 
 | 633 | gc_enable(PyObject *self, PyObject *args) | 
 | 634 | { | 
 | 635 |  | 
 | 636 | 	if (!PyArg_ParseTuple(args, ":enable"))	/* check no args */ | 
 | 637 | 		return NULL; | 
 | 638 |  | 
 | 639 | 	enabled = 1; | 
 | 640 |  | 
 | 641 | 	Py_INCREF(Py_None); | 
 | 642 | 	return Py_None; | 
 | 643 | } | 
 | 644 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 645 | PyDoc_STRVAR(gc_disable__doc__, | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 646 | "disable() -> None\n" | 
 | 647 | "\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 648 | "Disable automatic garbage collection.\n"); | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 649 |  | 
 | 650 | static PyObject * | 
 | 651 | gc_disable(PyObject *self, PyObject *args) | 
 | 652 | { | 
 | 653 |  | 
 | 654 | 	if (!PyArg_ParseTuple(args, ":disable"))	/* check no args */ | 
 | 655 | 		return NULL; | 
 | 656 |  | 
 | 657 | 	enabled = 0; | 
 | 658 |  | 
 | 659 | 	Py_INCREF(Py_None); | 
 | 660 | 	return Py_None; | 
 | 661 | } | 
 | 662 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 663 | PyDoc_STRVAR(gc_isenabled__doc__, | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 664 | "isenabled() -> status\n" | 
 | 665 | "\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 666 | "Returns true if automatic garbage collection is enabled.\n"); | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 667 |  | 
 | 668 | static PyObject * | 
 | 669 | gc_isenabled(PyObject *self, PyObject *args) | 
 | 670 | { | 
 | 671 |  | 
 | 672 | 	if (!PyArg_ParseTuple(args, ":isenabled"))	/* check no args */ | 
 | 673 | 		return NULL; | 
 | 674 |  | 
 | 675 | 	return Py_BuildValue("i", enabled); | 
 | 676 | } | 
 | 677 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 678 | PyDoc_STRVAR(gc_collect__doc__, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 679 | "collect() -> n\n" | 
 | 680 | "\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 681 | "Run a full collection.  The number of unreachable objects is returned.\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 682 |  | 
 | 683 | static PyObject * | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 684 | gc_collect(PyObject *self, PyObject *args) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 685 | { | 
 | 686 | 	long n; | 
 | 687 |  | 
| Fred Drake | cc1be24 | 2000-07-12 04:42:23 +0000 | [diff] [blame] | 688 | 	if (!PyArg_ParseTuple(args, ":collect"))	/* check no args */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 689 | 		return NULL; | 
 | 690 |  | 
| Neil Schemenauer | e8c40cb | 2001-10-31 23:09:35 +0000 | [diff] [blame] | 691 | 	if (collecting) { | 
 | 692 | 		n = 0; /* already collecting, don't do anything */ | 
 | 693 | 	} | 
 | 694 | 	else { | 
 | 695 | 		collecting = 1; | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 696 | 		n = collect(NUM_GENERATIONS - 1); | 
| Neil Schemenauer | e8c40cb | 2001-10-31 23:09:35 +0000 | [diff] [blame] | 697 | 		collecting = 0; | 
 | 698 | 	} | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 699 |  | 
| Neil Schemenauer | 7760cff | 2000-09-22 22:35:36 +0000 | [diff] [blame] | 700 | 	return Py_BuildValue("l", n); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 701 | } | 
 | 702 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 703 | PyDoc_STRVAR(gc_set_debug__doc__, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 704 | "set_debug(flags) -> None\n" | 
 | 705 | "\n" | 
 | 706 | "Set the garbage collection debugging flags. Debugging information is\n" | 
 | 707 | "written to sys.stderr.\n" | 
 | 708 | "\n" | 
 | 709 | "flags is an integer and can have the following bits turned on:\n" | 
 | 710 | "\n" | 
 | 711 | "  DEBUG_STATS - Print statistics during collection.\n" | 
 | 712 | "  DEBUG_COLLECTABLE - Print collectable objects found.\n" | 
 | 713 | "  DEBUG_UNCOLLECTABLE - Print unreachable but uncollectable objects found.\n" | 
 | 714 | "  DEBUG_INSTANCES - Print instance objects.\n" | 
 | 715 | "  DEBUG_OBJECTS - Print objects other than instances.\n" | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 716 | "  DEBUG_SAVEALL - Save objects to gc.garbage rather than freeing them.\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 717 | "  DEBUG_LEAK - Debug leaking programs (everything but STATS).\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 718 |  | 
 | 719 | static PyObject * | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 720 | gc_set_debug(PyObject *self, PyObject *args) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 721 | { | 
| Neil Schemenauer | 7760cff | 2000-09-22 22:35:36 +0000 | [diff] [blame] | 722 | 	if (!PyArg_ParseTuple(args, "i:set_debug", &debug)) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 723 | 		return NULL; | 
 | 724 |  | 
 | 725 | 	Py_INCREF(Py_None); | 
 | 726 | 	return Py_None; | 
 | 727 | } | 
 | 728 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 729 | PyDoc_STRVAR(gc_get_debug__doc__, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 730 | "get_debug() -> flags\n" | 
 | 731 | "\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 732 | "Get the garbage collection debugging flags.\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 733 |  | 
 | 734 | static PyObject * | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 735 | gc_get_debug(PyObject *self, PyObject *args) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 736 | { | 
| Fred Drake | cc1be24 | 2000-07-12 04:42:23 +0000 | [diff] [blame] | 737 | 	if (!PyArg_ParseTuple(args, ":get_debug"))	/* no args */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 738 | 		return NULL; | 
 | 739 |  | 
 | 740 | 	return Py_BuildValue("i", debug); | 
 | 741 | } | 
 | 742 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 743 | PyDoc_STRVAR(gc_set_thresh__doc__, | 
| Neal Norwitz | 2a47c0f | 2002-01-29 00:53:41 +0000 | [diff] [blame] | 744 | "set_threshold(threshold0, [threshold1, threshold2]) -> None\n" | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 745 | "\n" | 
 | 746 | "Sets the collection thresholds.  Setting threshold0 to zero disables\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 747 | "collection.\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 748 |  | 
 | 749 | static PyObject * | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 750 | gc_set_thresh(PyObject *self, PyObject *args) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 751 | { | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 752 | 	int i; | 
 | 753 | 	if (!PyArg_ParseTuple(args, "i|ii:set_threshold", | 
 | 754 | 			      &generations[0].threshold, | 
 | 755 | 			      &generations[1].threshold, | 
 | 756 | 			      &generations[2].threshold)) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 757 | 		return NULL; | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 758 | 	for (i = 2; i < NUM_GENERATIONS; i++) { | 
 | 759 |  		/* generations higher than 2 get the same threshold */ | 
 | 760 | 		generations[i].threshold = generations[2].threshold; | 
 | 761 | 	} | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 762 |  | 
 | 763 | 	Py_INCREF(Py_None); | 
 | 764 | 	return Py_None; | 
 | 765 | } | 
 | 766 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 767 | PyDoc_STRVAR(gc_get_thresh__doc__, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 768 | "get_threshold() -> (threshold0, threshold1, threshold2)\n" | 
 | 769 | "\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 770 | "Return the current collection thresholds\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 771 |  | 
 | 772 | static PyObject * | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 773 | gc_get_thresh(PyObject *self, PyObject *args) | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 774 | { | 
| Fred Drake | cc1be24 | 2000-07-12 04:42:23 +0000 | [diff] [blame] | 775 | 	if (!PyArg_ParseTuple(args, ":get_threshold"))	/* no args */ | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 776 | 		return NULL; | 
 | 777 |  | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 778 | 	return Py_BuildValue("(iii)", | 
 | 779 | 			     generations[0].threshold, | 
 | 780 | 			     generations[1].threshold, | 
 | 781 | 			     generations[2].threshold); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 782 | } | 
 | 783 |  | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 784 | static int | 
| Martin v. Löwis | 560da62 | 2001-11-24 09:24:51 +0000 | [diff] [blame] | 785 | referrersvisit(PyObject* obj, PyObject *objs) | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 786 | { | 
| Martin v. Löwis | c8fe77b | 2001-11-29 18:08:31 +0000 | [diff] [blame] | 787 | 	int i; | 
 | 788 | 	for (i = 0; i < PyTuple_GET_SIZE(objs); i++) | 
 | 789 | 		if (PyTuple_GET_ITEM(objs, i) == obj) | 
 | 790 | 			return 1; | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 791 | 	return 0; | 
 | 792 | } | 
 | 793 |  | 
| Neil Schemenauer | 17e7be6 | 2001-08-10 14:46:47 +0000 | [diff] [blame] | 794 | static int | 
| Martin v. Löwis | 560da62 | 2001-11-24 09:24:51 +0000 | [diff] [blame] | 795 | gc_referrers_for(PyObject *objs, PyGC_Head *list, PyObject *resultlist) | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 796 | { | 
 | 797 | 	PyGC_Head *gc; | 
 | 798 | 	PyObject *obj; | 
 | 799 | 	traverseproc traverse; | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 800 | 	for (gc = list->gc.gc_next; gc != list; gc = gc->gc.gc_next) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 801 | 		obj = FROM_GC(gc); | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 802 | 		traverse = obj->ob_type->tp_traverse; | 
 | 803 | 		if (obj == objs || obj == resultlist) | 
 | 804 | 			continue; | 
| Martin v. Löwis | 560da62 | 2001-11-24 09:24:51 +0000 | [diff] [blame] | 805 | 		if (traverse(obj, (visitproc)referrersvisit, objs)) { | 
| Neil Schemenauer | 17e7be6 | 2001-08-10 14:46:47 +0000 | [diff] [blame] | 806 | 			if (PyList_Append(resultlist, obj) < 0) | 
 | 807 | 				return 0; /* error */ | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 808 | 		} | 
 | 809 | 	} | 
| Neil Schemenauer | 17e7be6 | 2001-08-10 14:46:47 +0000 | [diff] [blame] | 810 | 	return 1; /* no error */ | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 811 | } | 
 | 812 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 813 | PyDoc_STRVAR(gc_get_referrers__doc__, | 
| Martin v. Löwis | 560da62 | 2001-11-24 09:24:51 +0000 | [diff] [blame] | 814 | "get_referrers(*objs) -> list\n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 815 | Return the list of objects that directly refer to any of objs."); | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 816 |  | 
| Neil Schemenauer | 17e7be6 | 2001-08-10 14:46:47 +0000 | [diff] [blame] | 817 | static PyObject * | 
| Martin v. Löwis | 560da62 | 2001-11-24 09:24:51 +0000 | [diff] [blame] | 818 | gc_get_referrers(PyObject *self, PyObject *args) | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 819 | { | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 820 | 	int i; | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 821 | 	PyObject *result = PyList_New(0); | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 822 | 	for (i = 0; i < NUM_GENERATIONS; i++) { | 
 | 823 | 		if (!(gc_referrers_for(args, GEN_HEAD(i), result))) { | 
 | 824 | 			Py_DECREF(result); | 
 | 825 | 			return NULL; | 
 | 826 | 		} | 
| Neil Schemenauer | 17e7be6 | 2001-08-10 14:46:47 +0000 | [diff] [blame] | 827 | 	} | 
| Neil Schemenauer | 48c7034 | 2001-08-09 15:38:31 +0000 | [diff] [blame] | 828 | 	return result; | 
 | 829 | } | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 830 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 831 | PyDoc_STRVAR(gc_get_objects__doc__, | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 832 | "get_objects() -> [...]\n" | 
 | 833 | "\n" | 
 | 834 | "Return a list of objects tracked by the collector (excluding the list\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 835 | "returned).\n"); | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 836 |  | 
 | 837 | /* appending objects in a GC list to a Python list */ | 
| Martin v. Löwis | 155aad1 | 2001-12-02 12:21:34 +0000 | [diff] [blame] | 838 | static int | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 839 | append_objects(PyObject *py_list, PyGC_Head *gc_list) | 
 | 840 | { | 
 | 841 | 	PyGC_Head *gc; | 
| Tim Peters | 9e4ca10 | 2001-10-11 18:31:31 +0000 | [diff] [blame] | 842 | 	for (gc = gc_list->gc.gc_next; gc != gc_list; gc = gc->gc.gc_next) { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 843 | 		PyObject *op = FROM_GC(gc); | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 844 | 		if (op != py_list) { | 
| Martin v. Löwis | 155aad1 | 2001-12-02 12:21:34 +0000 | [diff] [blame] | 845 | 			if (PyList_Append(py_list, op)) { | 
 | 846 | 				return -1; /* exception */ | 
 | 847 | 			} | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 848 | 		} | 
 | 849 | 	} | 
| Martin v. Löwis | 155aad1 | 2001-12-02 12:21:34 +0000 | [diff] [blame] | 850 | 	return 0; | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 851 | } | 
 | 852 |  | 
 | 853 | static PyObject * | 
 | 854 | gc_get_objects(PyObject *self, PyObject *args) | 
 | 855 | { | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 856 | 	int i; | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 857 | 	PyObject* result; | 
 | 858 |  | 
 | 859 | 	if (!PyArg_ParseTuple(args, ":get_objects")) /* check no args */ | 
 | 860 | 		return NULL; | 
 | 861 | 	result = PyList_New(0); | 
| Martin v. Löwis | f8a6f24 | 2001-12-02 18:31:02 +0000 | [diff] [blame] | 862 | 	if (result == NULL) { | 
 | 863 | 		return NULL; | 
 | 864 | 	} | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 865 | 	for (i = 0; i < NUM_GENERATIONS; i++) { | 
 | 866 | 		if (append_objects(result, GEN_HEAD(i))) { | 
 | 867 | 			Py_DECREF(result); | 
 | 868 | 			return NULL; | 
 | 869 | 		} | 
| Martin v. Löwis | 155aad1 | 2001-12-02 12:21:34 +0000 | [diff] [blame] | 870 | 	} | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 871 | 	return result; | 
 | 872 | } | 
 | 873 |  | 
 | 874 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 875 | PyDoc_STRVAR(gc__doc__, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 876 | "This module provides access to the garbage collector for reference cycles.\n" | 
 | 877 | "\n" | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 878 | "enable() -- Enable automatic garbage collection.\n" | 
 | 879 | "disable() -- Disable automatic garbage collection.\n" | 
 | 880 | "isenabled() -- Returns true if automatic collection is enabled.\n" | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 881 | "collect() -- Do a full collection right now.\n" | 
 | 882 | "set_debug() -- Set debugging flags.\n" | 
 | 883 | "get_debug() -- Get debugging flags.\n" | 
 | 884 | "set_threshold() -- Set the collection thresholds.\n" | 
 | 885 | "get_threshold() -- Return the current the collection thresholds.\n" | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 886 | "get_objects() -- Return a list of all objects tracked by the collector.\n" | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 887 | "get_referrers() -- Return the list of objects that refer to an object.\n"); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 888 |  | 
 | 889 | static PyMethodDef GcMethods[] = { | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 890 | 	{"enable",	   gc_enable,	  METH_VARARGS, gc_enable__doc__}, | 
 | 891 | 	{"disable",	   gc_disable,	  METH_VARARGS, gc_disable__doc__}, | 
| Vladimir Marangozov | f9d20c3 | 2000-08-06 22:45:31 +0000 | [diff] [blame] | 892 | 	{"isenabled",	   gc_isenabled,  METH_VARARGS, gc_isenabled__doc__}, | 
 | 893 | 	{"set_debug",	   gc_set_debug,  METH_VARARGS, gc_set_debug__doc__}, | 
 | 894 | 	{"get_debug",	   gc_get_debug,  METH_VARARGS, gc_get_debug__doc__}, | 
 | 895 | 	{"set_threshold",  gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__}, | 
 | 896 | 	{"get_threshold",  gc_get_thresh, METH_VARARGS, gc_get_thresh__doc__}, | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 897 | 	{"collect",	   gc_collect,	  METH_VARARGS, gc_collect__doc__}, | 
| Neil Schemenauer | c7c8d8e | 2001-08-09 15:58:59 +0000 | [diff] [blame] | 898 | 	{"get_objects",    gc_get_objects,METH_VARARGS, gc_get_objects__doc__}, | 
| Martin v. Löwis | 560da62 | 2001-11-24 09:24:51 +0000 | [diff] [blame] | 899 | 	{"get_referrers",  gc_get_referrers, METH_VARARGS, | 
 | 900 | 		gc_get_referrers__doc__}, | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 901 | 	{NULL,	NULL}		/* Sentinel */ | 
 | 902 | }; | 
 | 903 |  | 
 | 904 | void | 
 | 905 | initgc(void) | 
 | 906 | { | 
 | 907 | 	PyObject *m; | 
 | 908 | 	PyObject *d; | 
 | 909 |  | 
 | 910 | 	m = Py_InitModule4("gc", | 
 | 911 | 			      GcMethods, | 
 | 912 | 			      gc__doc__, | 
 | 913 | 			      NULL, | 
 | 914 | 			      PYTHON_API_VERSION); | 
 | 915 | 	d = PyModule_GetDict(m); | 
 | 916 | 	if (garbage == NULL) { | 
 | 917 | 		garbage = PyList_New(0); | 
 | 918 | 	} | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 919 | 	PyDict_SetItemString(d, "garbage", garbage); | 
 | 920 | 	PyDict_SetItemString(d, "DEBUG_STATS", | 
 | 921 | 			PyInt_FromLong(DEBUG_STATS)); | 
 | 922 | 	PyDict_SetItemString(d, "DEBUG_COLLECTABLE", | 
 | 923 | 			PyInt_FromLong(DEBUG_COLLECTABLE)); | 
 | 924 | 	PyDict_SetItemString(d, "DEBUG_UNCOLLECTABLE", | 
 | 925 | 			PyInt_FromLong(DEBUG_UNCOLLECTABLE)); | 
 | 926 | 	PyDict_SetItemString(d, "DEBUG_INSTANCES", | 
 | 927 | 			PyInt_FromLong(DEBUG_INSTANCES)); | 
 | 928 | 	PyDict_SetItemString(d, "DEBUG_OBJECTS", | 
 | 929 | 			PyInt_FromLong(DEBUG_OBJECTS)); | 
| Neil Schemenauer | 544de1e | 2000-09-22 15:22:38 +0000 | [diff] [blame] | 930 | 	PyDict_SetItemString(d, "DEBUG_SAVEALL", | 
 | 931 | 			PyInt_FromLong(DEBUG_SAVEALL)); | 
| Jeremy Hylton | c5007aa | 2000-06-30 05:02:53 +0000 | [diff] [blame] | 932 | 	PyDict_SetItemString(d, "DEBUG_LEAK", | 
 | 933 | 			PyInt_FromLong(DEBUG_LEAK)); | 
 | 934 | } | 
 | 935 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 936 | /* for debugging */ | 
 | 937 | void _PyGC_Dump(PyGC_Head *g) | 
 | 938 | { | 
 | 939 | 	_PyObject_Dump(FROM_GC(g)); | 
 | 940 | } | 
 | 941 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 942 | /* extension modules might be compiled with GC support so these | 
 | 943 |    functions must always be available */ | 
 | 944 |  | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 945 | #undef PyObject_GC_Track | 
 | 946 | #undef PyObject_GC_UnTrack | 
 | 947 | #undef PyObject_GC_Del | 
 | 948 | #undef _PyObject_GC_Malloc | 
 | 949 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 950 | void | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 951 | PyObject_GC_Track(void *op) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 952 | { | 
 | 953 | 	_PyObject_GC_TRACK(op); | 
 | 954 | } | 
 | 955 |  | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 956 | /* for binary compatibility with 2.2 */ | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 957 | void | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 958 | _PyObject_GC_Track(PyObject *op) | 
 | 959 | { | 
 | 960 |     PyObject_GC_Track(op); | 
 | 961 | } | 
 | 962 |  | 
 | 963 | void | 
 | 964 | PyObject_GC_UnTrack(void *op) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 965 | { | 
| Tim Peters | 803526b | 2002-07-07 05:13:56 +0000 | [diff] [blame] | 966 | 	/* Obscure:  the Py_TRASHCAN mechanism requires that we be able to | 
 | 967 | 	 * call PyObject_GC_UnTrack twice on an object. | 
 | 968 | 	 */ | 
| Neil Schemenauer | a2b11ec | 2002-05-21 15:53:24 +0000 | [diff] [blame] | 969 | 	if (IS_TRACKED(op)) | 
| Guido van Rossum | ff413af | 2002-03-28 20:34:59 +0000 | [diff] [blame] | 970 | 		_PyObject_GC_UNTRACK(op); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 971 | } | 
 | 972 |  | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 973 | /* for binary compatibility with 2.2 */ | 
 | 974 | void | 
 | 975 | _PyObject_GC_UnTrack(PyObject *op) | 
 | 976 | { | 
 | 977 |     PyObject_GC_UnTrack(op); | 
 | 978 | } | 
 | 979 |  | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 980 | PyObject * | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 981 | _PyObject_GC_Malloc(size_t basicsize) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 982 | { | 
 | 983 | 	PyObject *op; | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 984 | 	PyGC_Head *g = PyObject_MALLOC(sizeof(PyGC_Head) + basicsize); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 985 | 	if (g == NULL) | 
| Jeremy Hylton | 8a13518 | 2002-06-06 23:23:55 +0000 | [diff] [blame] | 986 | 		return PyErr_NoMemory(); | 
| Tim Peters | ea40563 | 2002-07-02 00:52:30 +0000 | [diff] [blame] | 987 | 	g->gc.gc_refs = GC_UNTRACKED; | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 988 | 	generations[0].count++; /* number of allocated GC objects */ | 
 | 989 |  	if (generations[0].count > generations[0].threshold && | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 990 |  	    enabled && | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 991 |  	    generations[0].threshold && | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 992 |  	    !collecting && | 
 | 993 |  	    !PyErr_Occurred()) { | 
 | 994 | 		collecting = 1; | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 995 | 		collect_generations(); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 996 | 		collecting = 0; | 
 | 997 | 	} | 
 | 998 | 	op = FROM_GC(g); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 999 | 	return op; | 
 | 1000 | } | 
 | 1001 |  | 
 | 1002 | PyObject * | 
 | 1003 | _PyObject_GC_New(PyTypeObject *tp) | 
 | 1004 | { | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 1005 | 	PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); | 
| Tim Peters | fa8efab | 2002-04-28 01:57:25 +0000 | [diff] [blame] | 1006 | 	if (op != NULL) | 
 | 1007 | 		op = PyObject_INIT(op, tp); | 
 | 1008 | 	return op; | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1009 | } | 
 | 1010 |  | 
 | 1011 | PyVarObject * | 
| Tim Peters | 6d483d3 | 2001-10-06 21:27:34 +0000 | [diff] [blame] | 1012 | _PyObject_GC_NewVar(PyTypeObject *tp, int nitems) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1013 | { | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 1014 | 	const size_t size = _PyObject_VAR_SIZE(tp, nitems); | 
 | 1015 | 	PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(size); | 
| Tim Peters | fa8efab | 2002-04-28 01:57:25 +0000 | [diff] [blame] | 1016 | 	if (op != NULL) | 
 | 1017 | 		op = PyObject_INIT_VAR(op, tp, nitems); | 
 | 1018 | 	return op; | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1019 | } | 
 | 1020 |  | 
 | 1021 | PyVarObject * | 
| Tim Peters | 6d483d3 | 2001-10-06 21:27:34 +0000 | [diff] [blame] | 1022 | _PyObject_GC_Resize(PyVarObject *op, int nitems) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1023 | { | 
| Tim Peters | f2a67da | 2001-10-07 03:54:51 +0000 | [diff] [blame] | 1024 | 	const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1025 | 	PyGC_Head *g = AS_GC(op); | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 1026 | 	g = PyObject_REALLOC(g,  sizeof(PyGC_Head) + basicsize); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1027 | 	if (g == NULL) | 
 | 1028 | 		return (PyVarObject *)PyErr_NoMemory(); | 
 | 1029 | 	op = (PyVarObject *) FROM_GC(g); | 
| Tim Peters | 6d483d3 | 2001-10-06 21:27:34 +0000 | [diff] [blame] | 1030 | 	op->ob_size = nitems; | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1031 | 	return op; | 
 | 1032 | } | 
 | 1033 |  | 
 | 1034 | void | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 1035 | PyObject_GC_Del(void *op) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1036 | { | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1037 | 	PyGC_Head *g = AS_GC(op); | 
| Neil Schemenauer | a2b11ec | 2002-05-21 15:53:24 +0000 | [diff] [blame] | 1038 | 	if (IS_TRACKED(op)) | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1039 | 		gc_list_remove(g); | 
| Neil Schemenauer | 2880ae5 | 2002-05-04 05:35:20 +0000 | [diff] [blame] | 1040 | 	if (generations[0].count > 0) { | 
 | 1041 | 		generations[0].count--; | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1042 | 	} | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 1043 | 	PyObject_FREE(g); | 
| Neil Schemenauer | 43411b5 | 2001-08-30 00:05:51 +0000 | [diff] [blame] | 1044 | } | 
 | 1045 |  | 
| Neil Schemenauer | fec4eb1 | 2002-04-12 02:41:03 +0000 | [diff] [blame] | 1046 | /* for binary compatibility with 2.2 */ | 
 | 1047 | #undef _PyObject_GC_Del | 
 | 1048 | void | 
 | 1049 | _PyObject_GC_Del(PyObject *op) | 
 | 1050 | { | 
 | 1051 |     PyObject_GC_Del(op); | 
 | 1052 | } |