summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/object.h10
-rw-r--r--Objects/object.c76
2 files changed, 69 insertions, 17 deletions
diff --git a/Include/object.h b/Include/object.h
index fabf0b6..f6ceba5 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -536,6 +536,11 @@ times.
Also, we could do an exact stack measure then.
Unfortunately, deallocations also take place when
the thread state is undefined.
+
+ CT 2k0422 complete rewrite.
+ There is no need to allocate new objects.
+ Everything is done vialob_refcnt and ob_type now.
+ Adding support for free-threading should be easy, too.
*/
#define PyTrash_UNWIND_LEVEL 50
@@ -551,11 +556,11 @@ times.
_PyTrash_deposit_object((PyObject*)op);\
--_PyTrash_delete_nesting; \
if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \
- _PyTrash_destroy_list(); \
+ _PyTrash_destroy_chain(); \
} \
extern DL_IMPORT(void) _PyTrash_deposit_object Py_PROTO((PyObject*));
-extern DL_IMPORT(void) _PyTrash_destroy_list Py_PROTO(());
+extern DL_IMPORT(void) _PyTrash_destroy_chain Py_PROTO(());
extern DL_IMPORT(int) _PyTrash_delete_nesting;
extern DL_IMPORT(PyObject *) _PyTrash_delete_later;
@@ -564,6 +569,7 @@ extern DL_IMPORT(PyObject *) _PyTrash_delete_later;
#define xxPy_TRASHCAN_SAFE_BEGIN(op)
#define xxPy_TRASHCAN_SAFE_END(op) ;
+
#ifdef __cplusplus
}
#endif
diff --git a/Objects/object.c b/Objects/object.c
index bd1d17f..ed276e2 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -33,6 +33,11 @@ PERFORMANCE OF THIS SOFTWARE.
#include "Python.h"
+/* just for trashcan: */
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+
#if defined( Py_TRACE_REFS ) || defined( Py_REF_DEBUG )
DL_IMPORT(long) _Py_RefTotal;
#endif
@@ -822,7 +827,8 @@ _Py_Dealloc(op)
{
destructor dealloc = op->ob_type->tp_dealloc;
_Py_ForgetReference(op);
- op->ob_type = NULL;
+ if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL-1)
+ op->ob_type = NULL;
(*dealloc)(op);
}
@@ -1045,37 +1051,77 @@ Py_ReprLeave(obj)
CT 2k0325
added better safe than sorry check for threadstate
+
+ CT 2k0422
+ complete rewrite. We now build a chain via ob_type
+ and save the limited number of types in ob_refcnt.
+ This is perfect since we don't need any memory.
+ A patch for free-threading would need just a lock.
*/
+#define Py_TRASHCAN_TUPLE 1
+#define Py_TRASHCAN_LIST 2
+#define Py_TRASHCAN_DICT 3
+#define Py_TRASHCAN_FRAME 4
+#define Py_TRASHCAN_TRACEBACK 5
+/* extend here if other objects want protection */
+
int _PyTrash_delete_nesting = 0;
+
PyObject * _PyTrash_delete_later = NULL;
void
_PyTrash_deposit_object(op)
PyObject *op;
{
- PyObject *error_type, *error_value, *error_traceback;
-
- if (PyThreadState_GET() != NULL)
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- if (!_PyTrash_delete_later)
- _PyTrash_delete_later = PyList_New(0);
- if (_PyTrash_delete_later)
- PyList_Append(_PyTrash_delete_later, (PyObject *)op);
-
- if (PyThreadState_GET() != NULL)
- PyErr_Restore(error_type, error_value, error_traceback);
+ int typecode;
+ PyObject *hold = _PyTrash_delete_later;
+
+ if (PyTuple_Check(op))
+ typecode = Py_TRASHCAN_TUPLE;
+ else if (PyList_Check(op))
+ typecode = Py_TRASHCAN_LIST;
+ else if (PyDict_Check(op))
+ typecode = Py_TRASHCAN_DICT;
+ else if (PyFrame_Check(op))
+ typecode = Py_TRASHCAN_FRAME;
+ else if (PyTraceBack_Check(op))
+ typecode = Py_TRASHCAN_TRACEBACK;
+ op->ob_refcnt = typecode;
+
+ op->ob_type = (PyTypeObject*)_PyTrash_delete_later;
+ _PyTrash_delete_later = op;
}
void
-_PyTrash_destroy_list()
+_PyTrash_destroy_chain()
{
while (_PyTrash_delete_later) {
PyObject *shredder = _PyTrash_delete_later;
- _PyTrash_delete_later = NULL;
+ _PyTrash_delete_later = (PyObject*) shredder->ob_type;
+
+ switch (shredder->ob_refcnt) {
+ case Py_TRASHCAN_TUPLE:
+ shredder->ob_type = &PyTuple_Type;
+ break;
+ case Py_TRASHCAN_LIST:
+ shredder->ob_type = &PyList_Type;
+ break;
+ case Py_TRASHCAN_DICT:
+ shredder->ob_type = &PyDict_Type;
+ break;
+ case Py_TRASHCAN_FRAME:
+ shredder->ob_type = &PyFrame_Type;
+ break;
+ case Py_TRASHCAN_TRACEBACK:
+ shredder->ob_type = &PyTraceBack_Type;
+ break;
+ }
+ _Py_NewReference(shredder);
+
++_PyTrash_delete_nesting;
Py_DECREF(shredder);
--_PyTrash_delete_nesting;
}
}
+