From 16746d924599f0d18eaa04124406c495c817d4d2 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 26 Jul 2022 15:10:34 +0100 Subject: [PATCH 1/2] Move weakreflist into the pre-header. --- Include/internal/pycore_object.h | 2 +- Objects/typeobject.c | 34 +++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 173d36784cf138..ab7657a672ba4e 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -263,7 +263,7 @@ extern int _Py_CheckSlotResult( // Test if a type supports weak references static inline int _PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) { - return (type->tp_weaklistoffset > 0); + return (type->tp_weaklistoffset != 0); } extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0801d9f3d5f1c6..59d4973742acdf 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2483,8 +2483,9 @@ subtype_getweakref(PyObject *obj, void *context) return NULL; } _PyObject_ASSERT((PyObject *)type, - type->tp_weaklistoffset > 0); + type->tp_weaklistoffset != 0); _PyObject_ASSERT((PyObject *)type, + (type->tp_weaklistoffset == -4 * ((int)sizeof(PyObject *))) || ((type->tp_weaklistoffset + sizeof(PyObject *)) <= (size_t)(type->tp_basicsize))); weaklistptr = (PyObject **)((char *)obj + type->tp_weaklistoffset); @@ -3078,19 +3079,28 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) } } - if (ctx->add_dict && ctx->base->tp_itemsize) { - type->tp_dictoffset = -(long)sizeof(PyObject *); - slotoffset += sizeof(PyObject *); + if (ctx->add_dict) { + if (ctx->base->tp_itemsize) { + type->tp_dictoffset = -(long)sizeof(PyObject *); + slotoffset += sizeof(PyObject *); + } + else { + assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); + type->tp_flags |= Py_TPFLAGS_MANAGED_DICT; + } } if (ctx->add_weak) { assert(!ctx->base->tp_itemsize); - type->tp_weaklistoffset = slotoffset; - slotoffset += sizeof(PyObject *); + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + type->tp_weaklistoffset = -4 * sizeof(PyObject *); + } + else { + type->tp_weaklistoffset = slotoffset; + slotoffset += sizeof(PyObject *); + } } - if (ctx->add_dict && ctx->base->tp_itemsize == 0) { - assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); - type->tp_flags |= Py_TPFLAGS_MANAGED_DICT; + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { type->tp_dictoffset = -slotoffset - sizeof(PyObject *)*3; } @@ -5070,11 +5080,13 @@ compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char* !same_slots_added(newbase, oldbase))) { goto differs; } - /* The above does not check for managed __dicts__ */ + /* The above does not check for managed __dict__ or __weakref__ */ if ((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == ((newto->tp_flags & Py_TPFLAGS_MANAGED_DICT))) { - return 1; + if (oldto->tp_weaklistoffset == newto->tp_weaklistoffset) { + return 1; + } } differs: PyErr_Format(PyExc_TypeError, From bcf23ceeda8f82152103cf7f925d4b17bdcf959e Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 4 Aug 2022 16:04:30 +0100 Subject: [PATCH 2/2] Add news --- .../2022-08-04-16-04-18.gh-issue-95245.N4gOUV.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-08-04-16-04-18.gh-issue-95245.N4gOUV.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-04-16-04-18.gh-issue-95245.N4gOUV.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-04-16-04-18.gh-issue-95245.N4gOUV.rst new file mode 100644 index 00000000000000..4449ddd8ded8a0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-04-16-04-18.gh-issue-95245.N4gOUV.rst @@ -0,0 +1,3 @@ +Reduces the size of a "simple" Python object from 8 to 6 words by moving the +weakreflist pointer into the pre-header directly before the object's +dict/values pointer.