Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1e34468

Browse files
authored
dict: Add dk_log2_index_bytes (GH-31439)
1 parent 090e5c4 commit 1e34468

2 files changed

Lines changed: 31 additions & 24 deletions

File tree

Include/internal/pycore_dict.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ struct _dictkeysobject {
6868
/* Size of the hash table (dk_indices). It must be a power of 2. */
6969
uint8_t dk_log2_size;
7070

71+
/* Size of the hash table (dk_indices) by bytes. */
72+
uint8_t dk_log2_index_bytes;
73+
7174
/* Kind of keys */
7275
uint8_t dk_kind;
7376

@@ -129,7 +132,7 @@ struct _dictvalues {
129132
2 : sizeof(int32_t))
130133
#endif
131134
#define DK_ENTRIES(dk) \
132-
((PyDictKeyEntry*)(&((int8_t*)((dk)->dk_indices))[DK_SIZE(dk) * DK_IXSIZE(dk)]))
135+
((PyDictKeyEntry*)(&((int8_t*)((dk)->dk_indices))[(size_t)1 << (dk)->dk_log2_index_bytes]))
133136

134137
extern uint64_t _pydict_global_version;
135138

Objects/dictobject.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,20 @@ As of Python 3.6, this is compact and ordered. Basic idea is described here:
1616
1717
layout:
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
3334
dk_indices is actual hashtable. It holds index in entries, or DKIX_EMPTY(-1)
3435
or DKIX_DUMMY(-2).
@@ -444,6 +445,7 @@ estimate_log2_keysize(Py_ssize_t n)
444445
static 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*
562564
new_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

Comments
 (0)