Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Objects/setobject.c
Line
Count
Source (jump to first uncovered line)
1
2
/* set object implementation
3
4
   Written and maintained by Raymond D. Hettinger <python@rcn.com>
5
   Derived from Objects/dictobject.c.
6
7
   The basic lookup function used by all operations.
8
   This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
9
10
   The initial probe index is computed as hash mod the table size.
11
   Subsequent probe indices are computed as explained in Objects/dictobject.c.
12
13
   To improve cache locality, each probe inspects a series of consecutive
14
   nearby entries before moving on to probes elsewhere in memory.  This leaves
15
   us with a hybrid of linear probing and randomized probing.  The linear probing
16
   reduces the cost of hash collisions because consecutive memory accesses
17
   tend to be much cheaper than scattered probes.  After LINEAR_PROBES steps,
18
   we then use more of the upper bits from the hash value and apply a simple
19
   linear congruential random number generator.  This helps break-up long
20
   chains of collisions.
21
22
   All arithmetic on hash should ignore overflow.
23
24
   Unlike the dictionary implementation, the lookkey function can return
25
   NULL if the rich comparison returns an error.
26
27
   Use cases for sets differ considerably from dictionaries where looked-up
28
   keys are more likely to be present.  In contrast, sets are primarily
29
   about membership testing where the presence of an element is not known in
30
   advance.  Accordingly, the set implementation needs to optimize for both
31
   the found and not-found case.
32
*/
33
34
#include "Python.h"
35
#include "pycore_ceval.h"               // _PyEval_GetBuiltin()
36
#include "pycore_critical_section.h"    // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
37
#include "pycore_dict.h"                // _PyDict_Contains_KnownHash()
38
#include "pycore_modsupport.h"          // _PyArg_NoKwnames()
39
#include "pycore_object.h"              // _PyObject_GC_UNTRACK()
40
#include "pycore_pyatomic_ft_wrappers.h"  // FT_ATOMIC_LOAD_SSIZE_RELAXED()
41
#include "pycore_pyerrors.h"            // _PyErr_SetKeyError()
42
#include "pycore_setobject.h"           // _PySet_NextEntry() definition
43
#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
44
45
#include "stringlib/eq.h"               // unicode_eq()
46
#include <stddef.h>                     // offsetof()
47
#include "clinic/setobject.c.h"
48
49
/*[clinic input]
50
class set "PySetObject *" "&PySet_Type"
51
class frozenset "PySetObject *" "&PyFrozenSet_Type"
52
[clinic start generated code]*/
53
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=97ad1d3e9f117079]*/
54
55
/*[python input]
56
class setobject_converter(self_converter):
57
    type = "PySetObject *"
58
[python start generated code]*/
59
/*[python end generated code: output=da39a3ee5e6b4b0d input=33a44506d4d57793]*/
60
61
/* Object used as dummy key to fill deleted entries */
62
static PyObject _dummy_struct;
63
64
9.08M
#define dummy (&_dummy_struct)
65
66
67
/* ======================================================================== */
68
/* ======= Begin logic for probing the hash table ========================= */
69
70
/* Set this to zero to turn-off linear probing */
71
#ifndef LINEAR_PROBES
72
61.4M
#define LINEAR_PROBES 9
73
#endif
74
75
/* This must be >= 1 */
76
6.02M
#define PERTURB_SHIFT 5
77
78
static setentry *
79
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
80
44.0M
{
81
44.0M
    setentry *table;
82
44.0M
    setentry *entry;
83
44.0M
    size_t perturb = hash;
84
44.0M
    size_t mask = so->mask;
85
44.0M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
86
44.0M
    int probes;
87
44.0M
    int cmp;
88
89
50.0M
    while (1) {
90
50.0M
        entry = &so->table[i];
91
50.0M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
92
57.7M
        do {
93
57.7M
            if (entry->hash == 0 && entry->key == NULL)
94
31.1M
                return entry;
95
26.6M
            if (entry->hash == hash) {
96
12.9M
                PyObject *startkey = entry->key;
97
12.9M
                assert(startkey != dummy);
98
12.9M
                if (startkey == key)
99
12.9M
                    return entry;
100
3.08k
                if (PyUnicode_CheckExact(startkey)
101
3.08k
                    && PyUnicode_CheckExact(key)
102
3.08k
                    && unicode_eq(startkey, key))
103
1.15k
                    return entry;
104
1.93k
                table = so->table;
105
1.93k
                Py_INCREF(startkey);
106
1.93k
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
107
1.93k
                Py_DECREF(startkey);
108
1.93k
                if (cmp < 0)
109
0
                    return NULL;
110
1.93k
                if (table != so->table || entry->key != startkey)
111
0
                    return set_lookkey(so, key, hash);
112
1.93k
                if (cmp > 0)
113
1.93k
                    return entry;
114
0
                mask = so->mask;
115
0
            }
116
13.6M
            entry++;
117
13.6M
        } while (probes--);
118
5.98M
        perturb >>= PERTURB_SHIFT;
119
5.98M
        i = (i * 5 + 1 + perturb) & mask;
120
5.98M
    }
121
44.0M
}
122
123
static int set_table_resize(PySetObject *, Py_ssize_t);
124
125
static int
126
set_add_entry_takeref(PySetObject *so, PyObject *key, Py_hash_t hash)
127
695k
{
128
695k
    setentry *table;
129
695k
    setentry *freeslot;
130
695k
    setentry *entry;
131
695k
    size_t perturb;
132
695k
    size_t mask;
133
695k
    size_t i;                       /* Unsigned for defined overflow behavior */
134
695k
    int probes;
135
695k
    int cmp;
136
137
695k
  restart:
138
139
695k
    mask = so->mask;
140
695k
    i = (size_t)hash & mask;
141
695k
    freeslot = NULL;
142
695k
    perturb = hash;
143
144
740k
    while (1) {
145
740k
        entry = &so->table[i];
146
740k
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
147
827k
        do {
148
827k
            if (entry->hash == 0 && entry->key == NULL)
149
412k
                goto found_unused_or_dummy;
150
415k
            if (entry->hash == hash) {
151
282k
                PyObject *startkey = entry->key;
152
282k
                assert(startkey != dummy);
153
282k
                if (startkey == key)
154
14.2k
                    goto found_active;
155
268k
                if (PyUnicode_CheckExact(startkey)
156
268k
                    && PyUnicode_CheckExact(key)
157
268k
                    && unicode_eq(startkey, key))
158
268k
                    goto found_active;
159
3
                table = so->table;
160
3
                Py_INCREF(startkey);
161
3
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
162
3
                Py_DECREF(startkey);
163
3
                if (cmp > 0)
164
0
                    goto found_active;
165
3
                if (cmp < 0)
166
0
                    goto comparison_error;
167
3
                if (table != so->table || entry->key != startkey)
168
0
                    goto restart;
169
3
                mask = so->mask;
170
3
            }
171
132k
            else if (entry->hash == -1) {
172
0
                assert (entry->key == dummy);
173
0
                freeslot = entry;
174
0
            }
175
132k
            entry++;
176
132k
        } while (probes--);
177
45.0k
        perturb >>= PERTURB_SHIFT;
178
45.0k
        i = (i * 5 + 1 + perturb) & mask;
179
45.0k
    }
180
181
412k
  found_unused_or_dummy:
182
412k
    if (freeslot == NULL)
183
412k
        goto found_unused;
184
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
185
0
    freeslot->key = key;
186
0
    freeslot->hash = hash;
187
0
    return 0;
188
189
412k
  found_unused:
190
412k
    so->fill++;
191
412k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
192
412k
    entry->key = key;
193
412k
    entry->hash = hash;
194
412k
    if ((size_t)so->fill*5 < mask*3)
195
399k
        return 0;
196
13.0k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
197
198
282k
  found_active:
199
282k
    Py_DECREF(key);
200
282k
    return 0;
201
202
0
  comparison_error:
203
0
    Py_DECREF(key);
204
0
    return -1;
205
412k
}
206
207
static int
208
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
209
693k
{
210
693k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
211
212
693k
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
213
693k
}
214
215
static void
216
set_unhashable_type(PyObject *key)
217
0
{
218
0
    PyObject *exc = PyErr_GetRaisedException();
219
0
    assert(exc != NULL);
220
0
    if (!Py_IS_TYPE(exc, (PyTypeObject*)PyExc_TypeError)) {
221
0
        PyErr_SetRaisedException(exc);
222
0
        return;
223
0
    }
224
225
0
    PyErr_Format(PyExc_TypeError,
226
0
                 "cannot use '%T' as a set element (%S)",
227
0
                 key, exc);
228
0
    Py_DECREF(exc);
229
0
}
230
231
int
232
_PySet_AddTakeRef(PySetObject *so, PyObject *key)
233
1.49k
{
234
1.49k
    Py_hash_t hash = _PyObject_HashFast(key);
235
1.49k
    if (hash == -1) {
236
0
        set_unhashable_type(key);
237
0
        Py_DECREF(key);
238
0
        return -1;
239
0
    }
240
    // We don't pre-increment here, the caller holds a strong
241
    // reference to the object which we are stealing.
242
1.49k
    return set_add_entry_takeref(so, key, hash);
243
1.49k
}
244
245
/*
246
Internal routine used by set_table_resize() to insert an item which is
247
known to be absent from the set.  Besides the performance benefit,
248
there is also safety benefit since using set_add_entry() risks making
249
a callback in the middle of a set_table_resize(), see issue 1456209.
250
The caller is responsible for updating the key's reference count and
251
the setobject's fill and used fields.
252
*/
253
static void
254
set_insert_clean(setentry *table, size_t mask, PyObject *key, Py_hash_t hash)
255
139k
{
256
139k
    setentry *entry;
257
139k
    size_t perturb = hash;
258
139k
    size_t i = (size_t)hash & mask;
259
139k
    size_t j;
260
261
140k
    while (1) {
262
140k
        entry = &table[i];
263
140k
        if (entry->key == NULL)
264
131k
            goto found_null;
265
9.19k
        if (i + LINEAR_PROBES <= mask) {
266
8.89k
            for (j = 0; j < LINEAR_PROBES; j++) {
267
8.89k
                entry++;
268
8.89k
                if (entry->key == NULL)
269
7.86k
                    goto found_null;
270
8.89k
            }
271
7.86k
        }
272
1.32k
        perturb >>= PERTURB_SHIFT;
273
1.32k
        i = (i * 5 + 1 + perturb) & mask;
274
1.32k
    }
275
139k
  found_null:
276
139k
    entry->key = key;
277
139k
    entry->hash = hash;
278
139k
}
279
280
/* ======== End logic for probing the hash table ========================== */
281
/* ======================================================================== */
282
283
/*
284
Restructure the table by allocating a new table and reinserting all
285
keys again.  When entries have been deleted, the new table may
286
actually be smaller than the old one.
287
*/
288
static int
289
set_table_resize(PySetObject *so, Py_ssize_t minused)
290
17.8k
{
291
17.8k
    setentry *oldtable, *newtable, *entry;
292
17.8k
    Py_ssize_t oldmask = so->mask;
293
17.8k
    size_t newmask;
294
17.8k
    int is_oldtable_malloced;
295
17.8k
    setentry small_copy[PySet_MINSIZE];
296
297
17.8k
    assert(minused >= 0);
298
299
    /* Find the smallest table size > minused. */
300
    /* XXX speed-up with intrinsics */
301
17.8k
    size_t newsize = PySet_MINSIZE;
302
56.7k
    while (newsize <= (size_t)minused) {
303
38.9k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
304
38.9k
    }
305
306
    /* Get space for a new table. */
307
17.8k
    oldtable = so->table;
308
17.8k
    assert(oldtable != NULL);
309
17.8k
    is_oldtable_malloced = oldtable != so->smalltable;
310
311
17.8k
    if (newsize == PySet_MINSIZE) {
312
        /* A large table is shrinking, or we can't get any smaller. */
313
0
        newtable = so->smalltable;
314
0
        if (newtable == oldtable) {
315
0
            if (so->fill == so->used) {
316
                /* No dummies, so no point doing anything. */
317
0
                return 0;
318
0
            }
319
            /* We're not going to resize it, but rebuild the
320
               table anyway to purge old dummy entries.
321
               Subtle:  This is *necessary* if fill==size,
322
               as set_lookkey needs at least one virgin slot to
323
               terminate failing searches.  If fill < size, it's
324
               merely desirable, as dummies slow searches. */
325
0
            assert(so->fill > so->used);
326
0
            memcpy(small_copy, oldtable, sizeof(small_copy));
327
0
            oldtable = small_copy;
328
0
        }
329
0
    }
330
17.8k
    else {
331
17.8k
        newtable = PyMem_NEW(setentry, newsize);
332
17.8k
        if (newtable == NULL) {
333
0
            PyErr_NoMemory();
334
0
            return -1;
335
0
        }
336
17.8k
    }
337
338
    /* Make the set empty, using the new table. */
339
17.8k
    assert(newtable != oldtable);
340
17.8k
    memset(newtable, 0, sizeof(setentry) * newsize);
341
17.8k
    so->mask = newsize - 1;
342
17.8k
    so->table = newtable;
343
344
    /* Copy the data over; this is refcount-neutral for active entries;
345
       dummy entries aren't copied over, of course */
346
17.8k
    newmask = (size_t)so->mask;
347
17.8k
    if (so->fill == so->used) {
348
267k
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
349
250k
            if (entry->key != NULL) {
350
134k
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
351
134k
            }
352
250k
        }
353
17.8k
    } else {
354
0
        so->fill = so->used;
355
0
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
356
0
            if (entry->key != NULL && entry->key != dummy) {
357
0
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
358
0
            }
359
0
        }
360
0
    }
361
362
17.8k
    if (is_oldtable_malloced)
363
2.89k
        PyMem_Free(oldtable);
364
17.8k
    return 0;
365
17.8k
}
366
367
static int
368
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
369
43.9M
{
370
43.9M
    setentry *entry;
371
372
43.9M
    entry = set_lookkey(so, key, hash);
373
43.9M
    if (entry != NULL)
374
43.9M
        return entry->key != NULL;
375
0
    return -1;
376
43.9M
}
377
378
57.2k
#define DISCARD_NOTFOUND 0
379
1.16k
#define DISCARD_FOUND 1
380
381
static int
382
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
383
58.4k
{
384
58.4k
    setentry *entry;
385
58.4k
    PyObject *old_key;
386
387
58.4k
    entry = set_lookkey(so, key, hash);
388
58.4k
    if (entry == NULL)
389
0
        return -1;
390
58.4k
    if (entry->key == NULL)
391
57.2k
        return DISCARD_NOTFOUND;
392
1.16k
    old_key = entry->key;
393
1.16k
    entry->key = dummy;
394
1.16k
    entry->hash = -1;
395
1.16k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
396
1.16k
    Py_DECREF(old_key);
397
1.16k
    return DISCARD_FOUND;
398
58.4k
}
399
400
static int
401
set_add_key(PySetObject *so, PyObject *key)
402
662k
{
403
662k
    Py_hash_t hash = _PyObject_HashFast(key);
404
662k
    if (hash == -1) {
405
0
        set_unhashable_type(key);
406
0
        return -1;
407
0
    }
408
662k
    return set_add_entry(so, key, hash);
409
662k
}
410
411
static int
412
set_contains_key(PySetObject *so, PyObject *key)
413
43.9M
{
414
43.9M
    Py_hash_t hash = _PyObject_HashFast(key);
415
43.9M
    if (hash == -1) {
416
0
        set_unhashable_type(key);
417
0
        return -1;
418
0
    }
419
43.9M
    return set_contains_entry(so, key, hash);
420
43.9M
}
421
422
static int
423
set_discard_key(PySetObject *so, PyObject *key)
424
58.4k
{
425
58.4k
    Py_hash_t hash = _PyObject_HashFast(key);
426
58.4k
    if (hash == -1) {
427
0
        set_unhashable_type(key);
428
0
        return -1;
429
0
    }
430
58.4k
    return set_discard_entry(so, key, hash);
431
58.4k
}
432
433
static void
434
set_empty_to_minsize(PySetObject *so)
435
160
{
436
160
    memset(so->smalltable, 0, sizeof(so->smalltable));
437
160
    so->fill = 0;
438
160
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
439
160
    so->mask = PySet_MINSIZE - 1;
440
160
    so->table = so->smalltable;
441
160
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
442
160
}
443
444
static int
445
set_clear_internal(PyObject *self)
446
160
{
447
160
    PySetObject *so = _PySet_CAST(self);
448
160
    setentry *entry;
449
160
    setentry *table = so->table;
450
160
    Py_ssize_t fill = so->fill;
451
160
    Py_ssize_t used = so->used;
452
160
    int table_is_malloced = table != so->smalltable;
453
160
    setentry small_copy[PySet_MINSIZE];
454
455
160
    assert (PyAnySet_Check(so));
456
160
    assert(table != NULL);
457
458
    /* This is delicate.  During the process of clearing the set,
459
     * decrefs can cause the set to mutate.  To avoid fatal confusion
460
     * (voice of experience), we have to make the set empty before
461
     * clearing the slots, and never refer to anything via so->ref while
462
     * clearing.
463
     */
464
160
    if (table_is_malloced)
465
0
        set_empty_to_minsize(so);
466
467
160
    else if (fill > 0) {
468
        /* It's a small table with something that needs to be cleared.
469
         * Afraid the only safe way is to copy the set entries into
470
         * another small table first.
471
         */
472
160
        memcpy(small_copy, table, sizeof(small_copy));
473
160
        table = small_copy;
474
160
        set_empty_to_minsize(so);
475
160
    }
476
    /* else it's a small table that's already empty */
477
478
    /* Now we can finally clear things.  If C had refcounts, we could
479
     * assert that the refcount on table is 1 now, i.e. that this function
480
     * has unique access to it, so decref side-effects can't alter it.
481
     */
482
863
    for (entry = table; used > 0; entry++) {
483
703
        if (entry->key && entry->key != dummy) {
484
160
            used--;
485
160
            Py_DECREF(entry->key);
486
160
        }
487
703
    }
488
489
160
    if (table_is_malloced)
490
0
        PyMem_Free(table);
491
160
    return 0;
492
160
}
493
494
/*
495
 * Iterate over a set table.  Use like so:
496
 *
497
 *     Py_ssize_t pos;
498
 *     setentry *entry;
499
 *     pos = 0;   # important!  pos should not otherwise be changed by you
500
 *     while (set_next(yourset, &pos, &entry)) {
501
 *              Refer to borrowed reference in entry->key.
502
 *     }
503
 *
504
 * CAUTION:  In general, it isn't safe to use set_next in a loop that
505
 * mutates the table.
506
 */
507
static int
508
set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
509
9.56M
{
510
9.56M
    Py_ssize_t i;
511
9.56M
    Py_ssize_t mask;
512
9.56M
    setentry *entry;
513
514
9.56M
    assert (PyAnySet_Check(so));
515
9.56M
    i = *pos_ptr;
516
9.56M
    assert(i >= 0);
517
9.56M
    mask = so->mask;
518
9.56M
    entry = &so->table[i];
519
31.1M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
520
21.6M
        i++;
521
21.6M
        entry++;
522
21.6M
    }
523
9.56M
    *pos_ptr = i+1;
524
9.56M
    if (i > mask)
525
1.15M
        return 0;
526
8.40M
    assert(entry != NULL);
527
8.40M
    *entry_ptr = entry;
528
8.40M
    return 1;
529
9.56M
}
530
531
static void
532
set_dealloc(PyObject *self)
533
739k
{
534
739k
    PySetObject *so = _PySet_CAST(self);
535
739k
    setentry *entry;
536
739k
    Py_ssize_t used = so->used;
537
538
    /* bpo-31095: UnTrack is needed before calling any callbacks */
539
739k
    PyObject_GC_UnTrack(so);
540
739k
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
541
542
2.04M
    for (entry = so->table; used > 0; entry++) {
543
1.30M
        if (entry->key && entry->key != dummy) {
544
457k
                used--;
545
457k
                Py_DECREF(entry->key);
546
457k
        }
547
1.30M
    }
548
739k
    if (so->table != so->smalltable)
549
14.5k
        PyMem_Free(so->table);
550
739k
    Py_TYPE(so)->tp_free(so);
551
739k
}
552
553
static PyObject *
554
set_repr_lock_held(PySetObject *so)
555
0
{
556
0
    PyObject *result=NULL, *keys, *listrepr, *tmp;
557
0
    int status = Py_ReprEnter((PyObject*)so);
558
559
0
    if (status != 0) {
560
0
        if (status < 0)
561
0
            return NULL;
562
0
        return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name);
563
0
    }
564
565
    /* shortcut for the empty set */
566
0
    if (!so->used) {
567
0
        Py_ReprLeave((PyObject*)so);
568
0
        return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name);
569
0
    }
570
571
    // gh-129967: avoid PySequence_List because it might re-lock the object
572
    // lock or the GIL and allow something to clear the set from underneath us.
573
0
    keys = PyList_New(so->used);
574
0
    if (keys == NULL) {
575
0
        goto done;
576
0
    }
577
578
0
    Py_ssize_t pos = 0, idx = 0;
579
0
    setentry *entry;
580
0
    while (set_next(so, &pos, &entry)) {
581
0
        PyList_SET_ITEM(keys, idx++, Py_NewRef(entry->key));
582
0
    }
583
584
    /* repr(keys)[1:-1] */
585
0
    listrepr = PyObject_Repr(keys);
586
0
    Py_DECREF(keys);
587
0
    if (listrepr == NULL)
588
0
        goto done;
589
0
    tmp = PyUnicode_Substring(listrepr, 1, PyUnicode_GET_LENGTH(listrepr)-1);
590
0
    Py_DECREF(listrepr);
591
0
    if (tmp == NULL)
592
0
        goto done;
593
0
    listrepr = tmp;
594
595
0
    if (!PySet_CheckExact(so))
596
0
        result = PyUnicode_FromFormat("%s({%U})",
597
0
                                      Py_TYPE(so)->tp_name,
598
0
                                      listrepr);
599
0
    else
600
0
        result = PyUnicode_FromFormat("{%U}", listrepr);
601
0
    Py_DECREF(listrepr);
602
0
done:
603
0
    Py_ReprLeave((PyObject*)so);
604
0
    return result;
605
0
}
606
607
static PyObject *
608
set_repr(PyObject *self)
609
0
{
610
0
    PySetObject *so = _PySet_CAST(self);
611
0
    PyObject *result;
612
0
    Py_BEGIN_CRITICAL_SECTION(so);
613
0
    result = set_repr_lock_held(so);
614
0
    Py_END_CRITICAL_SECTION();
615
0
    return result;
616
0
}
617
618
static Py_ssize_t
619
set_len(PyObject *self)
620
314k
{
621
314k
    PySetObject *so = _PySet_CAST(self);
622
314k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
623
314k
}
624
625
static int
626
set_merge_lock_held(PySetObject *so, PyObject *otherset)
627
87.8k
{
628
87.8k
    PySetObject *other;
629
87.8k
    PyObject *key;
630
87.8k
    Py_ssize_t i;
631
87.8k
    setentry *so_entry;
632
87.8k
    setentry *other_entry;
633
634
87.8k
    assert (PyAnySet_Check(so));
635
87.8k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
636
87.8k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
637
638
87.8k
    other = _PySet_CAST(otherset);
639
87.8k
    if (other == so || other->used == 0)
640
        /* a.update(a) or a.update(set()); nothing to do */
641
49.9k
        return 0;
642
    /* Do one big resize at the start, rather than
643
     * incrementally resizing as we insert new keys.  Expect
644
     * that there will be no (or few) overlapping keys.
645
     */
646
37.8k
    if ((so->fill + other->used)*5 >= so->mask*3) {
647
4.78k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
648
0
            return -1;
649
4.78k
    }
650
37.8k
    so_entry = so->table;
651
37.8k
    other_entry = other->table;
652
653
    /* If our table is empty, and both tables have the same size, and
654
       there are no dummies to eliminate, then just copy the pointers. */
655
37.8k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
656
264k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
657
238k
            key = other_entry->key;
658
238k
            if (key != NULL) {
659
59.4k
                assert(so_entry->key == NULL);
660
59.4k
                so_entry->key = Py_NewRef(key);
661
59.4k
                so_entry->hash = other_entry->hash;
662
59.4k
            }
663
238k
        }
664
25.8k
        so->fill = other->fill;
665
25.8k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
666
25.8k
        return 0;
667
25.8k
    }
668
669
    /* If our table is empty, we can use set_insert_clean() */
670
11.9k
    if (so->fill == 0) {
671
708
        setentry *newtable = so->table;
672
708
        size_t newmask = (size_t)so->mask;
673
708
        so->fill = other->used;
674
708
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
675
27.4k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
676
26.7k
            key = other_entry->key;
677
26.7k
            if (key != NULL && key != dummy) {
678
5.41k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
679
5.41k
                                 other_entry->hash);
680
5.41k
            }
681
26.7k
        }
682
708
        return 0;
683
708
    }
684
685
    /* We can't assure there are no duplicates, so do normal insertions */
686
118k
    for (i = 0; i <= other->mask; i++) {
687
107k
        other_entry = &other->table[i];
688
107k
        key = other_entry->key;
689
107k
        if (key != NULL && key != dummy) {
690
30.8k
            if (set_add_entry(so, key, other_entry->hash))
691
0
                return -1;
692
30.8k
        }
693
107k
    }
694
11.2k
    return 0;
695
11.2k
}
696
697
/*[clinic input]
698
@critical_section
699
set.pop
700
    so: setobject
701
702
Remove and return an arbitrary set element.
703
704
Raises KeyError if the set is empty.
705
[clinic start generated code]*/
706
707
static PyObject *
708
set_pop_impl(PySetObject *so)
709
/*[clinic end generated code: output=4d65180f1271871b input=9296c84921125060]*/
710
105
{
711
    /* Make sure the search finger is in bounds */
712
105
    setentry *entry = so->table + (so->finger & so->mask);
713
105
    setentry *limit = so->table + so->mask;
714
105
    PyObject *key;
715
716
105
    if (so->used == 0) {
717
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
718
0
        return NULL;
719
0
    }
720
641
    while (entry->key == NULL || entry->key==dummy) {
721
536
        entry++;
722
536
        if (entry > limit)
723
0
            entry = so->table;
724
536
    }
725
105
    key = entry->key;
726
105
    entry->key = dummy;
727
105
    entry->hash = -1;
728
105
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
729
105
    so->finger = entry - so->table + 1;   /* next place to start */
730
105
    return key;
731
105
}
732
733
static int
734
set_traverse(PyObject *self, visitproc visit, void *arg)
735
1.13M
{
736
1.13M
    PySetObject *so = _PySet_CAST(self);
737
1.13M
    Py_ssize_t pos = 0;
738
1.13M
    setentry *entry;
739
740
9.43M
    while (set_next(so, &pos, &entry))
741
8.29M
        Py_VISIT(entry->key);
742
1.13M
    return 0;
743
1.13M
}
744
745
/* Work to increase the bit dispersion for closely spaced hash values.
746
   This is important because some use cases have many combinations of a
747
   small number of elements with nearby hashes so that many distinct
748
   combinations collapse to only a handful of distinct hash values. */
749
750
static Py_uhash_t
751
_shuffle_bits(Py_uhash_t h)
752
1.28k
{
753
1.28k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
754
1.28k
}
755
756
/* Most of the constants in this hash algorithm are randomly chosen
757
   large primes with "interesting bit patterns" and that passed tests
758
   for good collision statistics on a variety of problematic datasets
759
   including powersets and graph structures (such as David Eppstein's
760
   graph recipes in Lib/test/test_set.py).
761
762
   This hash algorithm can be used on either a frozenset or a set.
763
   When it is used on a set, it computes the hash value of the equivalent
764
   frozenset without creating a new frozenset object. */
765
766
static Py_hash_t
767
frozenset_hash_impl(PyObject *self)
768
84
{
769
84
    PySetObject *so = _PySet_CAST(self);
770
84
    Py_uhash_t hash = 0;
771
84
    setentry *entry;
772
773
    /* Xor-in shuffled bits from every entry's hash field because xor is
774
       commutative and a frozenset hash should be independent of order.
775
776
       For speed, include null entries and dummy entries and then
777
       subtract out their effect afterwards so that the final hash
778
       depends only on active entries.  This allows the code to be
779
       vectorized by the compiler and it saves the unpredictable
780
       branches that would arise when trying to exclude null and dummy
781
       entries on every iteration. */
782
783
1.33k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
784
1.24k
        hash ^= _shuffle_bits(entry->hash);
785
786
    /* Remove the effect of an odd number of NULL entries */
787
84
    if ((so->mask + 1 - so->fill) & 1)
788
33
        hash ^= _shuffle_bits(0);
789
790
    /* Remove the effect of an odd number of dummy entries */
791
84
    if ((so->fill - so->used) & 1)
792
0
        hash ^= _shuffle_bits(-1);
793
794
    /* Factor in the number of active entries */
795
84
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
796
797
    /* Disperse patterns arising in nested frozensets */
798
84
    hash ^= (hash >> 11) ^ (hash >> 25);
799
84
    hash = hash * 69069U + 907133923UL;
800
801
    /* -1 is reserved as an error code */
802
84
    if (hash == (Py_uhash_t)-1)
803
0
        hash = 590923713UL;
804
805
84
    return (Py_hash_t)hash;
806
84
}
807
808
static Py_hash_t
809
frozenset_hash(PyObject *self)
810
140
{
811
140
    PySetObject *so = _PySet_CAST(self);
812
140
    Py_uhash_t hash;
813
814
140
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
815
56
        return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash);
816
56
    }
817
818
84
    hash = frozenset_hash_impl(self);
819
84
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, hash);
820
84
    return hash;
821
140
}
822
823
/***** Set iterator type ***********************************************/
824
825
typedef struct {
826
    PyObject_HEAD
827
    PySetObject *si_set; /* Set to NULL when iterator is exhausted */
828
    Py_ssize_t si_used;
829
    Py_ssize_t si_pos;
830
    Py_ssize_t len;
831
} setiterobject;
832
833
static void
834
setiter_dealloc(PyObject *self)
835
310k
{
836
310k
    setiterobject *si = (setiterobject*)self;
837
    /* bpo-31095: UnTrack is needed before calling any callbacks */
838
310k
    _PyObject_GC_UNTRACK(si);
839
310k
    Py_XDECREF(si->si_set);
840
310k
    PyObject_GC_Del(si);
841
310k
}
842
843
static int
844
setiter_traverse(PyObject *self, visitproc visit, void *arg)
845
0
{
846
0
    setiterobject *si = (setiterobject*)self;
847
0
    Py_VISIT(si->si_set);
848
0
    return 0;
849
0
}
850
851
static PyObject *
852
setiter_len(PyObject *op, PyObject *Py_UNUSED(ignored))
853
10
{
854
10
    setiterobject *si = (setiterobject*)op;
855
10
    Py_ssize_t len = 0;
856
10
    if (si->si_set != NULL && si->si_used == si->si_set->used)
857
10
        len = si->len;
858
10
    return PyLong_FromSsize_t(len);
859
10
}
860
861
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
862
863
static PyObject *
864
setiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
865
0
{
866
0
    setiterobject *si = (setiterobject*)op;
867
868
    /* copy the iterator state */
869
0
    setiterobject tmp = *si;
870
0
    Py_XINCREF(tmp.si_set);
871
872
    /* iterate the temporary into a list */
873
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
874
0
    Py_XDECREF(tmp.si_set);
875
0
    if (list == NULL) {
876
0
        return NULL;
877
0
    }
878
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
879
0
}
880
881
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
882
883
static PyMethodDef setiter_methods[] = {
884
    {"__length_hint__", setiter_len, METH_NOARGS, length_hint_doc},
885
    {"__reduce__", setiter_reduce, METH_NOARGS, reduce_doc},
886
    {NULL,              NULL}           /* sentinel */
887
};
888
889
static PyObject *setiter_iternext(PyObject *self)
890
497k
{
891
497k
    setiterobject *si = (setiterobject*)self;
892
497k
    PyObject *key = NULL;
893
497k
    Py_ssize_t i, mask;
894
497k
    setentry *entry;
895
497k
    PySetObject *so = si->si_set;
896
897
497k
    if (so == NULL)
898
0
        return NULL;
899
497k
    assert (PyAnySet_Check(so));
900
901
497k
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE(so->used);
902
497k
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE(si->si_used);
903
497k
    if (si_used != so_used) {
904
0
        PyErr_SetString(PyExc_RuntimeError,
905
0
                        "Set changed size during iteration");
906
0
        si->si_used = -1; /* Make this state sticky */
907
0
        return NULL;
908
0
    }
909
910
497k
    Py_BEGIN_CRITICAL_SECTION(so);
911
497k
    i = si->si_pos;
912
497k
    assert(i>=0);
913
497k
    entry = so->table;
914
497k
    mask = so->mask;
915
2.97M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
916
2.47M
        i++;
917
2.47M
    }
918
497k
    if (i <= mask) {
919
186k
        key = Py_NewRef(entry[i].key);
920
186k
    }
921
497k
    Py_END_CRITICAL_SECTION();
922
497k
    si->si_pos = i+1;
923
497k
    if (key == NULL) {
924
310k
        si->si_set = NULL;
925
310k
        Py_DECREF(so);
926
310k
        return NULL;
927
310k
    }
928
186k
    si->len--;
929
186k
    return key;
930
497k
}
931
932
PyTypeObject PySetIter_Type = {
933
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
934
    "set_iterator",                             /* tp_name */
935
    sizeof(setiterobject),                      /* tp_basicsize */
936
    0,                                          /* tp_itemsize */
937
    /* methods */
938
    setiter_dealloc,                            /* tp_dealloc */
939
    0,                                          /* tp_vectorcall_offset */
940
    0,                                          /* tp_getattr */
941
    0,                                          /* tp_setattr */
942
    0,                                          /* tp_as_async */
943
    0,                                          /* tp_repr */
944
    0,                                          /* tp_as_number */
945
    0,                                          /* tp_as_sequence */
946
    0,                                          /* tp_as_mapping */
947
    0,                                          /* tp_hash */
948
    0,                                          /* tp_call */
949
    0,                                          /* tp_str */
950
    PyObject_GenericGetAttr,                    /* tp_getattro */
951
    0,                                          /* tp_setattro */
952
    0,                                          /* tp_as_buffer */
953
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
954
    0,                                          /* tp_doc */
955
    setiter_traverse,                           /* tp_traverse */
956
    0,                                          /* tp_clear */
957
    0,                                          /* tp_richcompare */
958
    0,                                          /* tp_weaklistoffset */
959
    PyObject_SelfIter,                          /* tp_iter */
960
    setiter_iternext,                           /* tp_iternext */
961
    setiter_methods,                            /* tp_methods */
962
    0,
963
};
964
965
static PyObject *
966
set_iter(PyObject *so)
967
310k
{
968
310k
    Py_ssize_t size = set_len(so);
969
310k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
970
310k
    if (si == NULL)
971
0
        return NULL;
972
310k
    si->si_set = (PySetObject*)Py_NewRef(so);
973
310k
    si->si_used = size;
974
310k
    si->si_pos = 0;
975
310k
    si->len = size;
976
310k
    _PyObject_GC_TRACK(si);
977
310k
    return (PyObject *)si;
978
310k
}
979
980
static int
981
set_update_dict_lock_held(PySetObject *so, PyObject *other)
982
81
{
983
81
    assert(PyDict_CheckExact(other));
984
985
81
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
986
81
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
987
988
    /* Do one big resize at the start, rather than
989
    * incrementally resizing as we insert new keys.  Expect
990
    * that there will be no (or few) overlapping keys.
991
    */
992
81
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
993
81
    if ((so->fill + dictsize)*5 >= so->mask*3) {
994
0
        if (set_table_resize(so, (so->used + dictsize)*2) != 0) {
995
0
            return -1;
996
0
        }
997
0
    }
998
999
81
    Py_ssize_t pos = 0;
1000
81
    PyObject *key;
1001
81
    PyObject *value;
1002
81
    Py_hash_t hash;
1003
133
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1004
52
        if (set_add_entry(so, key, hash)) {
1005
0
            return -1;
1006
0
        }
1007
52
    }
1008
81
    return 0;
1009
81
}
1010
1011
static int
1012
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1013
15.8k
{
1014
15.8k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1015
1016
15.8k
    PyObject *it = PyObject_GetIter(other);
1017
15.8k
    if (it == NULL) {
1018
0
        return -1;
1019
0
    }
1020
1021
15.8k
    PyObject *key;
1022
72.0k
    while ((key = PyIter_Next(it)) != NULL) {
1023
56.2k
        if (set_add_key(so, key)) {
1024
0
            Py_DECREF(it);
1025
0
            Py_DECREF(key);
1026
0
            return -1;
1027
0
        }
1028
56.2k
        Py_DECREF(key);
1029
56.2k
    }
1030
15.8k
    Py_DECREF(it);
1031
15.8k
    if (PyErr_Occurred())
1032
0
        return -1;
1033
15.8k
    return 0;
1034
15.8k
}
1035
1036
static int
1037
set_update_lock_held(PySetObject *so, PyObject *other)
1038
0
{
1039
0
    if (PyAnySet_Check(other)) {
1040
0
        return set_merge_lock_held(so, other);
1041
0
    }
1042
0
    else if (PyDict_CheckExact(other)) {
1043
0
        return set_update_dict_lock_held(so, other);
1044
0
    }
1045
0
    return set_update_iterable_lock_held(so, other);
1046
0
}
1047
1048
// set_update for a `so` that is only visible to the current thread
1049
static int
1050
set_update_local(PySetObject *so, PyObject *other)
1051
55.4k
{
1052
55.4k
    assert(Py_REFCNT(so) == 1);
1053
55.4k
    if (PyAnySet_Check(other)) {
1054
39.5k
        int rv;
1055
39.5k
        Py_BEGIN_CRITICAL_SECTION(other);
1056
39.5k
        rv = set_merge_lock_held(so, other);
1057
39.5k
        Py_END_CRITICAL_SECTION();
1058
39.5k
        return rv;
1059
39.5k
    }
1060
15.9k
    else if (PyDict_CheckExact(other)) {
1061
81
        int rv;
1062
81
        Py_BEGIN_CRITICAL_SECTION(other);
1063
81
        rv = set_update_dict_lock_held(so, other);
1064
81
        Py_END_CRITICAL_SECTION();
1065
81
        return rv;
1066
81
    }
1067
15.8k
    return set_update_iterable_lock_held(so, other);
1068
55.4k
}
1069
1070
static int
1071
set_update_internal(PySetObject *so, PyObject *other)
1072
48.2k
{
1073
48.2k
    if (PyAnySet_Check(other)) {
1074
48.2k
        if (Py_Is((PyObject *)so, other)) {
1075
0
            return 0;
1076
0
        }
1077
48.2k
        int rv;
1078
48.2k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1079
48.2k
        rv = set_merge_lock_held(so, other);
1080
48.2k
        Py_END_CRITICAL_SECTION2();
1081
48.2k
        return rv;
1082
48.2k
    }
1083
0
    else if (PyDict_CheckExact(other)) {
1084
0
        int rv;
1085
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1086
0
        rv = set_update_dict_lock_held(so, other);
1087
0
        Py_END_CRITICAL_SECTION2();
1088
0
        return rv;
1089
0
    }
1090
0
    else {
1091
0
        int rv;
1092
0
        Py_BEGIN_CRITICAL_SECTION(so);
1093
0
        rv = set_update_iterable_lock_held(so, other);
1094
0
        Py_END_CRITICAL_SECTION();
1095
0
        return rv;
1096
0
    }
1097
48.2k
}
1098
1099
/*[clinic input]
1100
set.update
1101
    so: setobject
1102
    *others: array
1103
1104
Update the set, adding elements from all others.
1105
[clinic start generated code]*/
1106
1107
static PyObject *
1108
set_update_impl(PySetObject *so, PyObject * const *others,
1109
                Py_ssize_t others_length)
1110
/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
1111
0
{
1112
0
    Py_ssize_t i;
1113
1114
0
    for (i = 0; i < others_length; i++) {
1115
0
        PyObject *other = others[i];
1116
0
        if (set_update_internal(so, other))
1117
0
            return NULL;
1118
0
    }
1119
0
    Py_RETURN_NONE;
1120
0
}
1121
1122
/* XXX Todo:
1123
   If aligned memory allocations become available, make the
1124
   set object 64 byte aligned so that most of the fields
1125
   can be retrieved or updated in a single cache line.
1126
*/
1127
1128
static PyObject *
1129
make_new_set(PyTypeObject *type, PyObject *iterable)
1130
741k
{
1131
741k
    assert(PyType_Check(type));
1132
741k
    PySetObject *so;
1133
1134
741k
    so = (PySetObject *)type->tp_alloc(type, 0);
1135
741k
    if (so == NULL)
1136
0
        return NULL;
1137
1138
741k
    so->fill = 0;
1139
741k
    so->used = 0;
1140
741k
    so->mask = PySet_MINSIZE - 1;
1141
741k
    so->table = so->smalltable;
1142
741k
    so->hash = -1;
1143
741k
    so->finger = 0;
1144
741k
    so->weakreflist = NULL;
1145
1146
741k
    if (iterable != NULL) {
1147
55.4k
        if (set_update_local(so, iterable)) {
1148
0
            Py_DECREF(so);
1149
0
            return NULL;
1150
0
        }
1151
55.4k
    }
1152
1153
741k
    return (PyObject *)so;
1154
741k
}
1155
1156
static PyObject *
1157
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1158
116
{
1159
116
    if (type != &PySet_Type && type != &PyFrozenSet_Type) {
1160
0
        if (PyType_IsSubtype(type, &PySet_Type))
1161
0
            type = &PySet_Type;
1162
0
        else
1163
0
            type = &PyFrozenSet_Type;
1164
0
    }
1165
116
    return make_new_set(type, iterable);
1166
116
}
1167
1168
static PyObject *
1169
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1170
130
{
1171
130
    if (type != &PyFrozenSet_Type) {
1172
0
        return make_new_set(type, iterable);
1173
0
    }
1174
1175
130
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1176
        /* frozenset(f) is idempotent */
1177
0
        return Py_NewRef(iterable);
1178
0
    }
1179
130
    return make_new_set(type, iterable);
1180
130
}
1181
1182
static PyObject *
1183
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1184
0
{
1185
0
    PyObject *iterable = NULL;
1186
1187
0
    if ((type == &PyFrozenSet_Type ||
1188
0
         type->tp_init == PyFrozenSet_Type.tp_init) &&
1189
0
        !_PyArg_NoKeywords("frozenset", kwds)) {
1190
0
        return NULL;
1191
0
    }
1192
1193
0
    if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) {
1194
0
        return NULL;
1195
0
    }
1196
1197
0
    return make_new_frozenset(type, iterable);
1198
0
}
1199
1200
static PyObject *
1201
frozenset_vectorcall(PyObject *type, PyObject * const*args,
1202
                     size_t nargsf, PyObject *kwnames)
1203
130
{
1204
130
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1205
0
        return NULL;
1206
0
    }
1207
1208
130
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1209
130
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1210
0
        return NULL;
1211
0
    }
1212
1213
130
    PyObject *iterable = (nargs ? args[0] : NULL);
1214
130
    return make_new_frozenset(_PyType_CAST(type), iterable);
1215
130
}
1216
1217
static PyObject *
1218
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1219
0
{
1220
0
    return make_new_set(type, NULL);
1221
0
}
1222
1223
/* set_swap_bodies() switches the contents of any two sets by moving their
1224
   internal data pointers and, if needed, copying the internal smalltables.
1225
   Semantically equivalent to:
1226
1227
     t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
1228
1229
   The function always succeeds and it leaves both objects in a stable state.
1230
   Useful for operations that update in-place (by allowing an intermediate
1231
   result to be swapped into one of the original inputs).
1232
*/
1233
1234
static void
1235
set_swap_bodies(PySetObject *a, PySetObject *b)
1236
0
{
1237
0
    Py_ssize_t t;
1238
0
    setentry *u;
1239
0
    setentry tab[PySet_MINSIZE];
1240
0
    Py_hash_t h;
1241
1242
0
    t = a->fill;     a->fill   = b->fill;        b->fill  = t;
1243
0
    t = a->used;
1244
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(a->used, b->used);
1245
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(b->used, t);
1246
0
    t = a->mask;     a->mask   = b->mask;        b->mask  = t;
1247
1248
0
    u = a->table;
1249
0
    if (a->table == a->smalltable)
1250
0
        u = b->smalltable;
1251
0
    a->table  = b->table;
1252
0
    if (b->table == b->smalltable)
1253
0
        a->table = a->smalltable;
1254
0
    b->table = u;
1255
1256
0
    if (a->table == a->smalltable || b->table == b->smalltable) {
1257
0
        memcpy(tab, a->smalltable, sizeof(tab));
1258
0
        memcpy(a->smalltable, b->smalltable, sizeof(tab));
1259
0
        memcpy(b->smalltable, tab, sizeof(tab));
1260
0
    }
1261
1262
0
    if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type)  &&
1263
0
        PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
1264
0
        h = FT_ATOMIC_LOAD_SSIZE_RELAXED(a->hash);
1265
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, FT_ATOMIC_LOAD_SSIZE_RELAXED(b->hash));
1266
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, h);
1267
0
    } else {
1268
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, -1);
1269
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, -1);
1270
0
    }
1271
0
}
1272
1273
/*[clinic input]
1274
@critical_section
1275
set.copy
1276
    so: setobject
1277
1278
Return a shallow copy of a set.
1279
[clinic start generated code]*/
1280
1281
static PyObject *
1282
set_copy_impl(PySetObject *so)
1283
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
1284
33
{
1285
33
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1286
33
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1287
33
    if (copy == NULL) {
1288
0
        return NULL;
1289
0
    }
1290
33
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1291
0
        Py_DECREF(copy);
1292
0
        return NULL;
1293
0
    }
1294
33
    return copy;
1295
33
}
1296
1297
/*[clinic input]
1298
@critical_section
1299
frozenset.copy
1300
    so: setobject
1301
1302
Return a shallow copy of a set.
1303
[clinic start generated code]*/
1304
1305
static PyObject *
1306
frozenset_copy_impl(PySetObject *so)
1307
/*[clinic end generated code: output=b356263526af9e70 input=fbf5bef131268dd7]*/
1308
0
{
1309
0
    if (PyFrozenSet_CheckExact(so)) {
1310
0
        return Py_NewRef(so);
1311
0
    }
1312
0
    return set_copy_impl(so);
1313
0
}
1314
1315
/*[clinic input]
1316
@critical_section
1317
set.clear
1318
    so: setobject
1319
1320
Remove all elements from this set.
1321
[clinic start generated code]*/
1322
1323
static PyObject *
1324
set_clear_impl(PySetObject *so)
1325
/*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/
1326
160
{
1327
160
    set_clear_internal((PyObject*)so);
1328
160
    Py_RETURN_NONE;
1329
160
}
1330
1331
/*[clinic input]
1332
set.union
1333
    so: setobject
1334
    *others: array
1335
1336
Return a new set with elements from the set and all others.
1337
[clinic start generated code]*/
1338
1339
static PyObject *
1340
set_union_impl(PySetObject *so, PyObject * const *others,
1341
               Py_ssize_t others_length)
1342
/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
1343
2
{
1344
2
    PySetObject *result;
1345
2
    PyObject *other;
1346
2
    Py_ssize_t i;
1347
1348
2
    result = (PySetObject *)set_copy((PyObject *)so, NULL);
1349
2
    if (result == NULL)
1350
0
        return NULL;
1351
1352
4
    for (i = 0; i < others_length; i++) {
1353
2
        other = others[i];
1354
2
        if ((PyObject *)so == other)
1355
0
            continue;
1356
2
        if (set_update_local(result, other)) {
1357
0
            Py_DECREF(result);
1358
0
            return NULL;
1359
0
        }
1360
2
    }
1361
2
    return (PyObject *)result;
1362
2
}
1363
1364
static PyObject *
1365
set_or(PyObject *self, PyObject *other)
1366
25
{
1367
25
    PySetObject *result;
1368
1369
25
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1370
0
        Py_RETURN_NOTIMPLEMENTED;
1371
1372
25
    result = (PySetObject *)set_copy(self, NULL);
1373
25
    if (result == NULL) {
1374
0
        return NULL;
1375
0
    }
1376
25
    if (Py_Is(self, other)) {
1377
0
        return (PyObject *)result;
1378
0
    }
1379
25
    if (set_update_local(result, other)) {
1380
0
        Py_DECREF(result);
1381
0
        return NULL;
1382
0
    }
1383
25
    return (PyObject *)result;
1384
25
}
1385
1386
static PyObject *
1387
set_ior(PyObject *self, PyObject *other)
1388
48.2k
{
1389
48.2k
    if (!PyAnySet_Check(other))
1390
0
        Py_RETURN_NOTIMPLEMENTED;
1391
48.2k
    PySetObject *so = _PySet_CAST(self);
1392
1393
48.2k
    if (set_update_internal(so, other)) {
1394
0
        return NULL;
1395
0
    }
1396
48.2k
    return Py_NewRef(so);
1397
48.2k
}
1398
1399
static PyObject *
1400
set_intersection(PySetObject *so, PyObject *other)
1401
81
{
1402
81
    PySetObject *result;
1403
81
    PyObject *key, *it, *tmp;
1404
81
    Py_hash_t hash;
1405
81
    int rv;
1406
1407
81
    if ((PyObject *)so == other)
1408
0
        return set_copy_impl(so);
1409
1410
81
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1411
81
    if (result == NULL)
1412
0
        return NULL;
1413
1414
81
    if (PyAnySet_Check(other)) {
1415
81
        Py_ssize_t pos = 0;
1416
81
        setentry *entry;
1417
1418
81
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1419
66
            tmp = (PyObject *)so;
1420
66
            so = (PySetObject *)other;
1421
66
            other = tmp;
1422
66
        }
1423
1424
111
        while (set_next((PySetObject *)other, &pos, &entry)) {
1425
30
            key = entry->key;
1426
30
            hash = entry->hash;
1427
30
            Py_INCREF(key);
1428
30
            rv = set_contains_entry(so, key, hash);
1429
30
            if (rv < 0) {
1430
0
                Py_DECREF(result);
1431
0
                Py_DECREF(key);
1432
0
                return NULL;
1433
0
            }
1434
30
            if (rv) {
1435
0
                if (set_add_entry(result, key, hash)) {
1436
0
                    Py_DECREF(result);
1437
0
                    Py_DECREF(key);
1438
0
                    return NULL;
1439
0
                }
1440
0
            }
1441
30
            Py_DECREF(key);
1442
30
        }
1443
81
        return (PyObject *)result;
1444
81
    }
1445
1446
0
    it = PyObject_GetIter(other);
1447
0
    if (it == NULL) {
1448
0
        Py_DECREF(result);
1449
0
        return NULL;
1450
0
    }
1451
1452
0
    while ((key = PyIter_Next(it)) != NULL) {
1453
0
        hash = PyObject_Hash(key);
1454
0
        if (hash == -1)
1455
0
            goto error;
1456
0
        rv = set_contains_entry(so, key, hash);
1457
0
        if (rv < 0)
1458
0
            goto error;
1459
0
        if (rv) {
1460
0
            if (set_add_entry(result, key, hash))
1461
0
                goto error;
1462
0
            if (PySet_GET_SIZE(result) >= PySet_GET_SIZE(so)) {
1463
0
                Py_DECREF(key);
1464
0
                break;
1465
0
            }
1466
0
        }
1467
0
        Py_DECREF(key);
1468
0
    }
1469
0
    Py_DECREF(it);
1470
0
    if (PyErr_Occurred()) {
1471
0
        Py_DECREF(result);
1472
0
        return NULL;
1473
0
    }
1474
0
    return (PyObject *)result;
1475
0
  error:
1476
0
    Py_DECREF(it);
1477
0
    Py_DECREF(result);
1478
0
    Py_DECREF(key);
1479
0
    return NULL;
1480
0
}
1481
1482
/*[clinic input]
1483
set.intersection as set_intersection_multi
1484
    so: setobject
1485
    *others: array
1486
1487
Return a new set with elements common to the set and all others.
1488
[clinic start generated code]*/
1489
1490
static PyObject *
1491
set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
1492
                            Py_ssize_t others_length)
1493
/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
1494
0
{
1495
0
    Py_ssize_t i;
1496
1497
0
    if (others_length == 0) {
1498
0
        return set_copy((PyObject *)so, NULL);
1499
0
    }
1500
1501
0
    PyObject *result = Py_NewRef(so);
1502
0
    for (i = 0; i < others_length; i++) {
1503
0
        PyObject *other = others[i];
1504
0
        PyObject *newresult;
1505
0
        Py_BEGIN_CRITICAL_SECTION2(result, other);
1506
0
        newresult = set_intersection((PySetObject *)result, other);
1507
0
        Py_END_CRITICAL_SECTION2();
1508
0
        if (newresult == NULL) {
1509
0
            Py_DECREF(result);
1510
0
            return NULL;
1511
0
        }
1512
0
        Py_SETREF(result, newresult);
1513
0
    }
1514
0
    return result;
1515
0
}
1516
1517
static PyObject *
1518
set_intersection_update(PySetObject *so, PyObject *other)
1519
0
{
1520
0
    PyObject *tmp;
1521
1522
0
    tmp = set_intersection(so, other);
1523
0
    if (tmp == NULL)
1524
0
        return NULL;
1525
0
    set_swap_bodies(so, (PySetObject *)tmp);
1526
0
    Py_DECREF(tmp);
1527
0
    Py_RETURN_NONE;
1528
0
}
1529
1530
/*[clinic input]
1531
set.intersection_update as set_intersection_update_multi
1532
    so: setobject
1533
    *others: array
1534
1535
Update the set, keeping only elements found in it and all others.
1536
[clinic start generated code]*/
1537
1538
static PyObject *
1539
set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
1540
                                   Py_ssize_t others_length)
1541
/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
1542
0
{
1543
0
    PyObject *tmp;
1544
1545
0
    tmp = set_intersection_multi_impl(so, others, others_length);
1546
0
    if (tmp == NULL)
1547
0
        return NULL;
1548
0
    Py_BEGIN_CRITICAL_SECTION(so);
1549
0
    set_swap_bodies(so, (PySetObject *)tmp);
1550
0
    Py_END_CRITICAL_SECTION();
1551
0
    Py_DECREF(tmp);
1552
0
    Py_RETURN_NONE;
1553
0
}
1554
1555
static PyObject *
1556
set_and(PyObject *self, PyObject *other)
1557
81
{
1558
81
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1559
0
        Py_RETURN_NOTIMPLEMENTED;
1560
81
    PySetObject *so = _PySet_CAST(self);
1561
1562
81
    PyObject *rv;
1563
81
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1564
81
    rv = set_intersection(so, other);
1565
81
    Py_END_CRITICAL_SECTION2();
1566
1567
81
    return rv;
1568
81
}
1569
1570
static PyObject *
1571
set_iand(PyObject *self, PyObject *other)
1572
0
{
1573
0
    PyObject *result;
1574
1575
0
    if (!PyAnySet_Check(other))
1576
0
        Py_RETURN_NOTIMPLEMENTED;
1577
0
    PySetObject *so = _PySet_CAST(self);
1578
1579
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1580
0
    result = set_intersection_update(so, other);
1581
0
    Py_END_CRITICAL_SECTION2();
1582
1583
0
    if (result == NULL)
1584
0
        return NULL;
1585
0
    Py_DECREF(result);
1586
0
    return Py_NewRef(so);
1587
0
}
1588
1589
/*[clinic input]
1590
@critical_section so other
1591
set.isdisjoint
1592
    so: setobject
1593
    other: object
1594
    /
1595
1596
Return True if two sets have a null intersection.
1597
[clinic start generated code]*/
1598
1599
static PyObject *
1600
set_isdisjoint_impl(PySetObject *so, PyObject *other)
1601
/*[clinic end generated code: output=273493f2d57c565e input=32f8dcab5e0fc7d6]*/
1602
15.4k
{
1603
15.4k
    PyObject *key, *it, *tmp;
1604
15.4k
    int rv;
1605
1606
15.4k
    if ((PyObject *)so == other) {
1607
0
        if (PySet_GET_SIZE(so) == 0)
1608
0
            Py_RETURN_TRUE;
1609
0
        else
1610
0
            Py_RETURN_FALSE;
1611
0
    }
1612
1613
15.4k
    if (PyAnySet_CheckExact(other)) {
1614
0
        Py_ssize_t pos = 0;
1615
0
        setentry *entry;
1616
1617
0
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1618
0
            tmp = (PyObject *)so;
1619
0
            so = (PySetObject *)other;
1620
0
            other = tmp;
1621
0
        }
1622
0
        while (set_next((PySetObject *)other, &pos, &entry)) {
1623
0
            PyObject *key = entry->key;
1624
0
            Py_INCREF(key);
1625
0
            rv = set_contains_entry(so, key, entry->hash);
1626
0
            Py_DECREF(key);
1627
0
            if (rv < 0) {
1628
0
                return NULL;
1629
0
            }
1630
0
            if (rv) {
1631
0
                Py_RETURN_FALSE;
1632
0
            }
1633
0
        }
1634
0
        Py_RETURN_TRUE;
1635
0
    }
1636
1637
15.4k
    it = PyObject_GetIter(other);
1638
15.4k
    if (it == NULL)
1639
0
        return NULL;
1640
1641
21.0k
    while ((key = PyIter_Next(it)) != NULL) {
1642
20.9k
        rv = set_contains_key(so, key);
1643
20.9k
        Py_DECREF(key);
1644
20.9k
        if (rv < 0) {
1645
0
            Py_DECREF(it);
1646
0
            return NULL;
1647
0
        }
1648
20.9k
        if (rv) {
1649
15.3k
            Py_DECREF(it);
1650
15.3k
            Py_RETURN_FALSE;
1651
15.3k
        }
1652
20.9k
    }
1653
148
    Py_DECREF(it);
1654
148
    if (PyErr_Occurred())
1655
0
        return NULL;
1656
148
    Py_RETURN_TRUE;
1657
148
}
1658
1659
static int
1660
set_difference_update_internal(PySetObject *so, PyObject *other)
1661
6
{
1662
6
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1663
6
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1664
1665
6
    if ((PyObject *)so == other)
1666
0
        return set_clear_internal((PyObject*)so);
1667
1668
6
    if (PyAnySet_Check(other)) {
1669
6
        setentry *entry;
1670
6
        Py_ssize_t pos = 0;
1671
1672
        /* Optimization:  When the other set is more than 8 times
1673
           larger than the base set, replace the other set with
1674
           intersection of the two sets.
1675
        */
1676
6
        if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
1677
0
            other = set_intersection(so, other);
1678
0
            if (other == NULL)
1679
0
                return -1;
1680
6
        } else {
1681
6
            Py_INCREF(other);
1682
6
        }
1683
1684
12
        while (set_next((PySetObject *)other, &pos, &entry)) {
1685
6
            PyObject *key = entry->key;
1686
6
            Py_INCREF(key);
1687
6
            if (set_discard_entry(so, key, entry->hash) < 0) {
1688
0
                Py_DECREF(other);
1689
0
                Py_DECREF(key);
1690
0
                return -1;
1691
0
            }
1692
6
            Py_DECREF(key);
1693
6
        }
1694
1695
6
        Py_DECREF(other);
1696
6
    } else {
1697
0
        PyObject *key, *it;
1698
0
        it = PyObject_GetIter(other);
1699
0
        if (it == NULL)
1700
0
            return -1;
1701
1702
0
        while ((key = PyIter_Next(it)) != NULL) {
1703
0
            if (set_discard_key(so, key) < 0) {
1704
0
                Py_DECREF(it);
1705
0
                Py_DECREF(key);
1706
0
                return -1;
1707
0
            }
1708
0
            Py_DECREF(key);
1709
0
        }
1710
0
        Py_DECREF(it);
1711
0
        if (PyErr_Occurred())
1712
0
            return -1;
1713
0
    }
1714
    /* If more than 1/4th are dummies, then resize them away. */
1715
6
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1716
6
        return 0;
1717
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1718
6
}
1719
1720
/*[clinic input]
1721
set.difference_update
1722
    so: setobject
1723
    *others: array
1724
1725
Update the set, removing elements found in others.
1726
[clinic start generated code]*/
1727
1728
static PyObject *
1729
set_difference_update_impl(PySetObject *so, PyObject * const *others,
1730
                           Py_ssize_t others_length)
1731
/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
1732
0
{
1733
0
    Py_ssize_t i;
1734
1735
0
    for (i = 0; i < others_length; i++) {
1736
0
        PyObject *other = others[i];
1737
0
        int rv;
1738
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1739
0
        rv = set_difference_update_internal(so, other);
1740
0
        Py_END_CRITICAL_SECTION2();
1741
0
        if (rv) {
1742
0
            return NULL;
1743
0
        }
1744
0
    }
1745
0
    Py_RETURN_NONE;
1746
0
}
1747
1748
static PyObject *
1749
set_copy_and_difference(PySetObject *so, PyObject *other)
1750
6
{
1751
6
    PyObject *result;
1752
1753
6
    result = set_copy_impl(so);
1754
6
    if (result == NULL)
1755
0
        return NULL;
1756
6
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1757
6
        return result;
1758
0
    Py_DECREF(result);
1759
0
    return NULL;
1760
6
}
1761
1762
static PyObject *
1763
set_difference(PySetObject *so, PyObject *other)
1764
8
{
1765
8
    PyObject *result;
1766
8
    PyObject *key;
1767
8
    Py_hash_t hash;
1768
8
    setentry *entry;
1769
8
    Py_ssize_t pos = 0, other_size;
1770
8
    int rv;
1771
1772
8
    if (PyAnySet_Check(other)) {
1773
8
        other_size = PySet_GET_SIZE(other);
1774
8
    }
1775
0
    else if (PyDict_CheckExact(other)) {
1776
0
        other_size = PyDict_GET_SIZE(other);
1777
0
    }
1778
0
    else {
1779
0
        return set_copy_and_difference(so, other);
1780
0
    }
1781
1782
    /* If len(so) much more than len(other), it's more efficient to simply copy
1783
     * so and then iterate other looking for common elements. */
1784
8
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1785
6
        return set_copy_and_difference(so, other);
1786
6
    }
1787
1788
2
    result = make_new_set_basetype(Py_TYPE(so), NULL);
1789
2
    if (result == NULL)
1790
0
        return NULL;
1791
1792
2
    if (PyDict_CheckExact(other)) {
1793
0
        while (set_next(so, &pos, &entry)) {
1794
0
            key = entry->key;
1795
0
            hash = entry->hash;
1796
0
            Py_INCREF(key);
1797
0
            rv = _PyDict_Contains_KnownHash(other, key, hash);
1798
0
            if (rv < 0) {
1799
0
                Py_DECREF(result);
1800
0
                Py_DECREF(key);
1801
0
                return NULL;
1802
0
            }
1803
0
            if (!rv) {
1804
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
1805
0
                    Py_DECREF(result);
1806
0
                    Py_DECREF(key);
1807
0
                    return NULL;
1808
0
                }
1809
0
            }
1810
0
            Py_DECREF(key);
1811
0
        }
1812
0
        return result;
1813
0
    }
1814
1815
    /* Iterate over so, checking for common elements in other. */
1816
28
    while (set_next(so, &pos, &entry)) {
1817
26
        key = entry->key;
1818
26
        hash = entry->hash;
1819
26
        Py_INCREF(key);
1820
26
        rv = set_contains_entry((PySetObject *)other, key, hash);
1821
26
        if (rv < 0) {
1822
0
            Py_DECREF(result);
1823
0
            Py_DECREF(key);
1824
0
            return NULL;
1825
0
        }
1826
26
        if (!rv) {
1827
20
            if (set_add_entry((PySetObject *)result, key, hash)) {
1828
0
                Py_DECREF(result);
1829
0
                Py_DECREF(key);
1830
0
                return NULL;
1831
0
            }
1832
20
        }
1833
26
        Py_DECREF(key);
1834
26
    }
1835
2
    return result;
1836
2
}
1837
1838
/*[clinic input]
1839
set.difference as set_difference_multi
1840
    so: setobject
1841
    *others: array
1842
1843
Return a new set with elements in the set that are not in the others.
1844
[clinic start generated code]*/
1845
1846
static PyObject *
1847
set_difference_multi_impl(PySetObject *so, PyObject * const *others,
1848
                          Py_ssize_t others_length)
1849
/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
1850
0
{
1851
0
    Py_ssize_t i;
1852
0
    PyObject *result, *other;
1853
1854
0
    if (others_length == 0) {
1855
0
        return set_copy((PyObject *)so, NULL);
1856
0
    }
1857
1858
0
    other = others[0];
1859
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1860
0
    result = set_difference(so, other);
1861
0
    Py_END_CRITICAL_SECTION2();
1862
0
    if (result == NULL)
1863
0
        return NULL;
1864
1865
0
    for (i = 1; i < others_length; i++) {
1866
0
        other = others[i];
1867
0
        int rv;
1868
0
        Py_BEGIN_CRITICAL_SECTION(other);
1869
0
        rv = set_difference_update_internal((PySetObject *)result, other);
1870
0
        Py_END_CRITICAL_SECTION();
1871
0
        if (rv) {
1872
0
            Py_DECREF(result);
1873
0
            return NULL;
1874
0
        }
1875
0
    }
1876
0
    return result;
1877
0
}
1878
1879
static PyObject *
1880
set_sub(PyObject *self, PyObject *other)
1881
8
{
1882
8
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1883
0
        Py_RETURN_NOTIMPLEMENTED;
1884
8
    PySetObject *so = _PySet_CAST(self);
1885
1886
8
    PyObject *rv;
1887
8
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1888
8
    rv = set_difference(so, other);
1889
8
    Py_END_CRITICAL_SECTION2();
1890
8
    return rv;
1891
8
}
1892
1893
static PyObject *
1894
set_isub(PyObject *self, PyObject *other)
1895
0
{
1896
0
    if (!PyAnySet_Check(other))
1897
0
        Py_RETURN_NOTIMPLEMENTED;
1898
0
    PySetObject *so = _PySet_CAST(self);
1899
1900
0
    int rv;
1901
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1902
0
    rv = set_difference_update_internal(so, other);
1903
0
    Py_END_CRITICAL_SECTION2();
1904
0
    if (rv < 0) {
1905
0
        return NULL;
1906
0
    }
1907
0
    return Py_NewRef(so);
1908
0
}
1909
1910
static int
1911
set_symmetric_difference_update_dict(PySetObject *so, PyObject *other)
1912
0
{
1913
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1914
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1915
1916
0
    Py_ssize_t pos = 0;
1917
0
    PyObject *key, *value;
1918
0
    Py_hash_t hash;
1919
0
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1920
0
        Py_INCREF(key);
1921
0
        int rv = set_discard_entry(so, key, hash);
1922
0
        if (rv < 0) {
1923
0
            Py_DECREF(key);
1924
0
            return -1;
1925
0
        }
1926
0
        if (rv == DISCARD_NOTFOUND) {
1927
0
            if (set_add_entry(so, key, hash)) {
1928
0
                Py_DECREF(key);
1929
0
                return -1;
1930
0
            }
1931
0
        }
1932
0
        Py_DECREF(key);
1933
0
    }
1934
0
    return 0;
1935
0
}
1936
1937
static int
1938
set_symmetric_difference_update_set(PySetObject *so, PySetObject *other)
1939
0
{
1940
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1941
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1942
1943
0
    Py_ssize_t pos = 0;
1944
0
    setentry *entry;
1945
0
    while (set_next(other, &pos, &entry)) {
1946
0
        PyObject *key = Py_NewRef(entry->key);
1947
0
        Py_hash_t hash = entry->hash;
1948
0
        int rv = set_discard_entry(so, key, hash);
1949
0
        if (rv < 0) {
1950
0
            Py_DECREF(key);
1951
0
            return -1;
1952
0
        }
1953
0
        if (rv == DISCARD_NOTFOUND) {
1954
0
            if (set_add_entry(so, key, hash)) {
1955
0
                Py_DECREF(key);
1956
0
                return -1;
1957
0
            }
1958
0
        }
1959
0
        Py_DECREF(key);
1960
0
    }
1961
0
    return 0;
1962
0
}
1963
1964
/*[clinic input]
1965
set.symmetric_difference_update
1966
    so: setobject
1967
    other: object
1968
    /
1969
1970
Update the set, keeping only elements found in either set, but not in both.
1971
[clinic start generated code]*/
1972
1973
static PyObject *
1974
set_symmetric_difference_update_impl(PySetObject *so, PyObject *other)
1975
/*[clinic end generated code: output=79f80b4ee5da66c1 input=a50acf0365e1f0a5]*/
1976
0
{
1977
0
    if (Py_Is((PyObject *)so, other)) {
1978
0
        return set_clear((PyObject *)so, NULL);
1979
0
    }
1980
1981
0
    int rv;
1982
0
    if (PyDict_CheckExact(other)) {
1983
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1984
0
        rv = set_symmetric_difference_update_dict(so, other);
1985
0
        Py_END_CRITICAL_SECTION2();
1986
0
    }
1987
0
    else if (PyAnySet_Check(other)) {
1988
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1989
0
        rv = set_symmetric_difference_update_set(so, (PySetObject *)other);
1990
0
        Py_END_CRITICAL_SECTION2();
1991
0
    }
1992
0
    else {
1993
0
        PySetObject *otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
1994
0
        if (otherset == NULL) {
1995
0
            return NULL;
1996
0
        }
1997
1998
0
        Py_BEGIN_CRITICAL_SECTION(so);
1999
0
        rv = set_symmetric_difference_update_set(so, otherset);
2000
0
        Py_END_CRITICAL_SECTION();
2001
2002
0
        Py_DECREF(otherset);
2003
0
    }
2004
0
    if (rv < 0) {
2005
0
        return NULL;
2006
0
    }
2007
0
    Py_RETURN_NONE;
2008
0
}
2009
2010
/*[clinic input]
2011
@critical_section so other
2012
set.symmetric_difference
2013
    so: setobject
2014
    other: object
2015
    /
2016
2017
Return a new set with elements in either the set or other but not both.
2018
[clinic start generated code]*/
2019
2020
static PyObject *
2021
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
2022
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
2023
0
{
2024
0
    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
2025
0
    if (result == NULL) {
2026
0
        return NULL;
2027
0
    }
2028
0
    if (set_update_lock_held(result, other) < 0) {
2029
0
        Py_DECREF(result);
2030
0
        return NULL;
2031
0
    }
2032
0
    if (set_symmetric_difference_update_set(result, so) < 0) {
2033
0
        Py_DECREF(result);
2034
0
        return NULL;
2035
0
    }
2036
0
    return (PyObject *)result;
2037
0
}
2038
2039
static PyObject *
2040
set_xor(PyObject *self, PyObject *other)
2041
0
{
2042
0
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2043
0
        Py_RETURN_NOTIMPLEMENTED;
2044
0
    PySetObject *so = _PySet_CAST(self);
2045
0
    return set_symmetric_difference((PyObject*)so, other);
2046
0
}
2047
2048
static PyObject *
2049
set_ixor(PyObject *self, PyObject *other)
2050
0
{
2051
0
    PyObject *result;
2052
2053
0
    if (!PyAnySet_Check(other))
2054
0
        Py_RETURN_NOTIMPLEMENTED;
2055
0
    PySetObject *so = _PySet_CAST(self);
2056
2057
0
    result = set_symmetric_difference_update((PyObject*)so, other);
2058
0
    if (result == NULL)
2059
0
        return NULL;
2060
0
    Py_DECREF(result);
2061
0
    return Py_NewRef(so);
2062
0
}
2063
2064
/*[clinic input]
2065
@critical_section so other
2066
set.issubset
2067
    so: setobject
2068
    other: object
2069
    /
2070
2071
Report whether another set contains this set.
2072
[clinic start generated code]*/
2073
2074
static PyObject *
2075
set_issubset_impl(PySetObject *so, PyObject *other)
2076
/*[clinic end generated code: output=b2b59d5f314555ce input=f2a4fd0f2537758b]*/
2077
50
{
2078
50
    setentry *entry;
2079
50
    Py_ssize_t pos = 0;
2080
50
    int rv;
2081
2082
50
    if (!PyAnySet_Check(other)) {
2083
0
        PyObject *tmp = set_intersection(so, other);
2084
0
        if (tmp == NULL) {
2085
0
            return NULL;
2086
0
        }
2087
0
        int result = (PySet_GET_SIZE(tmp) == PySet_GET_SIZE(so));
2088
0
        Py_DECREF(tmp);
2089
0
        return PyBool_FromLong(result);
2090
0
    }
2091
50
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2092
0
        Py_RETURN_FALSE;
2093
2094
164
    while (set_next(so, &pos, &entry)) {
2095
114
        PyObject *key = entry->key;
2096
114
        Py_INCREF(key);
2097
114
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2098
114
        Py_DECREF(key);
2099
114
        if (rv < 0) {
2100
0
            return NULL;
2101
0
        }
2102
114
        if (!rv) {
2103
0
            Py_RETURN_FALSE;
2104
0
        }
2105
114
    }
2106
50
    Py_RETURN_TRUE;
2107
50
}
2108
2109
/*[clinic input]
2110
@critical_section so other
2111
set.issuperset
2112
    so: setobject
2113
    other: object
2114
    /
2115
2116
Report whether this set contains another set.
2117
[clinic start generated code]*/
2118
2119
static PyObject *
2120
set_issuperset_impl(PySetObject *so, PyObject *other)
2121
/*[clinic end generated code: output=ecf00ce552c09461 input=5f2e1f262e6e4ccc]*/
2122
282
{
2123
282
    if (PyAnySet_Check(other)) {
2124
0
        return set_issubset(other, (PyObject *)so);
2125
0
    }
2126
2127
282
    PyObject *key, *it = PyObject_GetIter(other);
2128
282
    if (it == NULL) {
2129
0
        return NULL;
2130
0
    }
2131
1.15k
    while ((key = PyIter_Next(it)) != NULL) {
2132
870
        int rv = set_contains_key(so, key);
2133
870
        Py_DECREF(key);
2134
870
        if (rv < 0) {
2135
0
            Py_DECREF(it);
2136
0
            return NULL;
2137
0
        }
2138
870
        if (!rv) {
2139
0
            Py_DECREF(it);
2140
0
            Py_RETURN_FALSE;
2141
0
        }
2142
870
    }
2143
282
    Py_DECREF(it);
2144
282
    if (PyErr_Occurred()) {
2145
0
        return NULL;
2146
0
    }
2147
282
    Py_RETURN_TRUE;
2148
282
}
2149
2150
static PyObject *
2151
set_richcompare(PyObject *self, PyObject *w, int op)
2152
50
{
2153
50
    PySetObject *v = _PySet_CAST(self);
2154
50
    PyObject *r1;
2155
50
    int r2;
2156
2157
50
    if(!PyAnySet_Check(w))
2158
0
        Py_RETURN_NOTIMPLEMENTED;
2159
2160
50
    switch (op) {
2161
16
    case Py_EQ:
2162
16
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
2163
0
            Py_RETURN_FALSE;
2164
16
        Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
2165
16
        Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject *)w)->hash);
2166
16
        if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
2167
0
            Py_RETURN_FALSE;
2168
16
        return set_issubset((PyObject*)v, w);
2169
0
    case Py_NE:
2170
0
        r1 = set_richcompare((PyObject*)v, w, Py_EQ);
2171
0
        if (r1 == NULL)
2172
0
            return NULL;
2173
0
        r2 = PyObject_IsTrue(r1);
2174
0
        Py_DECREF(r1);
2175
0
        if (r2 < 0)
2176
0
            return NULL;
2177
0
        return PyBool_FromLong(!r2);
2178
34
    case Py_LE:
2179
34
        return set_issubset((PyObject*)v, w);
2180
0
    case Py_GE:
2181
0
        return set_issuperset((PyObject*)v, w);
2182
0
    case Py_LT:
2183
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
2184
0
            Py_RETURN_FALSE;
2185
0
        return set_issubset((PyObject*)v, w);
2186
0
    case Py_GT:
2187
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
2188
0
            Py_RETURN_FALSE;
2189
0
        return set_issuperset((PyObject*)v, w);
2190
50
    }
2191
50
    Py_RETURN_NOTIMPLEMENTED;
2192
50
}
2193
2194
/*[clinic input]
2195
@critical_section
2196
set.add
2197
    so: setobject
2198
    object as key: object
2199
    /
2200
2201
Add an element to a set.
2202
2203
This has no effect if the element is already present.
2204
[clinic start generated code]*/
2205
2206
static PyObject *
2207
set_add_impl(PySetObject *so, PyObject *key)
2208
/*[clinic end generated code: output=4cc4a937f1425c96 input=03baf62cb0e66514]*/
2209
568k
{
2210
568k
    if (set_add_key(so, key))
2211
0
        return NULL;
2212
568k
    Py_RETURN_NONE;
2213
568k
}
2214
2215
static int
2216
set_contains_lock_held(PySetObject *so, PyObject *key)
2217
43.8M
{
2218
43.8M
    int rv;
2219
2220
43.8M
    rv = set_contains_key(so, key);
2221
43.8M
    if (rv < 0) {
2222
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2223
0
            return -1;
2224
0
        PyErr_Clear();
2225
0
        Py_hash_t hash;
2226
0
        Py_BEGIN_CRITICAL_SECTION(key);
2227
0
        hash = frozenset_hash_impl(key);
2228
0
        Py_END_CRITICAL_SECTION();
2229
0
        rv = set_contains_entry(so, key, hash);
2230
0
    }
2231
43.8M
    return rv;
2232
43.8M
}
2233
2234
int
2235
_PySet_Contains(PySetObject *so, PyObject *key)
2236
27.2M
{
2237
27.2M
    int rv;
2238
27.2M
    Py_BEGIN_CRITICAL_SECTION(so);
2239
27.2M
    rv = set_contains_lock_held(so, key);
2240
27.2M
    Py_END_CRITICAL_SECTION();
2241
27.2M
    return rv;
2242
27.2M
}
2243
2244
static int
2245
set_contains(PyObject *self, PyObject *key)
2246
348
{
2247
348
    PySetObject *so = _PySet_CAST(self);
2248
348
    return _PySet_Contains(so, key);
2249
348
}
2250
2251
/*[clinic input]
2252
@critical_section
2253
@coexist
2254
set.__contains__
2255
    so: setobject
2256
    object as key: object
2257
    /
2258
2259
x.__contains__(y) <==> y in x.
2260
[clinic start generated code]*/
2261
2262
static PyObject *
2263
set___contains___impl(PySetObject *so, PyObject *key)
2264
/*[clinic end generated code: output=b44863d034b3c70e input=4a7d568459617f24]*/
2265
16.5M
{
2266
16.5M
    long result;
2267
2268
16.5M
    result = set_contains_lock_held(so, key);
2269
16.5M
    if (result < 0)
2270
0
        return NULL;
2271
16.5M
    return PyBool_FromLong(result);
2272
16.5M
}
2273
2274
/*[clinic input]
2275
@coexist
2276
frozenset.__contains__
2277
    so: setobject
2278
    object as key: object
2279
    /
2280
2281
x.__contains__(y) <==> y in x.
2282
[clinic start generated code]*/
2283
2284
static PyObject *
2285
frozenset___contains___impl(PySetObject *so, PyObject *key)
2286
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
2287
221
{
2288
221
    long result;
2289
2290
221
    result = set_contains_lock_held(so, key);
2291
221
    if (result < 0)
2292
0
        return NULL;
2293
221
    return PyBool_FromLong(result);
2294
221
}
2295
2296
/*[clinic input]
2297
@critical_section
2298
set.remove
2299
    so: setobject
2300
    object as key: object
2301
    /
2302
2303
Remove an element from a set; it must be a member.
2304
2305
If the element is not a member, raise a KeyError.
2306
[clinic start generated code]*/
2307
2308
static PyObject *
2309
set_remove_impl(PySetObject *so, PyObject *key)
2310
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2311
0
{
2312
0
    int rv;
2313
2314
0
    rv = set_discard_key(so, key);
2315
0
    if (rv < 0) {
2316
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2317
0
            return NULL;
2318
0
        PyErr_Clear();
2319
0
        Py_hash_t hash;
2320
0
        Py_BEGIN_CRITICAL_SECTION(key);
2321
0
        hash = frozenset_hash_impl(key);
2322
0
        Py_END_CRITICAL_SECTION();
2323
0
        rv = set_discard_entry(so, key, hash);
2324
0
        if (rv < 0)
2325
0
            return NULL;
2326
0
    }
2327
2328
0
    if (rv == DISCARD_NOTFOUND) {
2329
0
        _PyErr_SetKeyError(key);
2330
0
        return NULL;
2331
0
    }
2332
0
    Py_RETURN_NONE;
2333
0
}
2334
2335
/*[clinic input]
2336
@critical_section
2337
set.discard
2338
    so: setobject
2339
    object as key: object
2340
    /
2341
2342
Remove an element from a set if it is a member.
2343
2344
Unlike set.remove(), the discard() method does not raise
2345
an exception when an element is missing from the set.
2346
[clinic start generated code]*/
2347
2348
static PyObject *
2349
set_discard_impl(PySetObject *so, PyObject *key)
2350
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2351
0
{
2352
0
    int rv;
2353
2354
0
    rv = set_discard_key(so, key);
2355
0
    if (rv < 0) {
2356
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2357
0
            return NULL;
2358
0
        PyErr_Clear();
2359
0
        Py_hash_t hash;
2360
0
        Py_BEGIN_CRITICAL_SECTION(key);
2361
0
        hash = frozenset_hash_impl(key);
2362
0
        Py_END_CRITICAL_SECTION();
2363
0
        rv = set_discard_entry(so, key, hash);
2364
0
        if (rv < 0)
2365
0
            return NULL;
2366
0
    }
2367
0
    Py_RETURN_NONE;
2368
0
}
2369
2370
/*[clinic input]
2371
@critical_section
2372
set.__reduce__
2373
    so: setobject
2374
2375
Return state information for pickling.
2376
[clinic start generated code]*/
2377
2378
static PyObject *
2379
set___reduce___impl(PySetObject *so)
2380
/*[clinic end generated code: output=9af7d0e029df87ee input=59405a4249e82f71]*/
2381
0
{
2382
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
2383
2384
0
    keys = PySequence_List((PyObject *)so);
2385
0
    if (keys == NULL)
2386
0
        goto done;
2387
0
    args = PyTuple_Pack(1, keys);
2388
0
    if (args == NULL)
2389
0
        goto done;
2390
0
    state = _PyObject_GetState((PyObject *)so);
2391
0
    if (state == NULL)
2392
0
        goto done;
2393
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, state);
2394
0
done:
2395
0
    Py_XDECREF(args);
2396
0
    Py_XDECREF(keys);
2397
0
    Py_XDECREF(state);
2398
0
    return result;
2399
0
}
2400
2401
/*[clinic input]
2402
@critical_section
2403
set.__sizeof__
2404
    so: setobject
2405
2406
S.__sizeof__() -> size of S in memory, in bytes.
2407
[clinic start generated code]*/
2408
2409
static PyObject *
2410
set___sizeof___impl(PySetObject *so)
2411
/*[clinic end generated code: output=4bfa3df7bd38ed88 input=09e1a09f168eaa23]*/
2412
0
{
2413
0
    size_t res = _PyObject_SIZE(Py_TYPE(so));
2414
0
    if (so->table != so->smalltable) {
2415
0
        res += ((size_t)so->mask + 1) * sizeof(setentry);
2416
0
    }
2417
0
    return PyLong_FromSize_t(res);
2418
0
}
2419
2420
static int
2421
set_init(PyObject *so, PyObject *args, PyObject *kwds)
2422
0
{
2423
0
    PySetObject *self = _PySet_CAST(so);
2424
0
    PyObject *iterable = NULL;
2425
2426
0
    if (!_PyArg_NoKeywords("set", kwds))
2427
0
        return -1;
2428
0
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
2429
0
        return -1;
2430
2431
0
    if (Py_REFCNT(self) == 1 && self->fill == 0) {
2432
0
        self->hash = -1;
2433
0
        if (iterable == NULL) {
2434
0
            return 0;
2435
0
        }
2436
0
        return set_update_local(self, iterable);
2437
0
    }
2438
0
    Py_BEGIN_CRITICAL_SECTION(self);
2439
0
    if (self->fill)
2440
0
        set_clear_internal((PyObject*)self);
2441
0
    self->hash = -1;
2442
0
    Py_END_CRITICAL_SECTION();
2443
2444
0
    if (iterable == NULL)
2445
0
        return 0;
2446
0
    return set_update_internal(self, iterable);
2447
0
}
2448
2449
static PyObject*
2450
set_vectorcall(PyObject *type, PyObject * const*args,
2451
               size_t nargsf, PyObject *kwnames)
2452
647k
{
2453
647k
    assert(PyType_Check(type));
2454
2455
647k
    if (!_PyArg_NoKwnames("set", kwnames)) {
2456
0
        return NULL;
2457
0
    }
2458
2459
647k
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2460
647k
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2461
0
        return NULL;
2462
0
    }
2463
2464
647k
    if (nargs) {
2465
15.6k
        return make_new_set(_PyType_CAST(type), args[0]);
2466
15.6k
    }
2467
2468
631k
    return make_new_set(_PyType_CAST(type), NULL);
2469
647k
}
2470
2471
static PySequenceMethods set_as_sequence = {
2472
    set_len,                            /* sq_length */
2473
    0,                                  /* sq_concat */
2474
    0,                                  /* sq_repeat */
2475
    0,                                  /* sq_item */
2476
    0,                                  /* sq_slice */
2477
    0,                                  /* sq_ass_item */
2478
    0,                                  /* sq_ass_slice */
2479
    set_contains,                       /* sq_contains */
2480
};
2481
2482
/* set object ********************************************************/
2483
2484
static PyMethodDef set_methods[] = {
2485
    SET_ADD_METHODDEF
2486
    SET_CLEAR_METHODDEF
2487
    SET___CONTAINS___METHODDEF
2488
    SET_COPY_METHODDEF
2489
    SET_DISCARD_METHODDEF
2490
    SET_DIFFERENCE_MULTI_METHODDEF
2491
    SET_DIFFERENCE_UPDATE_METHODDEF
2492
    SET_INTERSECTION_MULTI_METHODDEF
2493
    SET_INTERSECTION_UPDATE_MULTI_METHODDEF
2494
    SET_ISDISJOINT_METHODDEF
2495
    SET_ISSUBSET_METHODDEF
2496
    SET_ISSUPERSET_METHODDEF
2497
    SET_POP_METHODDEF
2498
    SET___REDUCE___METHODDEF
2499
    SET_REMOVE_METHODDEF
2500
    SET___SIZEOF___METHODDEF
2501
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2502
    SET_SYMMETRIC_DIFFERENCE_UPDATE_METHODDEF
2503
    SET_UNION_METHODDEF
2504
    SET_UPDATE_METHODDEF
2505
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2506
    {NULL,              NULL}   /* sentinel */
2507
};
2508
2509
static PyNumberMethods set_as_number = {
2510
    0,                                  /*nb_add*/
2511
    set_sub,                            /*nb_subtract*/
2512
    0,                                  /*nb_multiply*/
2513
    0,                                  /*nb_remainder*/
2514
    0,                                  /*nb_divmod*/
2515
    0,                                  /*nb_power*/
2516
    0,                                  /*nb_negative*/
2517
    0,                                  /*nb_positive*/
2518
    0,                                  /*nb_absolute*/
2519
    0,                                  /*nb_bool*/
2520
    0,                                  /*nb_invert*/
2521
    0,                                  /*nb_lshift*/
2522
    0,                                  /*nb_rshift*/
2523
    set_and,                            /*nb_and*/
2524
    set_xor,                            /*nb_xor*/
2525
    set_or,                             /*nb_or*/
2526
    0,                                  /*nb_int*/
2527
    0,                                  /*nb_reserved*/
2528
    0,                                  /*nb_float*/
2529
    0,                                  /*nb_inplace_add*/
2530
    set_isub,                           /*nb_inplace_subtract*/
2531
    0,                                  /*nb_inplace_multiply*/
2532
    0,                                  /*nb_inplace_remainder*/
2533
    0,                                  /*nb_inplace_power*/
2534
    0,                                  /*nb_inplace_lshift*/
2535
    0,                                  /*nb_inplace_rshift*/
2536
    set_iand,                           /*nb_inplace_and*/
2537
    set_ixor,                           /*nb_inplace_xor*/
2538
    set_ior,                            /*nb_inplace_or*/
2539
};
2540
2541
PyDoc_STRVAR(set_doc,
2542
"set(iterable=(), /)\n\
2543
--\n\
2544
\n\
2545
Build an unordered collection of unique elements.");
2546
2547
PyTypeObject PySet_Type = {
2548
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2549
    "set",                              /* tp_name */
2550
    sizeof(PySetObject),                /* tp_basicsize */
2551
    0,                                  /* tp_itemsize */
2552
    /* methods */
2553
    set_dealloc,                        /* tp_dealloc */
2554
    0,                                  /* tp_vectorcall_offset */
2555
    0,                                  /* tp_getattr */
2556
    0,                                  /* tp_setattr */
2557
    0,                                  /* tp_as_async */
2558
    set_repr,                           /* tp_repr */
2559
    &set_as_number,                     /* tp_as_number */
2560
    &set_as_sequence,                   /* tp_as_sequence */
2561
    0,                                  /* tp_as_mapping */
2562
    PyObject_HashNotImplemented,        /* tp_hash */
2563
    0,                                  /* tp_call */
2564
    0,                                  /* tp_str */
2565
    PyObject_GenericGetAttr,            /* tp_getattro */
2566
    0,                                  /* tp_setattro */
2567
    0,                                  /* tp_as_buffer */
2568
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2569
        Py_TPFLAGS_BASETYPE |
2570
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2571
    set_doc,                            /* tp_doc */
2572
    set_traverse,                       /* tp_traverse */
2573
    set_clear_internal,                 /* tp_clear */
2574
    set_richcompare,                    /* tp_richcompare */
2575
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2576
    set_iter,                           /* tp_iter */
2577
    0,                                  /* tp_iternext */
2578
    set_methods,                        /* tp_methods */
2579
    0,                                  /* tp_members */
2580
    0,                                  /* tp_getset */
2581
    0,                                  /* tp_base */
2582
    0,                                  /* tp_dict */
2583
    0,                                  /* tp_descr_get */
2584
    0,                                  /* tp_descr_set */
2585
    0,                                  /* tp_dictoffset */
2586
    set_init,                           /* tp_init */
2587
    PyType_GenericAlloc,                /* tp_alloc */
2588
    set_new,                            /* tp_new */
2589
    PyObject_GC_Del,                    /* tp_free */
2590
    .tp_vectorcall = set_vectorcall,
2591
    .tp_version_tag = _Py_TYPE_VERSION_SET,
2592
};
2593
2594
/* frozenset object ********************************************************/
2595
2596
2597
static PyMethodDef frozenset_methods[] = {
2598
    FROZENSET___CONTAINS___METHODDEF
2599
    FROZENSET_COPY_METHODDEF
2600
    SET_DIFFERENCE_MULTI_METHODDEF
2601
    SET_INTERSECTION_MULTI_METHODDEF
2602
    SET_ISDISJOINT_METHODDEF
2603
    SET_ISSUBSET_METHODDEF
2604
    SET_ISSUPERSET_METHODDEF
2605
    SET___REDUCE___METHODDEF
2606
    SET___SIZEOF___METHODDEF
2607
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2608
    SET_UNION_METHODDEF
2609
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2610
    {NULL,              NULL}   /* sentinel */
2611
};
2612
2613
static PyNumberMethods frozenset_as_number = {
2614
    0,                                  /*nb_add*/
2615
    set_sub,                            /*nb_subtract*/
2616
    0,                                  /*nb_multiply*/
2617
    0,                                  /*nb_remainder*/
2618
    0,                                  /*nb_divmod*/
2619
    0,                                  /*nb_power*/
2620
    0,                                  /*nb_negative*/
2621
    0,                                  /*nb_positive*/
2622
    0,                                  /*nb_absolute*/
2623
    0,                                  /*nb_bool*/
2624
    0,                                  /*nb_invert*/
2625
    0,                                  /*nb_lshift*/
2626
    0,                                  /*nb_rshift*/
2627
    set_and,                            /*nb_and*/
2628
    set_xor,                            /*nb_xor*/
2629
    set_or,                             /*nb_or*/
2630
};
2631
2632
PyDoc_STRVAR(frozenset_doc,
2633
"frozenset(iterable=(), /)\n\
2634
--\n\
2635
\n\
2636
Build an immutable unordered collection of unique elements.");
2637
2638
PyTypeObject PyFrozenSet_Type = {
2639
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2640
    "frozenset",                        /* tp_name */
2641
    sizeof(PySetObject),                /* tp_basicsize */
2642
    0,                                  /* tp_itemsize */
2643
    /* methods */
2644
    set_dealloc,                        /* tp_dealloc */
2645
    0,                                  /* tp_vectorcall_offset */
2646
    0,                                  /* tp_getattr */
2647
    0,                                  /* tp_setattr */
2648
    0,                                  /* tp_as_async */
2649
    set_repr,                           /* tp_repr */
2650
    &frozenset_as_number,               /* tp_as_number */
2651
    &set_as_sequence,                   /* tp_as_sequence */
2652
    0,                                  /* tp_as_mapping */
2653
    frozenset_hash,                     /* tp_hash */
2654
    0,                                  /* tp_call */
2655
    0,                                  /* tp_str */
2656
    PyObject_GenericGetAttr,            /* tp_getattro */
2657
    0,                                  /* tp_setattro */
2658
    0,                                  /* tp_as_buffer */
2659
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2660
        Py_TPFLAGS_BASETYPE |
2661
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2662
    frozenset_doc,                      /* tp_doc */
2663
    set_traverse,                       /* tp_traverse */
2664
    set_clear_internal,                 /* tp_clear */
2665
    set_richcompare,                    /* tp_richcompare */
2666
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2667
    set_iter,                           /* tp_iter */
2668
    0,                                  /* tp_iternext */
2669
    frozenset_methods,                  /* tp_methods */
2670
    0,                                  /* tp_members */
2671
    0,                                  /* tp_getset */
2672
    0,                                  /* tp_base */
2673
    0,                                  /* tp_dict */
2674
    0,                                  /* tp_descr_get */
2675
    0,                                  /* tp_descr_set */
2676
    0,                                  /* tp_dictoffset */
2677
    0,                                  /* tp_init */
2678
    PyType_GenericAlloc,                /* tp_alloc */
2679
    frozenset_new,                      /* tp_new */
2680
    PyObject_GC_Del,                    /* tp_free */
2681
    .tp_vectorcall = frozenset_vectorcall,
2682
    .tp_version_tag = _Py_TYPE_VERSION_FROZEN_SET,
2683
};
2684
2685
2686
/***** C API functions *************************************************/
2687
2688
PyObject *
2689
PySet_New(PyObject *iterable)
2690
92.3k
{
2691
92.3k
    return make_new_set(&PySet_Type, iterable);
2692
92.3k
}
2693
2694
PyObject *
2695
PyFrozenSet_New(PyObject *iterable)
2696
1.49k
{
2697
1.49k
    return make_new_set(&PyFrozenSet_Type, iterable);
2698
1.49k
}
2699
2700
Py_ssize_t
2701
PySet_Size(PyObject *anyset)
2702
16
{
2703
16
    if (!PyAnySet_Check(anyset)) {
2704
0
        PyErr_BadInternalCall();
2705
0
        return -1;
2706
0
    }
2707
16
    return set_len(anyset);
2708
16
}
2709
2710
int
2711
PySet_Clear(PyObject *set)
2712
160
{
2713
160
    if (!PySet_Check(set)) {
2714
0
        PyErr_BadInternalCall();
2715
0
        return -1;
2716
0
    }
2717
160
    (void)set_clear(set, NULL);
2718
160
    return 0;
2719
160
}
2720
2721
void
2722
_PySet_ClearInternal(PySetObject *so)
2723
0
{
2724
0
    (void)set_clear_internal((PyObject*)so);
2725
0
}
2726
2727
int
2728
PySet_Contains(PyObject *anyset, PyObject *key)
2729
105k
{
2730
105k
    if (!PyAnySet_Check(anyset)) {
2731
0
        PyErr_BadInternalCall();
2732
0
        return -1;
2733
0
    }
2734
2735
105k
    int rv;
2736
105k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2737
105k
    rv = set_contains_key((PySetObject *)anyset, key);
2738
105k
    Py_END_CRITICAL_SECTION();
2739
105k
    return rv;
2740
105k
}
2741
2742
int
2743
PySet_Discard(PyObject *set, PyObject *key)
2744
58.4k
{
2745
58.4k
    if (!PySet_Check(set)) {
2746
0
        PyErr_BadInternalCall();
2747
0
        return -1;
2748
0
    }
2749
2750
58.4k
    int rv;
2751
58.4k
    Py_BEGIN_CRITICAL_SECTION(set);
2752
58.4k
    rv = set_discard_key((PySetObject *)set, key);
2753
58.4k
    Py_END_CRITICAL_SECTION();
2754
58.4k
    return rv;
2755
58.4k
}
2756
2757
int
2758
PySet_Add(PyObject *anyset, PyObject *key)
2759
38.1k
{
2760
38.1k
    if (!PySet_Check(anyset) &&
2761
38.1k
        (!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) {
2762
0
        PyErr_BadInternalCall();
2763
0
        return -1;
2764
0
    }
2765
2766
38.1k
    int rv;
2767
38.1k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2768
38.1k
    rv = set_add_key((PySetObject *)anyset, key);
2769
38.1k
    Py_END_CRITICAL_SECTION();
2770
38.1k
    return rv;
2771
38.1k
}
2772
2773
int
2774
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2775
754
{
2776
754
    setentry *entry;
2777
2778
754
    if (!PyAnySet_Check(set)) {
2779
0
        PyErr_BadInternalCall();
2780
0
        return -1;
2781
0
    }
2782
754
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2783
220
        return 0;
2784
534
    *key = entry->key;
2785
534
    *hash = entry->hash;
2786
534
    return 1;
2787
754
}
2788
2789
int
2790
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2791
127k
{
2792
127k
    setentry *entry;
2793
2794
127k
    if (!PyAnySet_Check(set)) {
2795
0
        PyErr_BadInternalCall();
2796
0
        return -1;
2797
0
    }
2798
127k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
2799
127k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2800
17.4k
        return 0;
2801
110k
    *key = Py_NewRef(entry->key);
2802
110k
    *hash = entry->hash;
2803
110k
    return 1;
2804
127k
}
2805
2806
PyObject *
2807
PySet_Pop(PyObject *set)
2808
9
{
2809
9
    if (!PySet_Check(set)) {
2810
0
        PyErr_BadInternalCall();
2811
0
        return NULL;
2812
0
    }
2813
9
    return set_pop(set, NULL);
2814
9
}
2815
2816
int
2817
_PySet_Update(PyObject *set, PyObject *iterable)
2818
10
{
2819
10
    if (!PySet_Check(set)) {
2820
0
        PyErr_BadInternalCall();
2821
0
        return -1;
2822
0
    }
2823
10
    return set_update_internal((PySetObject *)set, iterable);
2824
10
}
2825
2826
/* Exported for the gdb plugin's benefit. */
2827
PyObject *_PySet_Dummy = dummy;
2828
2829
/***** Dummy Struct  *************************************************/
2830
2831
static PyObject *
2832
dummy_repr(PyObject *op)
2833
0
{
2834
0
    return PyUnicode_FromString("<dummy key>");
2835
0
}
2836
2837
static void _Py_NO_RETURN
2838
dummy_dealloc(PyObject* ignore)
2839
0
{
2840
0
    Py_FatalError("deallocating <dummy key>");
2841
0
}
2842
2843
static PyTypeObject _PySetDummy_Type = {
2844
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2845
    "<dummy key> type",
2846
    0,
2847
    0,
2848
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
2849
    0,                  /*tp_vectorcall_offset*/
2850
    0,                  /*tp_getattr*/
2851
    0,                  /*tp_setattr*/
2852
    0,                  /*tp_as_async*/
2853
    dummy_repr,         /*tp_repr*/
2854
    0,                  /*tp_as_number*/
2855
    0,                  /*tp_as_sequence*/
2856
    0,                  /*tp_as_mapping*/
2857
    0,                  /*tp_hash */
2858
    0,                  /*tp_call */
2859
    0,                  /*tp_str */
2860
    0,                  /*tp_getattro */
2861
    0,                  /*tp_setattro */
2862
    0,                  /*tp_as_buffer */
2863
    Py_TPFLAGS_DEFAULT, /*tp_flags */
2864
};
2865
2866
static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type);