@@ -5368,7 +5368,7 @@ init_inline_values(PyObject *obj, PyTypeObject *tp)
5368
5368
for (int i = 0 ; i < size ; i ++ ) {
5369
5369
values -> values [i ] = NULL ;
5370
5370
}
5371
- * _PyObject_ValuesPointer ( obj ) = values ;
5371
+ _PyDictOrValues_SetValues ( _PyObject_DictOrValuesPointer ( obj ), values ) ;
5372
5372
return 0 ;
5373
5373
}
5374
5374
@@ -5394,7 +5394,7 @@ _PyObject_InitializeDict(PyObject *obj)
5394
5394
if (dict == NULL ) {
5395
5395
return -1 ;
5396
5396
}
5397
- PyObject * * dictptr = _PyObject_DictPointer (obj );
5397
+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
5398
5398
* dictptr = dict ;
5399
5399
return 0 ;
5400
5400
}
@@ -5422,7 +5422,6 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
5422
5422
PyObject *
5423
5423
_PyObject_MakeDictFromInstanceAttributes (PyObject * obj , PyDictValues * values )
5424
5424
{
5425
- assert (Py_TYPE (obj )-> tp_flags & Py_TPFLAGS_MANAGED_DICT );
5426
5425
PyDictKeysObject * keys = CACHED_KEYS (Py_TYPE (obj ));
5427
5426
OBJECT_STAT_INC (dict_materialized_on_request );
5428
5427
return make_dict_from_instance_attributes (keys , values );
@@ -5458,8 +5457,7 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
5458
5457
if (dict == NULL ) {
5459
5458
return -1 ;
5460
5459
}
5461
- * _PyObject_ValuesPointer (obj ) = NULL ;
5462
- * _PyObject_ManagedDictPointer (obj ) = dict ;
5460
+ _PyObject_DictOrValuesPointer (obj )-> dict = dict ;
5463
5461
if (value == NULL ) {
5464
5462
return PyDict_DelItem (dict , name );
5465
5463
}
@@ -5488,6 +5486,37 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
5488
5486
return 0 ;
5489
5487
}
5490
5488
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
+
5491
5520
PyObject *
5492
5521
_PyObject_GetInstanceAttribute (PyObject * obj , PyDictValues * values ,
5493
5522
PyObject * name )
@@ -5511,105 +5540,94 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj)
5511
5540
if (tp -> tp_dictoffset == 0 ) {
5512
5541
return 1 ;
5513
5542
}
5514
- PyObject * * dictptr ;
5543
+ PyObject * dict ;
5515
5544
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 ) ) {
5518
5547
PyDictKeysObject * keys = CACHED_KEYS (tp );
5519
5548
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 ) {
5521
5550
return 0 ;
5522
5551
}
5523
5552
}
5524
5553
return 1 ;
5525
5554
}
5526
- dictptr = _PyObject_ManagedDictPointer ( obj );
5555
+ dict = _PyDictOrValues_GetDict ( dorv );
5527
5556
}
5528
5557
else {
5529
- dictptr = _PyObject_DictPointer (obj );
5558
+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
5559
+ dict = * dictptr ;
5530
5560
}
5531
- PyObject * dict = * dictptr ;
5532
5561
if (dict == NULL ) {
5533
5562
return 1 ;
5534
5563
}
5535
5564
return ((PyDictObject * )dict )-> ma_used == 0 ;
5536
5565
}
5537
5566
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
-
5570
5567
void
5571
5568
_PyObject_FreeInstanceAttributes (PyObject * self )
5572
5569
{
5573
5570
PyTypeObject * tp = Py_TYPE (self );
5574
5571
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 ) ) {
5577
5574
return ;
5578
5575
}
5576
+ PyDictValues * values = _PyDictOrValues_GetValues (dorv );
5579
5577
PyDictKeysObject * keys = CACHED_KEYS (tp );
5580
5578
for (Py_ssize_t i = 0 ; i < keys -> dk_nentries ; i ++ ) {
5581
- Py_XDECREF (( * values_ptr ) -> values [i ]);
5579
+ Py_XDECREF (values -> values [i ]);
5582
5580
}
5583
- free_values (* values_ptr );
5581
+ free_values (values );
5584
5582
}
5585
5583
5586
5584
int
5587
- _PyObject_VisitManagedDict (PyObject * self , visitproc visit , void * arg )
5585
+ _PyObject_VisitManagedDict (PyObject * obj , visitproc visit , void * arg )
5588
5586
{
5589
- PyTypeObject * tp = Py_TYPE (self );
5587
+ PyTypeObject * tp = Py_TYPE (obj );
5590
5588
if ((tp -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) == 0 ) {
5591
5589
return 0 ;
5592
5590
}
5593
5591
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 );
5597
5603
}
5598
- Py_VISIT (* _PyObject_ManagedDictPointer (self ));
5599
5604
return 0 ;
5600
5605
}
5601
5606
5602
-
5603
5607
void
5604
- _PyObject_ClearManagedDict (PyObject * self )
5608
+ _PyObject_ClearManagedDict (PyObject * obj )
5605
5609
{
5606
- PyTypeObject * tp = Py_TYPE (self );
5610
+ PyTypeObject * tp = Py_TYPE (obj );
5607
5611
if ((tp -> tp_flags & Py_TPFLAGS_MANAGED_DICT ) == 0 ) {
5608
5612
return ;
5609
5613
}
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
+ }
5613
5631
}
5614
5632
5615
5633
PyObject *
@@ -5618,25 +5636,26 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
5618
5636
PyObject * dict ;
5619
5637
PyTypeObject * tp = Py_TYPE (obj );
5620
5638
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 );
5625
5642
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 );
5627
5644
if (dict != NULL ) {
5628
- * values_ptr = NULL ;
5645
+ dorv_ptr -> dict = dict ;
5629
5646
}
5630
5647
}
5631
- else if (* dictptr == NULL ) {
5632
- * dictptr = dict = PyDict_New ();
5633
- }
5634
5648
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
+ }
5636
5655
}
5637
5656
}
5638
5657
else {
5639
- PyObject * * dictptr = _PyObject_DictPointer (obj );
5658
+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
5640
5659
if (dictptr == NULL ) {
5641
5660
PyErr_SetString (PyExc_AttributeError ,
5642
5661
"This object has no __dict__" );
0 commit comments