diff options
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 149 |
1 files changed, 112 insertions, 37 deletions
diff --git a/Objects/object.c b/Objects/object.c index 949e7dc7f3..8d4fe4248e 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -255,6 +255,72 @@ _PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems) return PyObject_INIT_VAR(op, tp, nitems); } +void +PyObject_CallFinalizer(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + + /* The former could happen on heaptypes created from the C API, e.g. + PyType_FromSpec(). */ + if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_FINALIZE) || + tp->tp_finalize == NULL) + return; + /* tp_finalize should only be called once. */ + if (PyType_IS_GC(tp) && _PyGC_FINALIZED(self)) + return; + + tp->tp_finalize(self); + if (PyType_IS_GC(tp)) + _PyGC_SET_FINALIZED(self, 1); +} + +int +PyObject_CallFinalizerFromDealloc(PyObject *self) +{ + Py_ssize_t refcnt; + + /* Temporarily resurrect the object. */ + if (self->ob_refcnt != 0) { + Py_FatalError("PyObject_CallFinalizerFromDealloc called on " + "object with a non-zero refcount"); + } + self->ob_refcnt = 1; + + PyObject_CallFinalizer(self); + + /* Undo the temporary resurrection; can't use DECREF here, it would + * cause a recursive call. + */ + assert(self->ob_refcnt > 0); + if (--self->ob_refcnt == 0) + return 0; /* this is the normal path out */ + + /* tp_finalize resurrected it! Make it look like the original Py_DECREF + * never happened. + */ + refcnt = self->ob_refcnt; + _Py_NewReference(self); + self->ob_refcnt = refcnt; + + if (PyType_IS_GC(Py_TYPE(self))) { + assert(_PyGC_REFS(self) != _PyGC_REFS_UNTRACKED); + } + /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so + * we need to undo that. */ + _Py_DEC_REFTOTAL; + /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object + * chain, so no more to do there. + * If COUNT_ALLOCS, the original decref bumped tp_frees, and + * _Py_NewReference bumped tp_allocs: both of those need to be + * undone. + */ +#ifdef COUNT_ALLOCS + --Py_TYPE(self)->tp_frees; + --Py_TYPE(self)->tp_allocs; +#endif + return -1; +} + int PyObject_Print(PyObject *op, FILE *fp, int flags) { @@ -377,6 +443,14 @@ PyObject_Repr(PyObject *v) if (Py_TYPE(v)->tp_repr == NULL) return PyUnicode_FromFormat("<%s object at %p>", v->ob_type->tp_name, v); + +#ifdef Py_DEBUG + /* PyObject_Repr() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller looses its exception */ + assert(!PyErr_Occurred()); +#endif + res = (*v->ob_type->tp_repr)(v); if (res == NULL) return NULL; @@ -408,6 +482,7 @@ PyObject_Str(PyObject *v) #endif if (v == NULL) return PyUnicode_FromString("<NULL>"); + if (PyUnicode_CheckExact(v)) { #ifndef Py_DEBUG if (PyUnicode_READY(v) < 0) @@ -419,6 +494,13 @@ PyObject_Str(PyObject *v) if (Py_TYPE(v)->tp_str == NULL) return PyObject_Repr(v); +#ifdef Py_DEBUG + /* PyObject_Str() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller looses its exception */ + assert(!PyErr_Occurred()); +#endif + /* It is possible for a type to have a tp_str representation that loops infinitely. */ if (Py_EnterRecursiveCall(" while getting the str of an object")) @@ -451,6 +533,9 @@ PyObject_ASCII(PyObject *v) if (repr == NULL) return NULL; + if (PyUnicode_IS_ASCII(repr)) + return repr; + /* repr is guaranteed to be a PyUnicode object by PyObject_Repr */ ascii = _PyUnicode_AsASCIIString(repr, "backslashreplace"); Py_DECREF(repr); @@ -1524,12 +1609,21 @@ notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_RETURN_NOTIMPLEMENTED; } +static void +notimplemented_dealloc(PyObject* ignore) +{ + /* This should never get called, but we also don't want to SEGV if + * we accidentally decref NotImplemented out of existence. + */ + Py_FatalError("deallocating NotImplemented"); +} + static PyTypeObject PyNotImplemented_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "NotImplementedType", 0, 0, - none_dealloc, /*tp_dealloc*/ /*never called*/ + notimplemented_dealloc, /*tp_dealloc*/ /*never called*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -1699,15 +1793,6 @@ _Py_ReadyTypes(void) if (PyType_Ready(&PyMemberDescr_Type) < 0) Py_FatalError("Can't initialize member descriptor type"); - if (PyType_Ready(&PyFilter_Type) < 0) - Py_FatalError("Can't initialize filter type"); - - if (PyType_Ready(&PyMap_Type) < 0) - Py_FatalError("Can't initialize map type"); - - if (PyType_Ready(&PyZip_Type) < 0) - Py_FatalError("Can't initialize zip type"); - if (PyType_Ready(&_PyNamespace_Type) < 0) Py_FatalError("Can't initialize namespace type"); @@ -1749,10 +1834,10 @@ _Py_NewReference(PyObject *op) } void -_Py_ForgetReference(register PyObject *op) +_Py_ForgetReference(PyObject *op) { #ifdef SLOW_UNREF_CHECK - register PyObject *p; + PyObject *p; #endif if (op->ob_refcnt < 0) Py_FatalError("UNREF negative refcnt"); @@ -1856,26 +1941,6 @@ PyTypeObject *_PyCapsule_hack = &PyCapsule_Type; Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size; -/* Python's malloc wrappers (see pymem.h) */ - -void * -PyMem_Malloc(size_t nbytes) -{ - return PyMem_MALLOC(nbytes); -} - -void * -PyMem_Realloc(void *p, size_t nbytes) -{ - return PyMem_REALLOC(p, nbytes); -} - -void -PyMem_Free(void *p) -{ - PyMem_FREE(p); -} - void _PyObject_DebugTypeStats(FILE *out) { @@ -1927,7 +1992,8 @@ Py_ReprEnter(PyObject *obj) if (PyList_GET_ITEM(list, i) == obj) return 1; } - PyList_Append(list, obj); + if (PyList_Append(list, obj) < 0) + return -1; return 0; } @@ -1937,13 +2003,18 @@ Py_ReprLeave(PyObject *obj) PyObject *dict; PyObject *list; Py_ssize_t i; + PyObject *error_type, *error_value, *error_traceback; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); dict = PyThreadState_GetDict(); if (dict == NULL) - return; + goto finally; + list = PyDict_GetItemString(dict, KEY); if (list == NULL || !PyList_Check(list)) - return; + goto finally; + i = PyList_GET_SIZE(list); /* Count backwards because we always expect obj to be list[-1] */ while (--i >= 0) { @@ -1952,6 +2023,10 @@ Py_ReprLeave(PyObject *obj) break; } } + +finally: + /* ignore exceptions because there is no way to report them. */ + PyErr_Restore(error_type, error_value, error_traceback); } /* Trashcan support. */ @@ -1972,7 +2047,7 @@ void _PyTrash_deposit_object(PyObject *op) { assert(PyObject_IS_GC(op)); - assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); + assert(_PyGC_REFS(op) == _PyGC_REFS_UNTRACKED); assert(op->ob_refcnt == 0); _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later; _PyTrash_delete_later = op; @@ -1984,7 +2059,7 @@ _PyTrash_thread_deposit_object(PyObject *op) { PyThreadState *tstate = PyThreadState_GET(); assert(PyObject_IS_GC(op)); - assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); + assert(_PyGC_REFS(op) == _PyGC_REFS_UNTRACKED); assert(op->ob_refcnt == 0); _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later; tstate->trash_delete_later = op; |