@@ -5368,7 +5368,7 @@ init_inline_values(PyObject *obj, PyTypeObject *tp)
53685368 for (int i = 0 ; i < size ; i ++ ) {
53695369 values -> values [i ] = NULL ;
53705370 }
5371- * _PyObject_ValuesPointer ( obj ) = values ;
5371+ _PyDictOrValues_SetValues ( _PyObject_DictOrValuesPointer ( obj ), values ) ;
53725372 return 0 ;
53735373}
53745374
@@ -5394,7 +5394,7 @@ _PyObject_InitializeDict(PyObject *obj)
53945394 if (dict == NULL ) {
53955395 return -1 ;
53965396 }
5397- PyObject * * dictptr = _PyObject_DictPointer (obj );
5397+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
53985398 * dictptr = dict ;
53995399 return 0 ;
54005400}
@@ -5422,7 +5422,6 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
54225422PyObject *
54235423_PyObject_MakeDictFromInstanceAttributes (PyObject * obj , PyDictValues * values )
54245424{
5425- assert (Py_TYPE (obj )-> tp_flags & Py_TPFLAGS_MANAGED_DICT );
54265425 PyDictKeysObject * keys = CACHED_KEYS (Py_TYPE (obj ));
54275426 OBJECT_STAT_INC (dict_materialized_on_request );
54285427 return make_dict_from_instance_attributes (keys , values );
@@ -5458,8 +5457,7 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
54585457 if (dict == NULL ) {
54595458 return -1 ;
54605459 }
5461- * _PyObject_ValuesPointer (obj ) = NULL ;
5462- * _PyObject_ManagedDictPointer (obj ) = dict ;
5460+ _PyObject_DictOrValuesPointer (obj )-> dict = dict ;
54635461 if (value == NULL ) {
54645462 return PyDict_DelItem (dict , name );
54655463 }
@@ -5488,6 +5486,37 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
54885486 return 0 ;
54895487}
54905488
5489+ /* Sanity check for managed dicts */
5490+ #if 0
5491+ #define CHECK (val ) assert(val); if (!(val)) { return 0; }
5492+
5493+ int
5494+ _PyObject_ManagedDictValidityCheck (PyObject * obj )
5495+ {
5496+ PyTypeObject * tp = Py_TYPE (obj );
5497+ CHECK (tp -> tp_flags & Py_TPFLAGS_MANAGED_DICT );
5498+ PyDictOrValues * dorv_ptr = _PyObject_DictOrValuesPointer (obj );
5499+ if (_PyDictOrValues_IsValues (* dorv_ptr )) {
5500+ PyDictValues * values = _PyDictOrValues_GetValues (* dorv_ptr );
5501+ int size = ((uint8_t * )values )[-2 ];
5502+ int count = 0 ;
5503+ PyDictKeysObject * keys = CACHED_KEYS (tp );
5504+ for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5505+ if (values -> values [i ] != NULL ) {
5506+ count ++ ;
5507+ }
5508+ }
5509+ CHECK (size == count );
5510+ }
5511+ else {
5512+ if (dorv_ptr -> dict != NULL ) {
5513+ CHECK (PyDict_Check (dorv_ptr -> dict ));
5514+ }
5515+ }
5516+ return 1 ;
5517+ }
5518+ #endif
5519+
54915520PyObject *
54925521_PyObject_GetInstanceAttribute (PyObject * obj , PyDictValues * values ,
54935522 PyObject * name )
@@ -5511,105 +5540,94 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj)
55115540 if (tp -> tp_dictoffset == 0 ) {
55125541 return 1 ;
55135542 }
5514- PyObject * * dictptr ;
5543+ PyObject * dict ;
55155544 if (tp -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) {
5516- PyDictValues * values = * _PyObject_ValuesPointer (obj );
5517- if (values ) {
5545+ PyDictOrValues dorv = * _PyObject_DictOrValuesPointer (obj );
5546+ if (_PyDictOrValues_IsValues ( dorv ) ) {
55185547 PyDictKeysObject * keys = CACHED_KEYS (tp );
55195548 for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5520- if (values -> values [i ] != NULL ) {
5549+ if (_PyDictOrValues_GetValues ( dorv ) -> values [i ] != NULL ) {
55215550 return 0 ;
55225551 }
55235552 }
55245553 return 1 ;
55255554 }
5526- dictptr = _PyObject_ManagedDictPointer ( obj );
5555+ dict = _PyDictOrValues_GetDict ( dorv );
55275556 }
55285557 else {
5529- dictptr = _PyObject_DictPointer (obj );
5558+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
5559+ dict = * dictptr ;
55305560 }
5531- PyObject * dict = * dictptr ;
55325561 if (dict == NULL ) {
55335562 return 1 ;
55345563 }
55355564 return ((PyDictObject * )dict )-> ma_used == 0 ;
55365565}
55375566
5538-
5539- int
5540- _PyObject_VisitInstanceAttributes (PyObject * self , visitproc visit , void * arg )
5541- {
5542- PyTypeObject * tp = Py_TYPE (self );
5543- assert (Py_TYPE (self )-> tp_flags & Py_TPFLAGS_MANAGED_DICT );
5544- PyDictValues * * values_ptr = _PyObject_ValuesPointer (self );
5545- if (* values_ptr == NULL ) {
5546- return 0 ;
5547- }
5548- PyDictKeysObject * keys = CACHED_KEYS (tp );
5549- for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5550- Py_VISIT ((* values_ptr )-> values [i ]);
5551- }
5552- return 0 ;
5553- }
5554-
5555- void
5556- _PyObject_ClearInstanceAttributes (PyObject * self )
5557- {
5558- PyTypeObject * tp = Py_TYPE (self );
5559- assert (Py_TYPE (self )-> tp_flags & Py_TPFLAGS_MANAGED_DICT );
5560- PyDictValues * * values_ptr = _PyObject_ValuesPointer (self );
5561- if (* values_ptr == NULL ) {
5562- return ;
5563- }
5564- PyDictKeysObject * keys = CACHED_KEYS (tp );
5565- for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5566- Py_CLEAR ((* values_ptr )-> values [i ]);
5567- }
5568- }
5569-
55705567void
55715568_PyObject_FreeInstanceAttributes (PyObject * self )
55725569{
55735570 PyTypeObject * tp = Py_TYPE (self );
55745571 assert (Py_TYPE (self )-> tp_flags & Py_TPFLAGS_MANAGED_DICT );
5575- PyDictValues * * values_ptr = _PyObject_ValuesPointer (self );
5576- if (* values_ptr == NULL ) {
5572+ PyDictOrValues dorv = * _PyObject_DictOrValuesPointer (self );
5573+ if (! _PyDictOrValues_IsValues ( dorv ) ) {
55775574 return ;
55785575 }
5576+ PyDictValues * values = _PyDictOrValues_GetValues (dorv );
55795577 PyDictKeysObject * keys = CACHED_KEYS (tp );
55805578 for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5581- Py_XDECREF (( * values_ptr ) -> values [i ]);
5579+ Py_XDECREF (values -> values [i ]);
55825580 }
5583- free_values (* values_ptr );
5581+ free_values (values );
55845582}
55855583
55865584int
5587- _PyObject_VisitManagedDict (PyObject * self , visitproc visit , void * arg )
5585+ _PyObject_VisitManagedDict (PyObject * obj , visitproc visit , void * arg )
55885586{
5589- PyTypeObject * tp = Py_TYPE (self );
5587+ PyTypeObject * tp = Py_TYPE (obj );
55905588 if ((tp -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) == 0 ) {
55915589 return 0 ;
55925590 }
55935591 assert (tp -> tp_dictoffset );
5594- int err = _PyObject_VisitInstanceAttributes (self , visit , arg );
5595- if (err ) {
5596- return err ;
5592+ PyDictOrValues dorv = * _PyObject_DictOrValuesPointer (obj );
5593+ if (_PyDictOrValues_IsValues (dorv )) {
5594+ PyDictValues * values = _PyDictOrValues_GetValues (dorv );
5595+ PyDictKeysObject * keys = CACHED_KEYS (tp );
5596+ for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5597+ Py_VISIT (values -> values [i ]);
5598+ }
5599+ }
5600+ else {
5601+ PyObject * dict = _PyDictOrValues_GetDict (dorv );
5602+ Py_VISIT (dict );
55975603 }
5598- Py_VISIT (* _PyObject_ManagedDictPointer (self ));
55995604 return 0 ;
56005605}
56015606
5602-
56035607void
5604- _PyObject_ClearManagedDict (PyObject * self )
5608+ _PyObject_ClearManagedDict (PyObject * obj )
56055609{
5606- PyTypeObject * tp = Py_TYPE (self );
5610+ PyTypeObject * tp = Py_TYPE (obj );
56075611 if ((tp -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) == 0 ) {
56085612 return ;
56095613 }
5610- _PyObject_FreeInstanceAttributes (self );
5611- * _PyObject_ValuesPointer (self ) = NULL ;
5612- Py_CLEAR (* _PyObject_ManagedDictPointer (self ));
5614+ PyDictOrValues * dorv_ptr = _PyObject_DictOrValuesPointer (obj );
5615+ if (_PyDictOrValues_IsValues (* dorv_ptr )) {
5616+ PyDictValues * values = _PyDictOrValues_GetValues (* dorv_ptr );
5617+ PyDictKeysObject * keys = CACHED_KEYS (tp );
5618+ for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5619+ Py_CLEAR (values -> values [i ]);
5620+ }
5621+ dorv_ptr -> dict = NULL ;
5622+ free_values (values );
5623+ }
5624+ else {
5625+ PyObject * dict = dorv_ptr -> dict ;
5626+ if (dict ) {
5627+ dorv_ptr -> dict = NULL ;
5628+ Py_DECREF (dict );
5629+ }
5630+ }
56135631}
56145632
56155633PyObject *
@@ -5618,25 +5636,26 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
56185636 PyObject * dict ;
56195637 PyTypeObject * tp = Py_TYPE (obj );
56205638 if (_PyType_HasFeature (tp , Py_TPFLAGS_MANAGED_DICT )) {
5621- PyDictValues * * values_ptr = _PyObject_ValuesPointer (obj );
5622- PyObject * * dictptr = _PyObject_ManagedDictPointer (obj );
5623- if (* values_ptr ) {
5624- assert (* dictptr == NULL );
5639+ PyDictOrValues * dorv_ptr = _PyObject_DictOrValuesPointer (obj );
5640+ if (_PyDictOrValues_IsValues (* dorv_ptr )) {
5641+ PyDictValues * values = _PyDictOrValues_GetValues (* dorv_ptr );
56255642 OBJECT_STAT_INC (dict_materialized_on_request );
5626- * dictptr = dict = make_dict_from_instance_attributes (CACHED_KEYS (tp ), * values_ptr );
5643+ dict = make_dict_from_instance_attributes (CACHED_KEYS (tp ), values );
56275644 if (dict != NULL ) {
5628- * values_ptr = NULL ;
5645+ dorv_ptr -> dict = dict ;
56295646 }
56305647 }
5631- else if (* dictptr == NULL ) {
5632- * dictptr = dict = PyDict_New ();
5633- }
56345648 else {
5635- dict = * dictptr ;
5649+ dict = _PyDictOrValues_GetDict (* dorv_ptr );
5650+ if (dict == NULL ) {
5651+ dictkeys_incref (CACHED_KEYS (tp ));
5652+ dict = new_dict_with_shared_keys (CACHED_KEYS (tp ));
5653+ dorv_ptr -> dict = dict ;
5654+ }
56365655 }
56375656 }
56385657 else {
5639- PyObject * * dictptr = _PyObject_DictPointer (obj );
5658+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
56405659 if (dictptr == NULL ) {
56415660 PyErr_SetString (PyExc_AttributeError ,
56425661 "This object has no __dict__" );
0 commit comments