From e700f013b9b1347505391ea450ba62d8b2fb9bcd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 9 Dec 2022 15:28:43 -0700 Subject: [PATCH 1/2] Add _Py_NewReferenceNoTotal(). --- Include/cpython/object.h | 1 + Modules/_testcapimodule.c | 7 +------ Objects/bytesobject.c | 9 ++++----- Objects/object.c | 29 ++++++++++++++++++----------- Objects/tupleobject.c | 9 ++++----- Objects/unicodeobject.c | 7 ++----- 6 files changed, 30 insertions(+), 32 deletions(-) diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 4263370861302b..fc74ba28c78c77 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -3,6 +3,7 @@ #endif PyAPI_FUNC(void) _Py_NewReference(PyObject *op); +PyAPI_FUNC(void) _Py_NewReferenceNoTotal(PyObject *op); #ifdef Py_TRACE_REFS /* Py_TRACE_REFS is such major surgery that we call external routines. */ diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 83eef73a875d9d..a465a714a7a8e0 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1643,15 +1643,10 @@ slot_tp_del(PyObject *self) */ { Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReference(self); + _Py_NewReferenceNoTotal(self); Py_SET_REFCNT(self, refcnt); } assert(!PyType_IS_GC(Py_TYPE(self)) || PyObject_GC_IsTracked(self)); - /* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased - _Py_RefTotal, so we need to undo that. */ -#ifdef Py_REF_DEBUG - _Py_RefTotal--; -#endif } static PyObject * diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 0fd10fa00d16fa..83147e910528c2 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3058,21 +3058,20 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) Py_DECREF(v); return 0; } - /* XXX UNREF/NEWREF interface should be more symmetrical */ -#ifdef Py_REF_DEBUG - _Py_RefTotal--; -#endif #ifdef Py_TRACE_REFS _Py_ForgetReference(v); #endif *pv = (PyObject *) PyObject_Realloc(v, PyBytesObject_SIZE + newsize); if (*pv == NULL) { +#ifdef Py_REF_DEBUG + _Py_RefTotal--; +#endif PyObject_Free(v); PyErr_NoMemory(); return -1; } - _Py_NewReference(*pv); + _Py_NewReferenceNoTotal(*pv); sv = (PyBytesObject *) *pv; Py_SET_SIZE(sv, newsize); sv->ob_sval[newsize] = '\0'; diff --git a/Objects/object.c b/Objects/object.c index 687bd36d2b4af1..82b957f8abeac1 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -238,17 +238,12 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) /* tp_finalize resurrected it! Make it look like the original Py_DECREF * never happened. */ Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReference(self); + _Py_NewReferenceNoTotal(self); Py_SET_REFCNT(self, refcnt); _PyObject_ASSERT(self, (!_PyType_IS_GC(Py_TYPE(self)) || _PyObject_GC_IS_TRACKED(self))); - /* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased - _Py_RefTotal, so we need to undo that. */ -#ifdef Py_REF_DEBUG - _Py_RefTotal--; -#endif return -1; } @@ -2001,21 +1996,33 @@ _PyTypes_FiniTypes(PyInterpreterState *interp) } -void -_Py_NewReference(PyObject *op) +static inline void +new_reference(PyObject *op) { if (_PyRuntime.tracemalloc.config.tracing) { _PyTraceMalloc_NewReference(op); } -#ifdef Py_REF_DEBUG - _Py_RefTotal++; -#endif Py_SET_REFCNT(op, 1); #ifdef Py_TRACE_REFS _Py_AddToAllObjects(op, 1); #endif } +void +_Py_NewReference(PyObject *op) +{ +#ifdef Py_REF_DEBUG + _Py_RefTotal++; +#endif + new_reference(op); +} + +void +_Py_NewReferenceNoTotal(PyObject *op) +{ + new_reference(op); +} + #ifdef Py_TRACE_REFS void diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index e1b9953226c0d7..6e54e777434e36 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -930,10 +930,6 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize) return *pv == NULL ? -1 : 0; } - /* XXX UNREF/NEWREF interface should be more symmetrical */ -#ifdef Py_REF_DEBUG - _Py_RefTotal--; -#endif if (_PyObject_GC_IS_TRACKED(v)) { _PyObject_GC_UNTRACK(v); } @@ -947,10 +943,13 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize) sv = PyObject_GC_Resize(PyTupleObject, v, newsize); if (sv == NULL) { *pv = NULL; +#ifdef Py_REF_DEBUG + _Py_RefTotal--; +#endif PyObject_GC_Del(v); return -1; } - _Py_NewReference((PyObject *) sv); + _Py_NewReferenceNoTotal((PyObject *) sv); /* Zero out items added by growing */ if (newsize > oldsize) memset(&sv->ob_item[oldsize], 0, diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index b721ccd805edf1..f21b13a9d2fb79 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -947,21 +947,18 @@ resize_compact(PyObject *unicode, Py_ssize_t length) _PyUnicode_UTF8(unicode) = NULL; _PyUnicode_UTF8_LENGTH(unicode) = 0; } -#ifdef Py_REF_DEBUG - _Py_RefTotal--; -#endif #ifdef Py_TRACE_REFS _Py_ForgetReference(unicode); #endif new_unicode = (PyObject *)PyObject_Realloc(unicode, new_size); if (new_unicode == NULL) { - _Py_NewReference(unicode); + _Py_NewReferenceNoTotal(unicode); PyErr_NoMemory(); return NULL; } unicode = new_unicode; - _Py_NewReference(unicode); + _Py_NewReferenceNoTotal(unicode); _PyUnicode_LENGTH(unicode) = length; #ifdef Py_DEBUG From 66ba4cff6194cef82206f880d58192f82ce24df2 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 14 Nov 2022 17:10:34 -0700 Subject: [PATCH 2/2] Move _Py_RefTotal to _PyRuntimeState. --- Include/internal/pycore_object.h | 4 ++++ Include/internal/pycore_object_state.h | 21 +++++++++++++++++++++ Include/internal/pycore_runtime.h | 2 ++ Include/object.h | 1 - Makefile.pre.in | 1 + Objects/object.c | 2 -- PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 +++ 8 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 Include/internal/pycore_object_state.h diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 8796dfe2f6b8cf..ed113032241a75 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -37,6 +37,10 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( #define _Py_FatalRefcountError(message) \ _Py_FatalRefcountErrorFunc(__func__, (message)) +#ifdef Py_REF_DEBUG +# define _Py_RefTotal (_PyRuntime.object_state.reftotal) +#endif + // Increment reference count by n static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n) { diff --git a/Include/internal/pycore_object_state.h b/Include/internal/pycore_object_state.h new file mode 100644 index 00000000000000..02d90c6381ee45 --- /dev/null +++ b/Include/internal/pycore_object_state.h @@ -0,0 +1,21 @@ +#ifndef Py_INTERNAL_OBJECT_H +#define Py_INTERNAL_OBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +struct _py_object_runtime_state { +#ifdef Py_REF_DEBUG + Py_ssize_t reftotal; +#endif +}; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_OBJECT_H */ diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index fe2de5feb47ae3..d3ea11a01e633f 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -17,6 +17,7 @@ extern "C" { #include "pycore_global_objects.h" // struct _Py_global_objects #include "pycore_import.h" // struct _import_runtime_state #include "pycore_interp.h" // PyInterpreterState +#include "pycore_object_state.h" // struct _py_object_runtime_state #include "pycore_parser.h" // struct _parser_runtime_state #include "pycore_pymem.h" // struct _pymem_allocators #include "pycore_pyhash.h" // struct pyhash_runtime_state @@ -151,6 +152,7 @@ typedef struct pyruntimestate { void *open_code_userdata; _Py_AuditHookEntry *audit_hook_head; + struct _py_object_runtime_state obj_state; struct _Py_float_runtime_state float_state; struct _Py_unicode_runtime_state unicode_state; struct _Py_dict_runtime_state dict_state; diff --git a/Include/object.h b/Include/object.h index 3774f126730005..6152200a316eff 100644 --- a/Include/object.h +++ b/Include/object.h @@ -490,7 +490,6 @@ you can count such references to the type object.) */ #ifdef Py_REF_DEBUG -PyAPI_DATA(Py_ssize_t) _Py_RefTotal; PyAPI_FUNC(void) _Py_NegativeRefcount(const char *filename, int lineno, PyObject *op); #endif /* Py_REF_DEBUG */ diff --git a/Makefile.pre.in b/Makefile.pre.in index de42d684f16602..92e31e606e6f0a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1653,6 +1653,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_moduleobject.h \ $(srcdir)/Include/internal/pycore_namespace.h \ $(srcdir)/Include/internal/pycore_object.h \ + $(srcdir)/Include/internal/pycore_object_state.h \ $(srcdir)/Include/internal/pycore_obmalloc.h \ $(srcdir)/Include/internal/pycore_obmalloc_init.h \ $(srcdir)/Include/internal/pycore_pathconfig.h \ diff --git a/Objects/object.c b/Objects/object.c index 82b957f8abeac1..68a96e872bbfc6 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -54,8 +54,6 @@ _PyObject_CheckConsistency(PyObject *op, int check_content) #ifdef Py_REF_DEBUG -Py_ssize_t _Py_RefTotal; - Py_ssize_t _Py_GetRefTotal(void) { diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 35fbff320f4661..d192677668183e 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -235,6 +235,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 19cb5cf1c80735..3c9c6e86e24e39 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -609,6 +609,9 @@ Include\internal + + Include\internal + Include\internal