Skip to content

Commit 1202a47

Browse files
committed
Issue 23261: Clean-up the hack to store the set.pop() search finger in a hash field instead of the setobject.
1 parent a556af7 commit 1202a47

File tree

3 files changed

+15
-25
lines changed

3 files changed

+15
-25
lines changed

Include/setobject.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ extern "C" {
1414
2. Active: key != NULL and key != dummy
1515
3. Dummy: key == dummy
1616
17-
Note: .pop() abuses the hash field of an Unused or Dummy slot to
18-
hold a search finger. The hash field of Unused or Dummy slots has
19-
no meaning otherwise.
17+
The hash field of Unused or Dummy slots have no meaning.
2018
*/
2119

2220
#define PySet_MINSIZE 8
@@ -59,6 +57,7 @@ typedef struct _setobject {
5957
Py_hash_t hash; /* Only used by frozenset objects */
6058
setentry smalltable[PySet_MINSIZE];
6159

60+
Py_ssize_t finger; /* Search finger for pop() */
6261
PyObject *weakreflist; /* List of weak references */
6362
} PySetObject;
6463

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ def delx(self): del self.__x
994994
# frozenset
995995
PySet_MINSIZE = 8
996996
samples = [[], range(10), range(50)]
997-
s = size('3n2P' + PySet_MINSIZE*'nP' + 'nP')
997+
s = size('3n2P' + PySet_MINSIZE*'nP' + '2nP')
998998
for sample in samples:
999999
minused = len(sample)
10001000
if minused == 0: tmp = 1

Objects/setobject.c

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -668,32 +668,22 @@ set_pop(PySetObject *so)
668668
return NULL;
669669
}
670670

671-
/* Set entry to "the first" unused or dummy set entry. We abuse
672-
* the hash field of slot 0 to hold a search finger:
673-
* If slot 0 has a value, use slot 0.
674-
* Else slot 0 is being used to hold a search finger,
675-
* and we use its hash value as the first index to look.
671+
i = so->finger;
672+
/* This may be a legit search finger, or it may be a once legit
673+
* search finger that's out of bounds now (due to wrapping or
674+
* resizing). We simply make sure it's in bounds now.
676675
*/
677-
entry = &so->table[0];
678-
if (entry->key == NULL || entry->key == dummy) {
679-
i = entry->hash;
680-
/* The hash field may be a real hash value, or it may be a
681-
* legit search finger, or it may be a once-legit search
682-
* finger that's out of bounds now because it wrapped around
683-
* or the table shrunk -- simply make sure it's in bounds now.
684-
*/
685-
if (i > so->mask || i < 1)
686-
i = 1; /* skip slot 0 */
687-
while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
688-
i++;
689-
if (i > so->mask)
690-
i = 1;
691-
}
676+
if (i > so->mask)
677+
i = 0;
678+
while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
679+
i++;
680+
if (i > so->mask)
681+
i = 0;
692682
}
693683
key = entry->key;
694684
entry->key = dummy;
695685
so->used--;
696-
so->table[0].hash = i + 1; /* next place to start */
686+
so->finger = i + 1; /* next place to start */
697687
return key;
698688
}
699689

@@ -1012,6 +1002,7 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
10121002
so->table = so->smalltable;
10131003
so->lookup = set_lookkey_unicode;
10141004
so->hash = -1;
1005+
so->finger = 0;
10151006
so->weakreflist = NULL;
10161007

10171008
if (iterable != NULL) {

0 commit comments

Comments
 (0)