From a7e58471b0d1f596cc4da823eb6cfd17a9251c76 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 1 Nov 2018 01:46:05 +0100 Subject: [PATCH] bpo-35081: Move _PyObject_GC_TRACK() to pycore_object.h * Create Include/internal/pycore_object.h * Move _PyObject_GC_TRACK() and _PyObject_GC_UNTRACK() macros to pycore_object.h * Remove _PyGC_generation0: replaced with _PyRuntime.gc.generation0 * Replace _PyObject_GC_UNTRACK() with PyObject_GC_UnTrack() in _queuemodule.c. The file is compiled without Py_BUILD_CORE. * Add #include "pycore_object.h" in all C files using _PyObject_GC_TRACK() and/or _PyObject_GC_UNTRACK() --- Include/internal/pycore_mem.h | 3 -- Include/internal/pycore_object.h | 54 ++++++++++++++++++++++++++++++++ Include/objimpl.h | 40 ----------------------- Modules/_io/bufferedio.c | 1 + Modules/_io/bytesio.c | 1 + Modules/_io/fileio.c | 1 + Modules/_io/iobase.c | 1 + Modules/_io/stringio.c | 1 + Modules/_io/textio.c | 1 + Modules/_io/winconsoleio.c | 3 +- Modules/_queuemodule.c | 4 +-- Modules/gcmodule.c | 1 + Objects/bytearrayobject.c | 7 +++-- Objects/bytesobject.c | 4 +-- Objects/call.c | 3 +- Objects/cellobject.c | 1 + Objects/classobject.c | 1 + Objects/descrobject.c | 1 + Objects/dictobject.c | 3 +- Objects/exceptions.c | 1 + Objects/frameobject.c | 4 +-- Objects/funcobject.c | 3 +- Objects/genobject.c | 5 +-- Objects/iterobject.c | 1 + Objects/listobject.c | 3 +- Objects/memoryobject.c | 1 + Objects/methodobject.c | 1 + Objects/odictobject.c | 3 +- Objects/setobject.c | 1 + Objects/sliceobject.c | 1 + Objects/tupleobject.c | 3 +- Objects/typeobject.c | 3 +- Objects/unicodeobject.c | 5 +-- Python/ceval.c | 5 ++- Python/context.c | 5 +-- Python/hamt.c | 3 +- 36 files changed, 109 insertions(+), 70 deletions(-) create mode 100644 Include/internal/pycore_object.h diff --git a/Include/internal/pycore_mem.h b/Include/internal/pycore_mem.h index 4a41b77734ac41..965657237e3900 100644 --- a/Include/internal/pycore_mem.h +++ b/Include/internal/pycore_mem.h @@ -147,9 +147,6 @@ struct _gc_runtime_state { PyAPI_FUNC(void) _PyGC_Initialize(struct _gc_runtime_state *); -#define _PyGC_generation0 _PyRuntime.gc.generation0 - - /* Set the memory allocator of the specified domain to the default. Save the old allocator into *old_alloc if it's non-NULL. Return on success, or return -1 if the domain is unknown. */ diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h new file mode 100644 index 00000000000000..37d88c7ea62cd6 --- /dev/null +++ b/Include/internal/pycore_object.h @@ -0,0 +1,54 @@ +#ifndef Py_INTERNAL_OBECT_H +#define Py_INTERNAL_OBECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "Py_BUILD_CORE must be defined to include this header" +#endif + +#include "pycore_state.h" + +/* Tell the GC to track this object. + * + * NB: While the object is tracked by the collector, it must be safe to call the + * ob_traverse method. + * + * Internal note: _PyRuntime.gc.generation0->_gc_prev doesn't have any bit flags + * because it's not object header. So we don't use _PyGCHead_PREV() and + * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations. + */ +#define _PyObject_GC_TRACK(o) do { \ + PyGC_Head *g = _Py_AS_GC(o); \ + if (g->_gc_next != 0) { \ + Py_FatalError("GC object already tracked"); \ + } \ + assert((g->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0); \ + PyGC_Head *last = (PyGC_Head*)(_PyRuntime.gc.generation0->_gc_prev); \ + _PyGCHead_SET_NEXT(last, g); \ + _PyGCHead_SET_PREV(g, last); \ + _PyGCHead_SET_NEXT(g, _PyRuntime.gc.generation0); \ + _PyRuntime.gc.generation0->_gc_prev = (uintptr_t)g; \ + } while (0); + +/* Tell the GC to stop tracking this object. + * + * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING must + * be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept. + */ +#define _PyObject_GC_UNTRACK(o) do { \ + PyGC_Head *g = _Py_AS_GC(o); \ + PyGC_Head *prev = _PyGCHead_PREV(g); \ + PyGC_Head *next = _PyGCHead_NEXT(g); \ + assert(next != NULL); \ + _PyGCHead_SET_NEXT(prev, next); \ + _PyGCHead_SET_PREV(next, prev); \ + g->_gc_next = 0; \ + g->_gc_prev &= _PyGC_PREV_MASK_FINALIZED; \ + } while (0); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_OBECT_H */ diff --git a/Include/objimpl.h b/Include/objimpl.h index b3d3a81a6c94bc..ba9c00a45d9a4d 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -278,8 +278,6 @@ typedef struct { uintptr_t _gc_prev; } PyGC_Head; -extern PyGC_Head *_PyGC_generation0; - #define _Py_AS_GC(o) ((PyGC_Head *)(o)-1) /* Bit flags for _gc_prev */ @@ -310,44 +308,6 @@ extern PyGC_Head *_PyGC_generation0; #define _PyGC_FINALIZED(o) _PyGCHead_FINALIZED(_Py_AS_GC(o)) #define _PyGC_SET_FINALIZED(o) _PyGCHead_SET_FINALIZED(_Py_AS_GC(o)) -/* Tell the GC to track this object. - * - * NB: While the object is tracked by the collector, it must be safe to call the - * ob_traverse method. - * - * Internal note: _PyGC_generation0->_gc_prev doesn't have any bit flags - * because it's not object header. So we don't use _PyGCHead_PREV() and - * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations. - */ -#define _PyObject_GC_TRACK(o) do { \ - PyGC_Head *g = _Py_AS_GC(o); \ - if (g->_gc_next != 0) { \ - Py_FatalError("GC object already tracked"); \ - } \ - assert((g->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0); \ - PyGC_Head *last = (PyGC_Head*)(_PyGC_generation0->_gc_prev); \ - _PyGCHead_SET_NEXT(last, g); \ - _PyGCHead_SET_PREV(g, last); \ - _PyGCHead_SET_NEXT(g, _PyGC_generation0); \ - _PyGC_generation0->_gc_prev = (uintptr_t)g; \ - } while (0); - -/* Tell the GC to stop tracking this object. - * - * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING must - * be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept. - */ -#define _PyObject_GC_UNTRACK(o) do { \ - PyGC_Head *g = _Py_AS_GC(o); \ - PyGC_Head *prev = _PyGCHead_PREV(g); \ - PyGC_Head *next = _PyGCHead_NEXT(g); \ - assert(next != NULL); \ - _PyGCHead_SET_NEXT(prev, next); \ - _PyGCHead_SET_PREV(next, prev); \ - g->_gc_next = 0; \ - g->_gc_prev &= _PyGC_PREV_MASK_FINALIZED; \ - } while (0); - /* True if the object is currently tracked by the GC. */ #define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 24ae963b2b8961..37953fae27c983 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -9,6 +9,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" #include "pythread.h" diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index a50add2389e561..3c1ea80d927169 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -1,6 +1,7 @@ #include "Python.h" #include "structmember.h" /* for offsetof() */ #include "_iomodule.h" +#include "pycore_object.h" /*[clinic input] module _io diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index ffcb7301295354..c502c430134ef6 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -2,6 +2,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_object.h" #include "structmember.h" #ifdef HAVE_SYS_TYPES_H #include diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 5b71732ef19c65..aaf9aca198e7a5 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -11,6 +11,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" +#include "pycore_object.h" #include "_iomodule.h" /*[clinic input] diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 5a03715fbde04c..9cf64e9407de99 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -2,6 +2,7 @@ #include "Python.h" #include "structmember.h" #include "accu.h" +#include "pycore_object.h" #include "_iomodule.h" /* Implementation note: the buffer is always at least one character longer diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index be427772817a9e..e53a8080e5768b 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -8,6 +8,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_object.h" #include "structmember.h" #include "_iomodule.h" diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 148255c354a495..824690ff58d688 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -8,6 +8,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_object.h" #ifdef MS_WINDOWS @@ -556,7 +557,7 @@ read_console_w(HANDLE handle, DWORD maxlen, DWORD *readlen) { Py_BEGIN_ALLOW_THREADS DWORD off = 0; while (off < maxlen) { - DWORD n = (DWORD)-1; + DWORD n = (DWORD)-1; DWORD len = min(maxlen - off, BUFSIZ); SetLastError(0); BOOL res = ReadConsoleW(handle, &buf[off], len, &n, NULL); diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index 2a9406cc4760b6..f6fb4b66f4e9e0 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -1,6 +1,6 @@ #include "Python.h" -#include "structmember.h" /* offsetof */ #include "pythread.h" +#include "structmember.h" /* offsetof */ /*[clinic input] module _queue @@ -26,7 +26,7 @@ typedef struct { static void simplequeue_dealloc(simplequeueobject *self) { - _PyObject_GC_UNTRACK(self); + PyObject_GC_UnTrack(self); if (self->lock != NULL) { /* Unlock the lock so it's safe to free it */ if (self->locked > 0) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index a54be07b27a854..fcb711d21e2b35 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -26,6 +26,7 @@ #include "Python.h" #include "pycore_context.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" #include "frameobject.h" /* for PyFrame_ClearFreeList */ #include "pydtrace.h" diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 7a0c340c804ee8..06c18b3fcc34f3 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2,12 +2,13 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "pycore_mem.h" -#include "pycore_state.h" -#include "structmember.h" #include "bytes_methods.h" #include "bytesobject.h" +#include "pycore_mem.h" +#include "pycore_object.h" +#include "pycore_state.h" #include "pystrhex.h" +#include "structmember.h" /*[clinic input] class bytearray "PyByteArrayObject *" "&PyByteArray_Type" diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index c912fc04fd4cb8..4dff4135a7ea01 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3,10 +3,10 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "bytes_methods.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" - -#include "bytes_methods.h" #include "pystrhex.h" #include diff --git a/Objects/call.c b/Objects/call.c index 48e3aafe5fe524..d5c458025e8581 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -1,6 +1,7 @@ #include "Python.h" -#include "pycore_state.h" #include "frameobject.h" +#include "pycore_object.h" +#include "pycore_state.h" int diff --git a/Objects/cellobject.c b/Objects/cellobject.c index 0b390c78f04e20..c445b6bdcf32c5 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" PyObject * diff --git a/Objects/classobject.c b/Objects/classobject.c index 93d1c67f1b4358..dbdabb478008c6 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a23b97f396f901..c89b28a01af544 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1,6 +1,7 @@ /* Descriptors -- a new, flexible way to describe attributes */ #include "Python.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" /* Why is this not included in Python.h? */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index ea564a2b7c9f63..1c29f93b11a86d 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -111,8 +111,9 @@ converting the dict to the combined table. #define PyDict_MINSIZE 8 #include "Python.h" -#include "pycore_state.h" #include "dict-common.h" +#include "pycore_object.h" +#include "pycore_state.h" #include "stringlib/eq.h" /* to get unicode_eq() */ /*[clinic input] diff --git a/Objects/exceptions.c b/Objects/exceptions.c index da79260ab3b811..1fe2e196c48c6e 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -7,6 +7,7 @@ #define PY_SSIZE_T_CLEAN #include #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" #include "osdefs.h" diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 7704022dd2e41a..db50cb291b5a5a 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1,11 +1,11 @@ /* Frame object implementation */ #include "Python.h" -#include "pycore_state.h" - #include "code.h" #include "frameobject.h" #include "opcode.h" +#include "pycore_object.h" +#include "pycore_state.h" #include "structmember.h" #define OFF(x) offsetof(PyFrameObject, x) diff --git a/Objects/funcobject.c b/Objects/funcobject.c index e5278f09af2bdd..fa9671ee21560b 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -2,9 +2,10 @@ /* Function object implementation */ #include "Python.h" +#include "code.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" -#include "code.h" #include "structmember.h" PyObject * diff --git a/Objects/genobject.c b/Objects/genobject.c index 7c2948bb52d0f6..0ee968e9f88c98 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1,10 +1,11 @@ /* Generator object implementation */ #include "Python.h" -#include "pycore_state.h" #include "frameobject.h" -#include "structmember.h" #include "opcode.h" +#include "pycore_object.h" +#include "pycore_state.h" +#include "structmember.h" static PyObject *gen_close(PyGenObject *, PyObject *); static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *); diff --git a/Objects/iterobject.c b/Objects/iterobject.c index 23f0639db2f10d..74b156b0107bc4 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" typedef struct { diff --git a/Objects/listobject.c b/Objects/listobject.c index e38b21f2a30b99..2c6cf0e62358a9 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1,8 +1,9 @@ /* List object implementation */ #include "Python.h" -#include "pycore_state.h" #include "accu.h" +#include "pycore_object.h" +#include "pycore_state.h" #ifdef STDC_HEADERS #include diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index f234bb4117dca5..bb4a7a05ec3dfe 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" #include "pystrhex.h" #include diff --git a/Objects/methodobject.c b/Objects/methodobject.c index b0bbfa2f5f9d65..c1a2d88f490cd8 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 52ac7e5f88b0c7..312137fb778074 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -465,9 +465,10 @@ Potential Optimizations */ #include "Python.h" +#include "dict-common.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" -#include "dict-common.h" #include #include "clinic/odictobject.c.h" diff --git a/Objects/setobject.c b/Objects/setobject.c index 42fe80fc050362..5c9758150c77a5 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -32,6 +32,7 @@ */ #include "Python.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 9f1cf78cedd31e..7ccd3be74b436f 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -15,6 +15,7 @@ this type and there is exactly one in existence. #include "Python.h" #include "pycore_mem.h" +#include "pycore_object.h" #include "pycore_state.h" #include "structmember.h" diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index cce266f7a2d211..ece8e20271b950 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -2,8 +2,9 @@ /* Tuple object implementation */ #include "Python.h" -#include "pycore_state.h" #include "accu.h" +#include "pycore_object.h" +#include "pycore_state.h" /*[clinic input] class tuple "PyTupleObject *" "&PyTuple_Type" diff --git a/Objects/typeobject.c b/Objects/typeobject.c index dedc4f7c876431..b89cffb6933314 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1,8 +1,9 @@ /* Type object implementation */ #include "Python.h" -#include "pycore_state.h" #include "frameobject.h" +#include "pycore_object.h" +#include "pycore_state.h" #include "structmember.h" #include diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 3692da64122f86..5a27f754cd01ef 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -40,10 +40,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "pycore_state.h" -#include "ucnhash.h" #include "bytes_methods.h" +#include "pycore_object.h" +#include "pycore_state.h" #include "stringlib/eq.h" +#include "ucnhash.h" #ifdef MS_WINDOWS #include diff --git a/Python/ceval.c b/Python/ceval.c index ac9db1533bf3ef..845955bcd5fe3d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -10,16 +10,15 @@ #define PY_LOCAL_AGGRESSIVE #include "Python.h" -#include "pycore_state.h" - #include "code.h" #include "dictobject.h" #include "frameobject.h" #include "opcode.h" +#include "pycore_object.h" +#include "pycore_state.h" #include "pydtrace.h" #include "setobject.h" #include "structmember.h" - #include #ifdef Py_DEBUG diff --git a/Python/context.c b/Python/context.c index 1fb2a5de2b1b81..9e8b21134beca4 100644 --- a/Python/context.c +++ b/Python/context.c @@ -1,9 +1,10 @@ #include "Python.h" -#include "structmember.h" -#include "pycore_state.h" #include "pycore_context.h" #include "pycore_hamt.h" +#include "pycore_object.h" +#include "pycore_state.h" +#include "structmember.h" #define CONTEXT_FREELIST_MAXLEN 255 diff --git a/Python/hamt.c b/Python/hamt.c index be3813b9aab175..49da24b99eb0fa 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -1,8 +1,9 @@ #include "Python.h" #include "structmember.h" -#include "pycore_state.h" #include "pycore_hamt.h" +#include "pycore_object.h" +#include "pycore_state.h" /* This file provides an implemention of an immutable mapping using the