From 40e547dfbb9052ca0c667b242f6825ed1c23c195 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 5 Feb 2020 01:11:10 +0100 Subject: [PATCH] bpo-39542: Make _Py_NewReference() opaque in C API (GH-18346) _Py_NewReference() becomes a regular opaque function, rather than a static inline function in the C API (object.h), to better hide implementation details. Move _Py_tracemalloc_config from public pymem.h to internal pycore_pymem.h header. Make _Py_AddToAllObjects() private. --- Include/internal/pycore_pymem.h | 34 ++++++++++++++++++++++++++++++++ Include/object.h | 21 ++------------------ Include/pymem.h | 35 --------------------------------- Modules/_tracemalloc.c | 1 + Objects/object.c | 18 ++++++++++++++++- 5 files changed, 54 insertions(+), 55 deletions(-) diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h index 06d0d06c75c..db153e0bd2d 100644 --- a/Include/internal/pycore_pymem.h +++ b/Include/internal/pycore_pymem.h @@ -169,6 +169,40 @@ PyAPI_FUNC(int) _PyMem_GetAllocatorName( PYMEM_ALLOCATOR_NOT_SET does nothing. */ PyAPI_FUNC(int) _PyMem_SetupAllocators(PyMemAllocatorName allocator); +/* bpo-35053: Expose _Py_tracemalloc_config for _Py_NewReference() + which access directly _Py_tracemalloc_config.tracing for best + performances. */ +struct _PyTraceMalloc_Config { + /* Module initialized? + Variable protected by the GIL */ + enum { + TRACEMALLOC_NOT_INITIALIZED, + TRACEMALLOC_INITIALIZED, + TRACEMALLOC_FINALIZED + } initialized; + + /* Is tracemalloc tracing memory allocations? + Variable protected by the GIL */ + int tracing; + + /* limit of the number of frames in a traceback, 1 by default. + Variable protected by the GIL. */ + int max_nframe; + + /* use domain in trace key? + Variable protected by the GIL. */ + int use_domain; +}; + +#define _PyTraceMalloc_Config_INIT \ + {.initialized = TRACEMALLOC_NOT_INITIALIZED, \ + .tracing = 0, \ + .max_nframe = 1, \ + .use_domain = 0} + +PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config; + + #ifdef __cplusplus } #endif diff --git a/Include/object.h b/Include/object.h index 175a208f0d2..8dccbf16971 100644 --- a/Include/object.h +++ b/Include/object.h @@ -1,8 +1,6 @@ #ifndef Py_OBJECT_H #define Py_OBJECT_H -#include "pymem.h" /* _Py_tracemalloc_config */ - #ifdef __cplusplus extern "C" { #endif @@ -390,28 +388,13 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void); when a memory block is reused from a free list. */ PyAPI_FUNC(int) _PyTraceMalloc_NewReference(PyObject *op); +PyAPI_FUNC(void) _Py_NewReference(PyObject *op); + #ifdef Py_TRACE_REFS /* Py_TRACE_REFS is such major surgery that we call external routines. */ PyAPI_FUNC(void) _Py_ForgetReference(PyObject *); -PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force); #endif - -static inline void _Py_NewReference(PyObject *op) -{ - if (_Py_tracemalloc_config.tracing) { - _PyTraceMalloc_NewReference(op); - } -#ifdef Py_REF_DEBUG - _Py_RefTotal++; -#endif - Py_REFCNT(op) = 1; -#ifdef Py_TRACE_REFS - _Py_AddToAllObjects(op, 1); -#endif -} - - PyAPI_FUNC(void) _Py_Dealloc(PyObject *); static inline void _Py_INCREF(PyObject *op) diff --git a/Include/pymem.h b/Include/pymem.h index 07b380aa6e7..607feb9484f 100644 --- a/Include/pymem.h +++ b/Include/pymem.h @@ -101,41 +101,6 @@ PyAPI_FUNC(void) PyMem_Free(void *ptr); #define PyMem_Del PyMem_Free #define PyMem_DEL PyMem_FREE -/* bpo-35053: expose _Py_tracemalloc_config for performance: - _Py_NewReference() needs an efficient check to test if tracemalloc is - tracing. - - It has to be defined in pymem.h, before object.h is included. */ -struct _PyTraceMalloc_Config { - /* Module initialized? - Variable protected by the GIL */ - enum { - TRACEMALLOC_NOT_INITIALIZED, - TRACEMALLOC_INITIALIZED, - TRACEMALLOC_FINALIZED - } initialized; - - /* Is tracemalloc tracing memory allocations? - Variable protected by the GIL */ - int tracing; - - /* limit of the number of frames in a traceback, 1 by default. - Variable protected by the GIL. */ - int max_nframe; - - /* use domain in trace key? - Variable protected by the GIL. */ - int use_domain; -}; - -PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config; - -#define _PyTraceMalloc_Config_INIT \ - {.initialized = TRACEMALLOC_NOT_INITIALIZED, \ - .tracing = 0, \ - .max_nframe = 1, \ - .use_domain = 0} - #ifndef Py_LIMITED_API # define Py_CPYTHON_PYMEM_H diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 70219721b51..ddf6ef4e11d 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "pycore_pymem.h" #include "pycore_traceback.h" #include "hashtable.h" #include "frameobject.h" diff --git a/Objects/object.c b/Objects/object.c index 085605ae367..e6bfad4e729 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -93,7 +93,7 @@ static PyObject refchain = {&refchain, &refchain}; * way, though; exceptions include statically allocated type objects, and * statically allocated singletons (like Py_True and Py_None). */ -void +static void _Py_AddToAllObjects(PyObject *op, int force) { #ifdef Py_DEBUG @@ -1805,6 +1805,22 @@ _PyTypes_Init(void) } +void +_Py_NewReference(PyObject *op) +{ + if (_Py_tracemalloc_config.tracing) { + _PyTraceMalloc_NewReference(op); + } +#ifdef Py_REF_DEBUG + _Py_RefTotal++; +#endif + Py_REFCNT(op) = 1; +#ifdef Py_TRACE_REFS + _Py_AddToAllObjects(op, 1); +#endif +} + + #ifdef Py_TRACE_REFS void _Py_ForgetReference(PyObject *op)