Coverage Report

Created: 2025-09-05 07:10

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