diff options
author | Mark Shannon <mark@hotpy.org> | 2021-12-07 16:02:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-07 16:02:53 (GMT) |
commit | 8319114feedd2a5b77378bba24eb9fb2689c5033 (patch) | |
tree | b96bfa2c7b8d36124b713170f421f653360a4b5c /Modules/gcmodule.c | |
parent | c7e7a4b969b5728d4b4f3c59bf98e1e830d5c6d6 (diff) | |
download | cpython-8319114feedd2a5b77378bba24eb9fb2689c5033.zip cpython-8319114feedd2a5b77378bba24eb9fb2689c5033.tar.gz cpython-8319114feedd2a5b77378bba24eb9fb2689c5033.tar.bz2 |
bpo-45947: Place dict and values pointer at fixed (negative) offset just before GC header. (GH-29879)
* Place __dict__ immediately before GC header for plain Python objects.
* Fix up lazy dict creation logic to use managed dict pointers.
* Manage values pointer, placing them directly before managed dict pointers.
* Convert hint-based load/store attr specialization target managed dict classes.
* Specialize LOAD_METHOD for managed dict objects.
* Remove unsafe _PyObject_GC_Calloc function.
* Remove unsafe _PyObject_GC_Malloc() function.
* Add comment explaning use of Py_TPFLAGS_MANAGED_DICT.
Diffstat (limited to 'Modules/gcmodule.c')
-rw-r--r-- | Modules/gcmodule.c | 64 |
1 files changed, 29 insertions, 35 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index b505676..1808057 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -69,10 +69,10 @@ module gc #define NEXT_MASK_UNREACHABLE (1) /* Get an object's GC head */ -#define AS_GC(o) ((PyGC_Head *)(o)-1) +#define AS_GC(o) ((PyGC_Head *)(((char *)(o))-sizeof(PyGC_Head))) /* Get the object given the GC head */ -#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) +#define FROM_GC(g) ((PyObject *)(((char *)(g))+sizeof(PyGC_Head))) static inline int gc_is_collecting(PyGC_Head *g) @@ -2231,28 +2231,14 @@ PyObject_IS_GC(PyObject *obj) return _PyObject_IS_GC(obj); } -static PyObject * -_PyObject_GC_Alloc(int use_calloc, size_t basicsize) +void +_PyObject_GC_Link(PyObject *op) { + PyGC_Head *g = AS_GC(op); + assert(((uintptr_t)g & (sizeof(uintptr_t)-1)) == 0); // g must be correctly aligned + PyThreadState *tstate = _PyThreadState_GET(); GCState *gcstate = &tstate->interp->gc; - if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) { - return _PyErr_NoMemory(tstate); - } - size_t size = sizeof(PyGC_Head) + basicsize; - - PyGC_Head *g; - if (use_calloc) { - g = (PyGC_Head *)PyObject_Calloc(1, size); - } - else { - g = (PyGC_Head *)PyObject_Malloc(size); - } - if (g == NULL) { - return _PyErr_NoMemory(tstate); - } - assert(((uintptr_t)g & 3) == 0); // g must be aligned 4bytes boundary - g->_gc_next = 0; g->_gc_prev = 0; gcstate->generations[0].count++; /* number of allocated GC objects */ @@ -2266,26 +2252,32 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize) gc_collect_generations(tstate); gcstate->collecting = 0; } - PyObject *op = FROM_GC(g); - return op; } -PyObject * -_PyObject_GC_Malloc(size_t basicsize) -{ - return _PyObject_GC_Alloc(0, basicsize); -} - -PyObject * -_PyObject_GC_Calloc(size_t basicsize) +static PyObject * +gc_alloc(size_t basicsize, size_t presize) { - return _PyObject_GC_Alloc(1, basicsize); + PyThreadState *tstate = _PyThreadState_GET(); + if (basicsize > PY_SSIZE_T_MAX - presize) { + return _PyErr_NoMemory(tstate); + } + size_t size = presize + basicsize; + char *mem = PyObject_Malloc(size); + if (mem == NULL) { + return _PyErr_NoMemory(tstate); + } + ((PyObject **)mem)[0] = NULL; + ((PyObject **)mem)[1] = NULL; + PyObject *op = (PyObject *)(mem + presize); + _PyObject_GC_Link(op); + return op; } PyObject * _PyObject_GC_New(PyTypeObject *tp) { - PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); + size_t presize = _PyType_PreHeaderSize(tp); + PyObject *op = gc_alloc(_PyObject_SIZE(tp), presize); if (op == NULL) { return NULL; } @@ -2303,8 +2295,9 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) PyErr_BadInternalCall(); return NULL; } + size_t presize = _PyType_PreHeaderSize(tp); size = _PyObject_VAR_SIZE(tp, nitems); - op = (PyVarObject *) _PyObject_GC_Malloc(size); + op = (PyVarObject *)gc_alloc(size, presize); if (op == NULL) { return NULL; } @@ -2333,6 +2326,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) void PyObject_GC_Del(void *op) { + size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); PyGC_Head *g = AS_GC(op); if (_PyObject_GC_IS_TRACKED(op)) { gc_list_remove(g); @@ -2341,7 +2335,7 @@ PyObject_GC_Del(void *op) if (gcstate->generations[0].count > 0) { gcstate->generations[0].count--; } - PyObject_Free(g); + PyObject_Free(((char *)op)-presize); } int |