diff options
author | Mark Shannon <mark@hotpy.org> | 2022-08-16 12:57:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-16 12:57:18 (GMT) |
commit | 5a8c15819c27c516e5b75b7c9d89eacdb16b77c3 (patch) | |
tree | b75d585f24f97aac724952a75175cc9f15af48af /Objects | |
parent | 829aab859266253320317caabdb0e17fa4e0f05e (diff) | |
download | cpython-5a8c15819c27c516e5b75b7c9d89eacdb16b77c3.zip cpython-5a8c15819c27c516e5b75b7c9d89eacdb16b77c3.tar.gz cpython-5a8c15819c27c516e5b75b7c9d89eacdb16b77c3.tar.bz2 |
GH-95245: Move weakreflist into the pre-header. (GH-95996)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 67dfc6f..c881aeb 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2497,10 +2497,11 @@ subtype_getweakref(PyObject *obj, void *context) return NULL; } _PyObject_ASSERT((PyObject *)type, - type->tp_weaklistoffset > 0); + type->tp_weaklistoffset > 0 || + type->tp_weaklistoffset == MANAGED_WEAKREF_OFFSET); _PyObject_ASSERT((PyObject *)type, - ((type->tp_weaklistoffset + sizeof(PyObject *)) - <= (size_t)(type->tp_basicsize))); + ((type->tp_weaklistoffset + (Py_ssize_t)sizeof(PyObject *)) + <= type->tp_basicsize)); weaklistptr = (PyObject **)((char *)obj + type->tp_weaklistoffset); if (*weaklistptr == NULL) result = Py_None; @@ -3093,9 +3094,9 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) } if (ctx->add_weak) { - assert(!ctx->base->tp_itemsize); - type->tp_weaklistoffset = slotoffset; - slotoffset += sizeof(PyObject *); + assert((type->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF) == 0); + type->tp_flags |= Py_TPFLAGS_MANAGED_WEAKREF; + type->tp_weaklistoffset = MANAGED_WEAKREF_OFFSET; } if (ctx->add_dict) { assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); @@ -5116,9 +5117,9 @@ compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char* !same_slots_added(newbase, oldbase))) { goto differs; } - /* The above does not check for managed __dicts__ */ - if ((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == - ((newto->tp_flags & Py_TPFLAGS_MANAGED_DICT))) + /* The above does not check for the preheader */ + if ((oldto->tp_flags & Py_TPFLAGS_PREHEADER) == + ((newto->tp_flags & Py_TPFLAGS_PREHEADER))) { return 1; } @@ -5217,7 +5218,7 @@ object_set_class(PyObject *self, PyObject *value, void *closure) if (compatible_for_assignment(oldto, newto, "__class__")) { /* Changing the class will change the implicit dict keys, * so we must materialize the dictionary first. */ - assert((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == (newto->tp_flags & Py_TPFLAGS_MANAGED_DICT)); + assert((oldto->tp_flags & Py_TPFLAGS_PREHEADER) == (newto->tp_flags & Py_TPFLAGS_PREHEADER)); _PyObject_GetDictPtr(self); if (oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT && _PyDictOrValues_IsValues(*_PyObject_DictOrValuesPointer(self))) @@ -5360,7 +5361,7 @@ object_getstate_default(PyObject *obj, int required) { basicsize += sizeof(PyObject *); } - if (Py_TYPE(obj)->tp_weaklistoffset) { + if (Py_TYPE(obj)->tp_weaklistoffset > 0) { basicsize += sizeof(PyObject *); } if (slotnames != Py_None) { @@ -6150,7 +6151,7 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) if (type->tp_clear == NULL) type->tp_clear = base->tp_clear; } - type->tp_flags |= (base->tp_flags & Py_TPFLAGS_MANAGED_DICT); + type->tp_flags |= (base->tp_flags & Py_TPFLAGS_PREHEADER); if (type->tp_basicsize == 0) type->tp_basicsize = base->tp_basicsize; @@ -6571,7 +6572,7 @@ type_ready_fill_dict(PyTypeObject *type) } static int -type_ready_dict_offset(PyTypeObject *type) +type_ready_preheader(PyTypeObject *type) { if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { if (type->tp_dictoffset > 0 || type->tp_dictoffset < -1) { @@ -6583,6 +6584,18 @@ type_ready_dict_offset(PyTypeObject *type) } type->tp_dictoffset = -1; } + if (type->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF) { + if (type->tp_weaklistoffset != 0 && + type->tp_weaklistoffset != MANAGED_WEAKREF_OFFSET) + { + PyErr_Format(PyExc_TypeError, + "type %s has the Py_TPFLAGS_MANAGED_WEAKREF flag " + "but tp_weaklistoffset is set", + type->tp_name); + return -1; + } + type->tp_weaklistoffset = MANAGED_WEAKREF_OFFSET; + } return 0; } @@ -6802,7 +6815,7 @@ type_ready_post_checks(PyTypeObject *type) return -1; } } - else if (type->tp_dictoffset < sizeof(PyObject)) { + else if (type->tp_dictoffset < (Py_ssize_t)sizeof(PyObject)) { if (type->tp_dictoffset + type->tp_basicsize <= 0) { PyErr_Format(PyExc_SystemError, "type %s has a tp_dictoffset that is too small"); @@ -6847,7 +6860,7 @@ type_ready(PyTypeObject *type) if (type_ready_inherit(type) < 0) { return -1; } - if (type_ready_dict_offset(type) < 0) { + if (type_ready_preheader(type) < 0) { return -1; } if (type_ready_set_hash(type) < 0) { |