@@ -11,7 +11,7 @@ extern "C" {
1111
1212#include "pycore_freelist.h" // _PyFreeListState
1313#include "pycore_identifier.h" // _Py_Identifier
14- #include "pycore_object.h" //PyDictOrValues
14+ #include "pycore_object.h" //PyManagedDictPointer
1515
1616// Unsafe flavor of PyDict_GetItemWithError(): no error checking
1717extern PyObject * _PyDict_GetItemWithError (PyObject * dp ,PyObject * key );
@@ -181,6 +181,10 @@ struct _dictkeysobject {
181181 * [-1] = prefix size. [-2] = used size. size[-2-n...] = insertion order.
182182 */
183183struct _dictvalues {
184+ uint8_t capacity ;
185+ uint8_t size ;
186+ uint8_t embedded ;
187+ uint8_t valid ;
184188PyObject * values [1 ];
185189};
186190
@@ -196,6 +200,7 @@ static inline void* _DK_ENTRIES(PyDictKeysObject *dk) {
196200size_t index = (size_t )1 <<dk -> dk_log2_index_bytes ;
197201return (& indices [index ]);
198202}
203+
199204static inline PyDictKeyEntry * DK_ENTRIES (PyDictKeysObject * dk ) {
200205assert (dk -> dk_kind == DICT_KEYS_GENERAL );
201206return (PyDictKeyEntry * )_DK_ENTRIES (dk );
@@ -211,9 +216,6 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
211216#define DICT_WATCHER_MASK ((1 << DICT_MAX_WATCHERS) - 1)
212217#define DICT_WATCHER_AND_MODIFICATION_MASK ((1 << (DICT_MAX_WATCHERS + DICT_WATCHED_MUTATION_BITS)) - 1)
213218
214- #define DICT_VALUES_SIZE (values ) ((uint8_t *)values)[-1]
215- #define DICT_VALUES_USED_SIZE (values ) ((uint8_t *)values)[-2]
216-
217219#ifdef Py_GIL_DISABLED
218220#define DICT_NEXT_VERSION (INTERP ) \
219221 (_Py_atomic_add_uint64(&(INTERP)->dict_state.global_version, DICT_VERSION_INCREMENT) + DICT_VERSION_INCREMENT)
@@ -246,25 +248,63 @@ _PyDict_NotifyEvent(PyInterpreterState *interp,
246248return DICT_NEXT_VERSION (interp ) | (mp -> ma_version_tag & DICT_WATCHER_AND_MODIFICATION_MASK );
247249}
248250
249- extern PyObject * _PyObject_MakeDictFromInstanceAttributes (PyObject * obj , PyDictValues * values );
250- PyAPI_FUNC ( bool ) _PyObject_MakeInstanceAttributesFromDict ( PyObject * obj , PyDictOrValues * dorv );
251+ extern PyDictObject * _PyObject_MakeDictFromInstanceAttributes (PyObject * obj );
252+
251253PyAPI_FUNC (PyObject * )_PyDict_FromItems (
252254PyObject * const * keys ,Py_ssize_t keys_offset ,
253255PyObject * const * values ,Py_ssize_t values_offset ,
254256Py_ssize_t length );
255257
258+ static inline uint8_t *
259+ get_insertion_order_array (PyDictValues * values )
260+ {
261+ return (uint8_t * )& values -> values [values -> capacity ];
262+ }
263+
256264static inline void
257265_PyDictValues_AddToInsertionOrder (PyDictValues * values ,Py_ssize_t ix )
258266{
259267assert (ix < SHARED_KEYS_MAX_SIZE );
260- uint8_t * size_ptr = ((uint8_t * )values )- 2 ;
261- int size = * size_ptr ;
262- assert (size + 2 < DICT_VALUES_SIZE (values ));
263- size ++ ;
264- size_ptr [- size ]= (uint8_t )ix ;
265- * size_ptr = size ;
268+ int size = values -> size ;
269+ uint8_t * array = get_insertion_order_array (values );
270+ assert (size < values -> capacity );
271+ assert (((uint8_t )ix )== ix );
272+ array [size ]= (uint8_t )ix ;
273+ values -> size = size + 1 ;
274+ }
275+
276+ static inline size_t
277+ shared_keys_usable_size (PyDictKeysObject * keys )
278+ {
279+ #ifdef Py_GIL_DISABLED
280+ // dk_usable will decrease for each instance that is created and each
281+ // value that is added. dk_nentries will increase for each value that
282+ // is added. We want to always return the right value or larger.
283+ // We therefore increase dk_nentries first and we decrease dk_usable
284+ // second, and conversely here we read dk_usable first and dk_entries
285+ // second (to avoid the case where we read entries before the increment
286+ // and read usable after the decrement)
287+ return (size_t )(_Py_atomic_load_ssize_acquire (& keys -> dk_usable )+
288+ _Py_atomic_load_ssize_acquire (& keys -> dk_nentries ));
289+ #else
290+ return (size_t )keys -> dk_nentries + (size_t )keys -> dk_usable ;
291+ #endif
266292}
267293
294+ static inline size_t
295+ _PyInlineValuesSize (PyTypeObject * tp )
296+ {
297+ PyDictKeysObject * keys = ((PyHeapTypeObject * )tp )-> ht_cached_keys ;
298+ assert (keys != NULL );
299+ size_t size = shared_keys_usable_size (keys );
300+ size_t prefix_size = _Py_SIZE_ROUND_UP (size ,sizeof (PyObject * ));
301+ assert (prefix_size < 256 );
302+ return prefix_size + (size + 1 )* sizeof (PyObject * );
303+ }
304+
305+ int
306+ _PyDict_DetachFromObject (PyDictObject * dict ,PyObject * obj );
307+
268308#ifdef __cplusplus
269309}
270310#endif