| OLD | NEW |
| 1 /* | 1 /* |
| 2 | 2 |
| 3 Reference Cycle Garbage Collection | 3 Reference Cycle Garbage Collection |
| 4 ================================== | 4 ================================== |
| 5 | 5 |
| 6 Neil Schemenauer <nas@arctrix.com> | 6 Neil Schemenauer <nas@arctrix.com> |
| 7 | 7 |
| 8 Based on a post on the python-dev list. Ideas from Guido van Rossum, | 8 Based on a post on the python-dev list. Ideas from Guido van Rossum, |
| 9 Eric Tiedemann, and various others. | 9 Eric Tiedemann, and various others. |
| 10 | 10 |
| 11 http://www.arctrix.com/nas/python/gc/ | 11 http://www.arctrix.com/nas/python/gc/ |
| 12 | 12 |
| 13 The following mailing list threads provide a historical perspective on | 13 The following mailing list threads provide a historical perspective on |
| 14 the design of this module. Note that a fair amount of refinement has | 14 the design of this module. Note that a fair amount of refinement has |
| 15 occurred since those discussions. | 15 occurred since those discussions. |
| 16 | 16 |
| 17 http://mail.python.org/pipermail/python-dev/2000-March/002385.html | 17 http://mail.python.org/pipermail/python-dev/2000-March/002385.html |
| 18 http://mail.python.org/pipermail/python-dev/2000-March/002434.html | 18 http://mail.python.org/pipermail/python-dev/2000-March/002434.html |
| 19 http://mail.python.org/pipermail/python-dev/2000-March/002497.html | 19 http://mail.python.org/pipermail/python-dev/2000-March/002497.html |
| 20 | 20 |
| 21 For a highlevel view of the collection process, read the collect | 21 For a highlevel view of the collection process, read the collect |
| 22 function. | 22 function. |
| 23 | 23 |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "Python.h" | 26 #include "Python.h" |
| 27 #include "frameobject.h" /* for PyFrame_ClearFreeList */ | 27 #include "frameobject.h" /* for PyFrame_ClearFreeList */ |
| 28 |
| 29 #ifdef WITH_DTRACE |
| 30 #include "pydtrace.h" |
| 31 #endif |
| 28 | 32 |
| 29 /* Get an object's GC head */ | 33 /* Get an object's GC head */ |
| 30 #define AS_GC(o) ((PyGC_Head *)(o)-1) | 34 #define AS_GC(o) ((PyGC_Head *)(o)-1) |
| 31 | 35 |
| 32 /* Get the object given the GC head */ | 36 /* Get the object given the GC head */ |
| 33 #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) | 37 #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) |
| 34 | 38 |
| 35 /*** Global GC state ***/ | 39 /*** Global GC state ***/ |
| 36 | 40 |
| 37 struct gc_generation { | 41 struct gc_generation { |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 result = PyFloat_AsDouble(f); | 838 result = PyFloat_AsDouble(f); |
| 835 Py_DECREF(f); | 839 Py_DECREF(f); |
| 836 } | 840 } |
| 837 } | 841 } |
| 838 return result; | 842 return result; |
| 839 } | 843 } |
| 840 | 844 |
| 841 /* This is the main function. Read this to understand how the | 845 /* This is the main function. Read this to understand how the |
| 842 * collection process works. */ | 846 * collection process works. */ |
| 843 static Py_ssize_t | 847 static Py_ssize_t |
| 844 collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) | 848 #ifdef WITH_DTRACE |
| 849 collect2 |
| 850 #else |
| 851 collect |
| 852 #endif |
| 853 (int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) |
| 845 { | 854 { |
| 846 int i; | 855 int i; |
| 847 Py_ssize_t m = 0; /* # objects collected */ | 856 Py_ssize_t m = 0; /* # objects collected */ |
| 848 Py_ssize_t n = 0; /* # unreachable objects that couldn't be collected */ | 857 Py_ssize_t n = 0; /* # unreachable objects that couldn't be collected */ |
| 849 PyGC_Head *young; /* the generation we are examining */ | 858 PyGC_Head *young; /* the generation we are examining */ |
| 850 PyGC_Head *old; /* next older generation */ | 859 PyGC_Head *old; /* next older generation */ |
| 851 PyGC_Head unreachable; /* non-problematic unreachable trash */ | 860 PyGC_Head unreachable; /* non-problematic unreachable trash */ |
| 852 PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ | 861 PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ |
| 853 PyGC_Head *gc; | 862 PyGC_Head *gc; |
| 854 double t1 = 0.0; | 863 double t1 = 0.0; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 PyErr_WriteUnraisable(gc_str); | 1001 PyErr_WriteUnraisable(gc_str); |
| 993 Py_FatalError("unexpected exception during garbage collection"); | 1002 Py_FatalError("unexpected exception during garbage collection"); |
| 994 } | 1003 } |
| 995 | 1004 |
| 996 if (n_collected) | 1005 if (n_collected) |
| 997 *n_collected = m; | 1006 *n_collected = m; |
| 998 if (n_uncollectable) | 1007 if (n_uncollectable) |
| 999 *n_uncollectable = n; | 1008 *n_uncollectable = n; |
| 1000 return n+m; | 1009 return n+m; |
| 1001 } | 1010 } |
| 1011 |
| 1012 #ifdef WITH_DTRACE |
| 1013 static void |
| 1014 dtrace_gc_start(int collection) |
| 1015 { |
| 1016 PYTHON_GC_START(collection); |
| 1017 |
| 1018 /* |
| 1019 * Currently a USDT tail-call will not receive the correct arguments. |
| 1020 * Disable the tail call here. |
| 1021 */ |
| 1022 #if defined(__sparc) |
| 1023 asm("nop"); |
| 1024 #endif |
| 1025 } |
| 1026 |
| 1027 static void |
| 1028 dtrace_gc_done(Py_ssize_t value) |
| 1029 { |
| 1030 PYTHON_GC_DONE((long) value); |
| 1031 |
| 1032 /* |
| 1033 * Currently a USDT tail-call will not receive the correct arguments. |
| 1034 * Disable the tail call here. |
| 1035 */ |
| 1036 #if defined(__sparc) |
| 1037 asm("nop"); |
| 1038 #endif |
| 1039 } |
| 1040 |
| 1041 static Py_ssize_t |
| 1042 collect(int collection, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) |
| 1043 { |
| 1044 Py_ssize_t value; |
| 1045 |
| 1046 if (PYTHON_GC_START_ENABLED()) |
| 1047 dtrace_gc_start(collection); |
| 1048 value = collect2(collection, n_collected, n_uncollectable); |
| 1049 if (PYTHON_GC_DONE_ENABLED()) |
| 1050 dtrace_gc_done(value); |
| 1051 return value; |
| 1052 } |
| 1053 #endif /* WITH_DTRACE */ |
| 1002 | 1054 |
| 1003 /* Invoke progress callbacks to notify clients that garbage collection | 1055 /* Invoke progress callbacks to notify clients that garbage collection |
| 1004 * is starting or stopping | 1056 * is starting or stopping |
| 1005 */ | 1057 */ |
| 1006 static void | 1058 static void |
| 1007 invoke_gc_callback(const char *phase, int generation, | 1059 invoke_gc_callback(const char *phase, int generation, |
| 1008 Py_ssize_t collected, Py_ssize_t uncollectable) | 1060 Py_ssize_t collected, Py_ssize_t uncollectable) |
| 1009 { | 1061 { |
| 1010 Py_ssize_t i; | 1062 Py_ssize_t i; |
| 1011 PyObject *info = NULL; | 1063 PyObject *info = NULL; |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1622 PyObject_GC_Del(void *op) | 1674 PyObject_GC_Del(void *op) |
| 1623 { | 1675 { |
| 1624 PyGC_Head *g = AS_GC(op); | 1676 PyGC_Head *g = AS_GC(op); |
| 1625 if (IS_TRACKED(op)) | 1677 if (IS_TRACKED(op)) |
| 1626 gc_list_remove(g); | 1678 gc_list_remove(g); |
| 1627 if (generations[0].count > 0) { | 1679 if (generations[0].count > 0) { |
| 1628 generations[0].count--; | 1680 generations[0].count--; |
| 1629 } | 1681 } |
| 1630 PyObject_FREE(g); | 1682 PyObject_FREE(g); |
| 1631 } | 1683 } |
| OLD | NEW |