Coverage Report

Created: 2026-05-30 06:18

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