@@ -16,19 +16,20 @@ As of Python 3.6, this is compact and ordered. Basic idea is described here:
1616
1717layout:
1818
19- +---------------+
20- | dk_refcnt |
21- | dk_log2_size |
22- | dk_kind |
23- | dk_usable |
24- | dk_nentries |
25- +---------------+
26- | dk_indices |
27- | |
28- +---------------+
29- | dk_entries |
30- | |
31- +---------------+
19+ +---------------------+
20+ | dk_refcnt |
21+ | dk_log2_size |
22+ | dk_log2_index_bytes |
23+ | dk_kind |
24+ | dk_usable |
25+ | dk_nentries |
26+ +---------------------+
27+ | dk_indices[] |
28+ | |
29+ +---------------------+
30+ | dk_entries[] |
31+ | |
32+ +---------------------+
3233
3334dk_indices is actual hashtable. It holds index in entries, or DKIX_EMPTY(-1)
3435or DKIX_DUMMY(-2).
@@ -444,6 +445,7 @@ estimate_log2_keysize(Py_ssize_t n)
444445static PyDictKeysObject empty_keys_struct = {
445446 1 , /* dk_refcnt */
446447 0 , /* dk_log2_size */
448+ 0 , /* dk_log2_index_bytes */
447449 DICT_KEYS_SPLIT , /* dk_kind */
448450 1 , /* dk_version */
449451 0 , /* dk_usable (immutable) */
@@ -562,24 +564,25 @@ static PyDictKeysObject*
562564new_keys_object (uint8_t log2_size )
563565{
564566 PyDictKeysObject * dk ;
565- Py_ssize_t es , usable ;
567+ Py_ssize_t usable ;
568+ int log2_bytes ;
566569
567570 assert (log2_size >= PyDict_LOG_MINSIZE );
568571
569572 usable = USABLE_FRACTION (1 <<log2_size );
570- if (log2_size <= 7 ) {
571- es = 1 ;
573+ if (log2_size < 8 ) {
574+ log2_bytes = log2_size ;
572575 }
573- else if (log2_size <= 15 ) {
574- es = 2 ;
576+ else if (log2_size < 16 ) {
577+ log2_bytes = log2_size + 1 ;
575578 }
576579#if SIZEOF_VOID_P > 4
577- else if (log2_size <= 31 ) {
578- es = 4 ;
580+ else if (log2_size >= 32 ) {
581+ log2_bytes = log2_size + 3 ;
579582 }
580583#endif
581584 else {
582- es = sizeof ( Py_ssize_t ) ;
585+ log2_bytes = log2_size + 2 ;
583586 }
584587
585588#if PyDict_MAXFREELIST > 0
@@ -595,7 +598,7 @@ new_keys_object(uint8_t log2_size)
595598#endif
596599 {
597600 dk = PyObject_Malloc (sizeof (PyDictKeysObject )
598- + (es << log2_size )
601+ + (( size_t ) 1 << log2_bytes )
599602 + sizeof (PyDictKeyEntry ) * usable );
600603 if (dk == NULL ) {
601604 PyErr_NoMemory ();
@@ -607,11 +610,12 @@ new_keys_object(uint8_t log2_size)
607610#endif
608611 dk -> dk_refcnt = 1 ;
609612 dk -> dk_log2_size = log2_size ;
613+ dk -> dk_log2_index_bytes = log2_bytes ;
610614 dk -> dk_kind = DICT_KEYS_UNICODE ;
611615 dk -> dk_nentries = 0 ;
612616 dk -> dk_usable = usable ;
613617 dk -> dk_version = 0 ;
614- memset (& dk -> dk_indices [0 ], 0xff , es << log2_size );
618+ memset (& dk -> dk_indices [0 ], 0xff , (( size_t ) 1 << log2_bytes ) );
615619 memset (DK_ENTRIES (dk ), 0 , sizeof (PyDictKeyEntry ) * usable );
616620 return dk ;
617621}
0 commit comments