mirror of
https://github.com/python/cpython
synced 2026-09-29 11:55:30 +03:00
final patches from Neil Schemenauer for garbage collection
This commit is contained in:
parent
4e542a3d99
commit
c5007aa5c3
16 changed files with 956 additions and 18 deletions
|
|
@ -132,6 +132,7 @@ PyClass_New(bases, dict, name)
|
|||
Py_XINCREF(op->cl_getattr);
|
||||
Py_XINCREF(op->cl_setattr);
|
||||
Py_XINCREF(op->cl_delattr);
|
||||
PyObject_GC_Init(op);
|
||||
return (PyObject *) op;
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +142,7 @@ static void
|
|||
class_dealloc(op)
|
||||
PyClassObject *op;
|
||||
{
|
||||
PyObject_GC_Fini(op);
|
||||
Py_DECREF(op->cl_bases);
|
||||
Py_DECREF(op->cl_dict);
|
||||
Py_XDECREF(op->cl_name);
|
||||
|
|
@ -428,7 +430,7 @@ PyTypeObject PyClass_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"class",
|
||||
sizeof(PyClassObject) + PyGC_INFO_SIZE,
|
||||
sizeof(PyClassObject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
(destructor)class_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
|
|
@ -490,6 +492,7 @@ PyInstance_New(class, arg, kw)
|
|||
if (inst == NULL)
|
||||
return NULL;
|
||||
inst->in_dict = PyDict_New();
|
||||
PyObject_GC_Init(inst);
|
||||
if (inst->in_dict == NULL) {
|
||||
PyObject_DEL(inst);
|
||||
return NULL;
|
||||
|
|
@ -539,11 +542,12 @@ instance_dealloc(inst)
|
|||
PyObject *error_type, *error_value, *error_traceback;
|
||||
PyObject *del;
|
||||
static PyObject *delstr;
|
||||
extern long _Py_RefTotal;
|
||||
PyObject_GC_Fini(inst);
|
||||
/* Call the __del__ method if it exists. First temporarily
|
||||
revive the object and save the current exception, if any. */
|
||||
#ifdef Py_TRACE_REFS
|
||||
/* much too complicated if Py_TRACE_REFS defined */
|
||||
extern long _Py_RefTotal;
|
||||
inst->ob_type = &PyInstance_Type;
|
||||
_Py_NewReference((PyObject *)inst);
|
||||
_Py_RefTotal--; /* compensate for increment in NEWREF */
|
||||
|
|
@ -591,6 +595,7 @@ instance_dealloc(inst)
|
|||
#ifdef COUNT_ALLOCS
|
||||
inst->ob_type->tp_free--;
|
||||
#endif
|
||||
PyObject_GC_Init((PyObject *)inst);
|
||||
return; /* __del__ added a reference; don't delete now */
|
||||
}
|
||||
#ifdef Py_TRACE_REFS
|
||||
|
|
@ -598,7 +603,9 @@ instance_dealloc(inst)
|
|||
inst->ob_type->tp_free--; /* compensate for increment in UNREF */
|
||||
#endif
|
||||
_Py_ForgetReference((PyObject *)inst);
|
||||
#ifndef WITH_CYCLE_GC
|
||||
inst->ob_type = NULL;
|
||||
#endif
|
||||
#endif /* Py_TRACE_REFS */
|
||||
Py_DECREF(inst->in_class);
|
||||
Py_XDECREF(inst->in_dict);
|
||||
|
|
@ -1510,7 +1517,7 @@ PyTypeObject PyInstance_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"instance",
|
||||
sizeof(PyInstanceObject) + PyGC_INFO_SIZE,
|
||||
sizeof(PyInstanceObject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
(destructor)instance_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
|
|
@ -1568,6 +1575,7 @@ PyMethod_New(func, self, class)
|
|||
im->im_self = self;
|
||||
Py_INCREF(class);
|
||||
im->im_class = class;
|
||||
PyObject_GC_Init(im);
|
||||
return (PyObject *)im;
|
||||
}
|
||||
|
||||
|
|
@ -1643,6 +1651,7 @@ static void
|
|||
instancemethod_dealloc(im)
|
||||
register PyMethodObject *im;
|
||||
{
|
||||
PyObject_GC_Fini(im);
|
||||
Py_DECREF(im->im_func);
|
||||
Py_XDECREF(im->im_self);
|
||||
Py_DECREF(im->im_class);
|
||||
|
|
@ -1745,7 +1754,7 @@ PyTypeObject PyMethod_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"instance method",
|
||||
sizeof(PyMethodObject) + PyGC_INFO_SIZE,
|
||||
sizeof(PyMethodObject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
(destructor)instancemethod_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ PyDict_New()
|
|||
mp->ma_table = NULL;
|
||||
mp->ma_fill = 0;
|
||||
mp->ma_used = 0;
|
||||
PyObject_GC_Init(mp);
|
||||
return (PyObject *)mp;
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +482,7 @@ dict_dealloc(mp)
|
|||
register int i;
|
||||
register dictentry *ep;
|
||||
Py_TRASHCAN_SAFE_BEGIN(mp)
|
||||
PyObject_GC_Fini(mp);
|
||||
for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
|
||||
if (ep->me_key != NULL) {
|
||||
Py_DECREF(ep->me_key);
|
||||
|
|
@ -1087,7 +1089,7 @@ PyTypeObject PyDict_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"dictionary",
|
||||
sizeof(dictobject) + PyGC_INFO_SIZE,
|
||||
sizeof(dictobject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
(destructor)dict_dealloc, /*tp_dealloc*/
|
||||
(printfunc)dict_print, /*tp_print*/
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ PyFunction_New(code, globals)
|
|||
Py_INCREF(doc);
|
||||
op->func_doc = doc;
|
||||
}
|
||||
PyObject_GC_Init(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +187,7 @@ static void
|
|||
func_dealloc(op)
|
||||
PyFunctionObject *op;
|
||||
{
|
||||
PyObject_GC_Fini(op);
|
||||
Py_DECREF(op->func_code);
|
||||
Py_DECREF(op->func_globals);
|
||||
Py_DECREF(op->func_name);
|
||||
|
|
@ -277,7 +279,7 @@ PyTypeObject PyFunction_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"function",
|
||||
sizeof(PyFunctionObject) + PyGC_INFO_SIZE,
|
||||
sizeof(PyFunctionObject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
(destructor)func_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ PyList_New(size)
|
|||
}
|
||||
/* PyObject_NewVar is inlined */
|
||||
op = (PyListObject *) PyObject_MALLOC(sizeof(PyListObject)
|
||||
+ PyGC_INFO_SIZE);
|
||||
+ PyGC_HEAD_SIZE);
|
||||
if (op == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
op = (PyListObject *) PyObject_FROM_GC(op);
|
||||
if (size <= 0) {
|
||||
op->ob_item = NULL;
|
||||
}
|
||||
|
|
@ -89,6 +90,7 @@ PyList_New(size)
|
|||
PyObject_INIT_VAR(op, &PyList_Type, size);
|
||||
for (i = 0; i < size; i++)
|
||||
op->ob_item[i] = NULL;
|
||||
PyObject_GC_Init(op);
|
||||
return (PyObject *) op;
|
||||
}
|
||||
|
||||
|
|
@ -216,6 +218,7 @@ list_dealloc(op)
|
|||
{
|
||||
int i;
|
||||
Py_TRASHCAN_SAFE_BEGIN(op)
|
||||
PyObject_GC_Fini(op);
|
||||
if (op->ob_item != NULL) {
|
||||
/* Do it backwards, for Christian Tismer.
|
||||
There's a simple test case where somehow this reduces
|
||||
|
|
@ -1498,7 +1501,7 @@ PyTypeObject PyList_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"list",
|
||||
sizeof(PyListObject) + PyGC_INFO_SIZE,
|
||||
sizeof(PyListObject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
(destructor)list_dealloc, /*tp_dealloc*/
|
||||
(printfunc)list_print, /*tp_print*/
|
||||
|
|
@ -1577,7 +1580,7 @@ static PyTypeObject immutable_list_type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"list (immutable, during sort)",
|
||||
sizeof(PyListObject) + PyGC_INFO_SIZE,
|
||||
sizeof(PyListObject) + PyGC_HEAD_SIZE,
|
||||
0,
|
||||
0, /*tp_dealloc*/ /* Cannot happen */
|
||||
(printfunc)list_print, /*tp_print*/
|
||||
|
|
|
|||
|
|
@ -124,6 +124,10 @@ PyObject_Init(op, tp)
|
|||
"NULL object passed to PyObject_Init");
|
||||
return op;
|
||||
}
|
||||
#ifdef WITH_CYCLE_GC
|
||||
if (PyType_IS_GC(tp))
|
||||
op = (PyObject *) PyObject_FROM_GC(op);
|
||||
#endif
|
||||
/* Any changes should be reflected in PyObject_INIT (objimpl.h) */
|
||||
op->ob_type = tp;
|
||||
_Py_NewReference(op);
|
||||
|
|
@ -141,6 +145,10 @@ PyObject_InitVar(op, tp, size)
|
|||
"NULL object passed to PyObject_InitVar");
|
||||
return op;
|
||||
}
|
||||
#ifdef WITH_CYCLE_GC
|
||||
if (PyType_IS_GC(tp))
|
||||
op = (PyVarObject *) PyObject_FROM_GC(op);
|
||||
#endif
|
||||
/* Any changes should be reflected in PyObject_INIT_VAR */
|
||||
op->ob_size = size;
|
||||
op->ob_type = tp;
|
||||
|
|
@ -156,6 +164,10 @@ _PyObject_New(tp)
|
|||
op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
|
||||
if (op == NULL)
|
||||
return PyErr_NoMemory();
|
||||
#ifdef WITH_CYCLE_GC
|
||||
if (PyType_IS_GC(tp))
|
||||
op = (PyObject *) PyObject_FROM_GC(op);
|
||||
#endif
|
||||
return PyObject_INIT(op, tp);
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +180,10 @@ _PyObject_NewVar(tp, size)
|
|||
op = (PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE(tp, size));
|
||||
if (op == NULL)
|
||||
return (PyVarObject *)PyErr_NoMemory();
|
||||
#ifdef WITH_CYCLE_GC
|
||||
if (PyType_IS_GC(tp))
|
||||
op = (PyVarObject *) PyObject_FROM_GC(op);
|
||||
#endif
|
||||
return PyObject_INIT_VAR(op, tp, size);
|
||||
}
|
||||
|
||||
|
|
@ -175,9 +191,23 @@ void
|
|||
_PyObject_Del(op)
|
||||
PyObject *op;
|
||||
{
|
||||
PyObject_FREE(op);
|
||||
#ifdef WITH_CYCLE_GC
|
||||
if (PyType_IS_GC(op->ob_type)) {
|
||||
PyGC_Head *g = PyObject_AS_GC(op);
|
||||
PyObject_FREE(g);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PyObject_FREE(op);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WITH_CYCLE_GC
|
||||
/* extension modules might need these */
|
||||
void _PyGC_Insert(PyObject *op) { }
|
||||
void _PyGC_Remove(PyObject *op) { }
|
||||
#endif
|
||||
|
||||
int
|
||||
PyObject_Print(op, fp, flags)
|
||||
PyObject *op;
|
||||
|
|
@ -917,8 +947,10 @@ _Py_Dealloc(op)
|
|||
{
|
||||
destructor dealloc = op->ob_type->tp_dealloc;
|
||||
_Py_ForgetReference(op);
|
||||
#ifndef WITH_CYCLE_GC
|
||||
if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL-1)
|
||||
op->ob_type = NULL;
|
||||
#endif
|
||||
(*dealloc)(op);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ PyTuple_New(size)
|
|||
/* Check for overflow */
|
||||
if (nbytes / sizeof(PyObject *) != (size_t)size ||
|
||||
(nbytes += sizeof(PyTupleObject) - sizeof(PyObject *)
|
||||
+ PyGC_INFO_SIZE)
|
||||
+ PyGC_HEAD_SIZE)
|
||||
<= 0)
|
||||
{
|
||||
return PyErr_NoMemory();
|
||||
|
|
@ -103,7 +103,7 @@ PyTuple_New(size)
|
|||
op = (PyTupleObject *) PyObject_MALLOC(nbytes);
|
||||
if (op == NULL)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
op = (PyTupleObject *) PyObject_FROM_GC(op);
|
||||
PyObject_INIT_VAR(op, &PyTuple_Type, size);
|
||||
}
|
||||
for (i = 0; i < size; i++)
|
||||
|
|
@ -115,6 +115,7 @@ PyTuple_New(size)
|
|||
Py_INCREF(op); /* extra INCREF so that this is never freed */
|
||||
}
|
||||
#endif
|
||||
PyObject_GC_Init(op);
|
||||
return (PyObject *) op;
|
||||
}
|
||||
|
||||
|
|
@ -181,6 +182,7 @@ tupledealloc(op)
|
|||
register int i;
|
||||
register int len = op->ob_size;
|
||||
Py_TRASHCAN_SAFE_BEGIN(op)
|
||||
PyObject_GC_Fini(op);
|
||||
if (len > 0) {
|
||||
i = len;
|
||||
while (--i >= 0)
|
||||
|
|
@ -453,7 +455,7 @@ PyTypeObject PyTuple_Type = {
|
|||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"tuple",
|
||||
sizeof(PyTupleObject) - sizeof(PyObject *) + PyGC_INFO_SIZE,
|
||||
sizeof(PyTupleObject) - sizeof(PyObject *) + PyGC_HEAD_SIZE,
|
||||
sizeof(PyObject *),
|
||||
(destructor)tupledealloc, /*tp_dealloc*/
|
||||
(printfunc)tupleprint, /*tp_print*/
|
||||
|
|
@ -557,12 +559,27 @@ _PyTuple_Resize(pv, newsize, last_is_sticky)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef WITH_CYCLE_GC
|
||||
PyGC_Head *g = PyObject_AS_GC((PyObject *)v);
|
||||
PyObject_GC_Fini((PyObject *)v);
|
||||
sv = (PyTupleObject *)
|
||||
PyObject_REALLOC((char *)g, sizeof(PyTupleObject)
|
||||
+ PyGC_HEAD_SIZE
|
||||
+ newsize * sizeof(PyObject *));
|
||||
if (g == NULL) {
|
||||
sv = NULL;
|
||||
} else {
|
||||
sv = (PyTupleObject *)PyObject_FROM_GC(g);
|
||||
}
|
||||
#else
|
||||
sv = (PyTupleObject *)
|
||||
PyObject_REALLOC((char *)v, sizeof(PyTupleObject)
|
||||
+ PyGC_INFO_SIZE
|
||||
+ PyGC_HEAD_SIZE
|
||||
+ newsize * sizeof(PyObject *));
|
||||
#endif
|
||||
*pv = (PyObject *) sv;
|
||||
if (sv == NULL) {
|
||||
PyObject_GC_Init((PyObject *)v);
|
||||
PyObject_DEL(v);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
|
|
@ -578,6 +595,7 @@ _PyTuple_Resize(pv, newsize, last_is_sticky)
|
|||
sv->ob_item[i - sizediff] = NULL;
|
||||
}
|
||||
}
|
||||
PyObject_GC_Init(sv);
|
||||
sv->ob_size = newsize;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue