@@ -2497,10 +2497,11 @@ subtype_getweakref(PyObject *obj, void *context)
24972497 return NULL ;
24982498 }
24992499 _PyObject_ASSERT ((PyObject * )type ,
2500- type -> tp_weaklistoffset > 0 );
2500+ type -> tp_weaklistoffset > 0 ||
2501+ type -> tp_weaklistoffset == MANAGED_WEAKREF_OFFSET );
25012502 _PyObject_ASSERT ((PyObject * )type ,
2502- ((type -> tp_weaklistoffset + sizeof (PyObject * ))
2503- <= ( size_t )( type -> tp_basicsize ) ));
2503+ ((type -> tp_weaklistoffset + ( Py_ssize_t ) sizeof (PyObject * ))
2504+ <= type -> tp_basicsize ));
25042505 weaklistptr = (PyObject * * )((char * )obj + type -> tp_weaklistoffset );
25052506 if (* weaklistptr == NULL )
25062507 result = Py_None ;
@@ -3093,9 +3094,9 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type)
30933094 }
30943095
30953096 if (ctx -> add_weak ) {
3096- assert (! ctx -> base -> tp_itemsize );
3097- type -> tp_weaklistoffset = slotoffset ;
3098- slotoffset += sizeof ( PyObject * ) ;
3097+ assert (( type -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ) == 0 );
3098+ type -> tp_flags |= Py_TPFLAGS_MANAGED_WEAKREF ;
3099+ type -> tp_weaklistoffset = MANAGED_WEAKREF_OFFSET ;
30993100 }
31003101 if (ctx -> add_dict ) {
31013102 assert ((type -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) == 0 );
@@ -5116,9 +5117,9 @@ compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char*
51165117 !same_slots_added (newbase , oldbase ))) {
51175118 goto differs ;
51185119 }
5119- /* The above does not check for managed __dicts__ */
5120- if ((oldto -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) ==
5121- ((newto -> tp_flags & Py_TPFLAGS_MANAGED_DICT )))
5120+ /* The above does not check for the preheader */
5121+ if ((oldto -> tp_flags & Py_TPFLAGS_PREHEADER ) ==
5122+ ((newto -> tp_flags & Py_TPFLAGS_PREHEADER )))
51225123 {
51235124 return 1 ;
51245125 }
@@ -5217,7 +5218,7 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
52175218 if (compatible_for_assignment (oldto , newto , "__class__" )) {
52185219 /* Changing the class will change the implicit dict keys,
52195220 * so we must materialize the dictionary first. */
5220- assert ((oldto -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) == (newto -> tp_flags & Py_TPFLAGS_MANAGED_DICT ));
5221+ assert ((oldto -> tp_flags & Py_TPFLAGS_PREHEADER ) == (newto -> tp_flags & Py_TPFLAGS_PREHEADER ));
52215222 _PyObject_GetDictPtr (self );
52225223 if (oldto -> tp_flags & Py_TPFLAGS_MANAGED_DICT &&
52235224 _PyDictOrValues_IsValues (* _PyObject_DictOrValuesPointer (self )))
@@ -5360,7 +5361,7 @@ object_getstate_default(PyObject *obj, int required)
53605361 {
53615362 basicsize += sizeof (PyObject * );
53625363 }
5363- if (Py_TYPE (obj )-> tp_weaklistoffset ) {
5364+ if (Py_TYPE (obj )-> tp_weaklistoffset > 0 ) {
53645365 basicsize += sizeof (PyObject * );
53655366 }
53665367 if (slotnames != Py_None ) {
@@ -6150,7 +6151,7 @@ inherit_special(PyTypeObject *type, PyTypeObject *base)
61506151 if (type -> tp_clear == NULL )
61516152 type -> tp_clear = base -> tp_clear ;
61526153 }
6153- type -> tp_flags |= (base -> tp_flags & Py_TPFLAGS_MANAGED_DICT );
6154+ type -> tp_flags |= (base -> tp_flags & Py_TPFLAGS_PREHEADER );
61546155
61556156 if (type -> tp_basicsize == 0 )
61566157 type -> tp_basicsize = base -> tp_basicsize ;
@@ -6571,7 +6572,7 @@ type_ready_fill_dict(PyTypeObject *type)
65716572}
65726573
65736574static int
6574- type_ready_dict_offset (PyTypeObject * type )
6575+ type_ready_preheader (PyTypeObject * type )
65756576{
65766577 if (type -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) {
65776578 if (type -> tp_dictoffset > 0 || type -> tp_dictoffset < -1 ) {
@@ -6583,6 +6584,18 @@ type_ready_dict_offset(PyTypeObject *type)
65836584 }
65846585 type -> tp_dictoffset = -1 ;
65856586 }
6587+ if (type -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ) {
6588+ if (type -> tp_weaklistoffset != 0 &&
6589+ type -> tp_weaklistoffset != MANAGED_WEAKREF_OFFSET )
6590+ {
6591+ PyErr_Format (PyExc_TypeError ,
6592+ "type %s has the Py_TPFLAGS_MANAGED_WEAKREF flag "
6593+ "but tp_weaklistoffset is set" ,
6594+ type -> tp_name );
6595+ return -1 ;
6596+ }
6597+ type -> tp_weaklistoffset = MANAGED_WEAKREF_OFFSET ;
6598+ }
65866599 return 0 ;
65876600}
65886601
@@ -6802,7 +6815,7 @@ type_ready_post_checks(PyTypeObject *type)
68026815 return -1 ;
68036816 }
68046817 }
6805- else if (type -> tp_dictoffset < sizeof (PyObject )) {
6818+ else if (type -> tp_dictoffset < ( Py_ssize_t ) sizeof (PyObject )) {
68066819 if (type -> tp_dictoffset + type -> tp_basicsize <= 0 ) {
68076820 PyErr_Format (PyExc_SystemError ,
68086821 "type %s has a tp_dictoffset that is too small" );
@@ -6847,7 +6860,7 @@ type_ready(PyTypeObject *type)
68476860 if (type_ready_inherit (type ) < 0 ) {
68486861 return -1 ;
68496862 }
6850- if (type_ready_dict_offset (type ) < 0 ) {
6863+ if (type_ready_preheader (type ) < 0 ) {
68516864 return -1 ;
68526865 }
68536866 if (type_ready_set_hash (type ) < 0 ) {
0 commit comments