Coverage Report

Created: 2026-02-26 06:53

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
6.28M
#define dummy (&_dummy_struct)
65
66
113M
#define SET_LOOKKEY_FOUND 1
67
596M
#define SET_LOOKKEY_NO_MATCH 0
68
0
#define SET_LOOKKEY_ERROR (-1)
69
91.7M
#define SET_LOOKKEY_CHANGED (-2)
70
435M
#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
33.8k
#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
112M
{
141
112M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
142
112M
    if (entry->hash == 0 && entry->key == NULL)
143
40.6M
        return SET_LOOKKEY_EMPTY;
144
71.5M
    if (entry->hash == hash) {
145
51.1M
        PyObject *startkey = entry->key;
146
51.1M
        assert(startkey != dummy);
147
51.1M
        if (startkey == key)
148
51.0M
            return SET_LOOKKEY_FOUND;
149
20.5k
        if (PyUnicode_CheckExact(startkey)
150
20.5k
            && PyUnicode_CheckExact(key)
151
4.05k
            && unicode_eq(startkey, key))
152
4.05k
            return SET_LOOKKEY_FOUND;
153
16.5k
        table = so->table;
154
16.5k
        Py_INCREF(startkey);
155
16.5k
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
156
16.5k
        Py_DECREF(startkey);
157
16.5k
        if (cmp < 0)
158
0
            return SET_LOOKKEY_ERROR;
159
16.5k
        if (table != so->table || entry->key != startkey)
160
0
            return SET_LOOKKEY_CHANGED;
161
16.5k
        if (cmp > 0)
162
16.5k
            return SET_LOOKKEY_FOUND;
163
16.5k
    }
164
20.4M
    return SET_LOOKKEY_NO_MATCH;
165
71.5M
}
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
243M
{
175
243M
    assert(PyFrozenSet_Check(so));
176
243M
    PyObject *startkey = ep->key;
177
243M
    if (startkey == NULL) {
178
120M
        return SET_LOOKKEY_EMPTY;
179
120M
    }
180
122M
    if (startkey == key) {
181
62.5M
        return SET_LOOKKEY_FOUND;
182
62.5M
    }
183
60.2M
    Py_ssize_t ep_hash = ep->hash;
184
60.2M
    if (ep_hash == hash) {
185
678
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
186
678
        if (cmp < 0) {
187
0
            return SET_LOOKKEY_ERROR;
188
0
        }
189
678
        assert(cmp == SET_LOOKKEY_FOUND || cmp == SET_LOOKKEY_NO_MATCH);
190
678
        return cmp;
191
678
    }
192
60.2M
    return SET_LOOKKEY_NO_MATCH;
193
60.2M
}
194
195
static void
196
set_zero_table(setentry *table, size_t size)
197
47.4k
{
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
47.4k
    memset(table, 0, sizeof(setentry)*size);
206
47.4k
#endif
207
47.4k
}
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
439M
#define LINEAR_PROBES 9
215
#endif
216
217
/* This must be >= 1 */
218
15.9M
#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
274M
{
224
274M
    setentry *entry;
225
274M
    size_t perturb = hash;
226
274M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
227
274M
    int probes;
228
274M
    int status;
229
230
290M
    while (1) {
231
290M
        entry = &table[i];
232
290M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
233
355M
        do {
234
355M
            status = compare_entry(so, table, entry, key, hash);
235
355M
            if (status != SET_LOOKKEY_NO_MATCH) {
236
274M
                if (status == SET_LOOKKEY_EMPTY) {
237
160M
                    return SET_LOOKKEY_NO_MATCH;
238
160M
                }
239
113M
                *epp = entry;
240
113M
                return status;
241
274M
            }
242
80.6M
            entry++;
243
80.6M
        } while (probes--);
244
15.7M
        perturb >>= PERTURB_SHIFT;
245
15.7M
        i = (i * 5 + 1 + perturb) & mask;
246
15.7M
    }
247
274M
    Py_UNREACHABLE();
248
274M
}
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
6.69M
{
255
6.69M
    setentry *table;
256
6.69M
    setentry *freeslot;
257
6.69M
    setentry *entry;
258
6.69M
    size_t perturb;
259
6.69M
    size_t mask;
260
6.69M
    size_t i;                       /* Unsigned for defined overflow behavior */
261
6.69M
    int probes;
262
6.69M
    int cmp;
263
264
6.69M
  restart:
265
266
6.69M
    mask = so->mask;
267
6.69M
    i = (size_t)hash & mask;
268
6.69M
    freeslot = NULL;
269
6.69M
    perturb = hash;
270
271
6.92M
    while (1) {
272
6.92M
        entry = &so->table[i];
273
6.92M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
274
9.94M
        do {
275
9.94M
            if (entry->hash == 0 && entry->key == NULL)
276
3.32M
                goto found_unused_or_dummy;
277
6.62M
            if (entry->hash == hash) {
278
3.37M
                PyObject *startkey = entry->key;
279
3.37M
                assert(startkey != dummy);
280
3.37M
                if (startkey == key)
281
83.5k
                    goto found_active;
282
3.29M
                if (PyUnicode_CheckExact(startkey)
283
3.29M
                    && PyUnicode_CheckExact(key)
284
456k
                    && unicode_eq(startkey, key))
285
456k
                    goto found_active;
286
2.83M
                table = so->table;
287
2.83M
                Py_INCREF(startkey);
288
2.83M
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
289
2.83M
                Py_DECREF(startkey);
290
2.83M
                if (cmp > 0)
291
2.83M
                    goto found_active;
292
945
                if (cmp < 0)
293
0
                    goto comparison_error;
294
945
                if (table != so->table || entry->key != startkey)
295
0
                    goto restart;
296
945
                mask = so->mask;
297
945
            }
298
3.24M
            else if (entry->hash == -1) {
299
0
                assert (entry->key == dummy);
300
0
                freeslot = entry;
301
0
            }
302
3.24M
            entry++;
303
3.24M
        } while (probes--);
304
230k
        perturb >>= PERTURB_SHIFT;
305
230k
        i = (i * 5 + 1 + perturb) & mask;
306
230k
    }
307
308
3.32M
  found_unused_or_dummy:
309
3.32M
    if (freeslot == NULL)
310
3.32M
        goto found_unused;
311
0
    if (freeslot->hash != -1) {
312
0
        goto restart;
313
0
    }
314
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
315
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(freeslot->hash, hash);
316
0
    FT_ATOMIC_STORE_PTR_RELEASE(freeslot->key, key);
317
0
    return 0;
318
319
3.32M
  found_unused:
320
3.32M
    so->fill++;
321
3.32M
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
322
3.32M
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, hash);
323
3.32M
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, key);
324
3.32M
    if ((size_t)so->fill*5 < mask*3)
325
3.29M
        return 0;
326
30.6k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
327
328
3.37M
  found_active:
329
3.37M
    Py_DECREF(key);
330
3.37M
    return 0;
331
332
0
  comparison_error:
333
0
    Py_DECREF(key);
334
0
    return -1;
335
3.32M
}
336
337
static int
338
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
339
6.68M
{
340
6.68M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
341
342
6.68M
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
343
6.68M
}
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
6.61k
{
364
6.61k
    Py_hash_t hash = _PyObject_HashFast(key);
365
6.61k
    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
6.61k
    return set_add_entry_takeref(so, key, hash);
373
6.61k
}
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.92M
{
386
1.92M
    setentry *entry;
387
1.92M
    size_t perturb = hash;
388
1.92M
    size_t i = (size_t)hash & mask;
389
1.92M
    size_t j;
390
391
1.93M
    while (1) {
392
1.93M
        entry = &table[i];
393
1.93M
        if (entry->key == NULL)
394
1.78M
            goto found_null;
395
147k
        if (i + LINEAR_PROBES <= mask) {
396
210k
            for (j = 0; j < LINEAR_PROBES; j++) {
397
206k
                entry++;
398
206k
                if (entry->key == NULL)
399
138k
                    goto found_null;
400
206k
            }
401
143k
        }
402
8.19k
        perturb >>= PERTURB_SHIFT;
403
8.19k
        i = (i * 5 + 1 + perturb) & mask;
404
8.19k
    }
405
1.92M
  found_null:
406
1.92M
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, hash);
407
1.92M
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, key);
408
1.92M
}
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
274M
{
416
274M
    int status;
417
274M
    if (PyFrozenSet_CheckExact(so)) {
418
182M
        status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
419
182M
                               set_compare_frozenset);
420
182M
    }
421
91.7M
    else {
422
91.7M
        Py_BEGIN_CRITICAL_SECTION(so);
423
91.7M
        do {
424
91.7M
            status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
425
91.7M
                                   set_compare_entry_lock_held);
426
91.7M
        } while (status == SET_LOOKKEY_CHANGED);
427
91.7M
        Py_END_CRITICAL_SECTION();
428
91.7M
    }
429
274M
    assert(status == SET_LOOKKEY_FOUND ||
430
274M
           status == SET_LOOKKEY_NO_MATCH ||
431
274M
           status == SET_LOOKKEY_ERROR);
432
274M
    return status;
433
274M
}
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
33.8k
{
469
#ifdef Py_GIL_DISABLED
470
    if (use_qsbr) {
471
        _PyMem_FreeDelayed(entries, size * sizeof(setentry));
472
        return;
473
    }
474
#endif
475
33.8k
    PyMem_Free(entries);
476
33.8k
}
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
35.1k
{
486
35.1k
    setentry *oldtable, *newtable, *entry;
487
35.1k
    Py_ssize_t oldmask = so->mask;
488
35.1k
    Py_ssize_t oldsize = (size_t)oldmask + 1;
489
35.1k
    size_t newmask;
490
35.1k
    int is_oldtable_malloced;
491
35.1k
    setentry small_copy[PySet_MINSIZE];
492
493
35.1k
    assert(minused >= 0);
494
495
    /* Find the smallest table size > minused. */
496
    /* XXX speed-up with intrinsics */
497
35.1k
    size_t newsize = PySet_MINSIZE;
498
138k
    while (newsize <= (size_t)minused) {
499
103k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
500
103k
    }
501
502
    /* Get space for a new table. */
503
35.1k
    oldtable = so->table;
504
35.1k
    assert(oldtable != NULL);
505
35.1k
    is_oldtable_malloced = oldtable != so->smalltable;
506
507
35.1k
    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
35.1k
    else {
527
35.1k
        newtable = PyMem_NEW(setentry, newsize);
528
35.1k
        if (newtable == NULL) {
529
0
            PyErr_NoMemory();
530
0
            return -1;
531
0
        }
532
35.1k
    }
533
534
    /* Make the set empty, using the new table. */
535
35.1k
    assert(newtable != oldtable);
536
35.1k
    set_zero_table(newtable, newsize);
537
35.1k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, NULL);
538
35.1k
    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
35.1k
    newmask = (size_t)so->mask;
543
35.1k
    if (so->fill == so->used) {
544
3.25M
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
545
3.21M
            if (entry->key != NULL) {
546
1.91M
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
547
1.91M
            }
548
3.21M
        }
549
35.1k
    } else {
550
0
        so->fill = so->used;
551
0
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
552
0
            if (entry->key != NULL && entry->key != dummy) {
553
0
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
554
0
            }
555
0
        }
556
0
    }
557
558
35.1k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, newtable);
559
560
35.1k
    if (is_oldtable_malloced)
561
12.0k
        free_entries(oldtable, oldsize, SET_IS_SHARED(so));
562
35.1k
    return 0;
563
35.1k
}
564
565
static int
566
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
567
274M
{
568
#ifdef Py_GIL_DISABLED
569
    return set_lookkey_threadsafe(so, key, hash);
570
#else
571
274M
    setentry *entry; // unused
572
274M
    return set_lookkey(so, key, hash, &entry);
573
274M
#endif
574
274M
}
575
576
40.1k
#define DISCARD_NOTFOUND 0
577
1.04k
#define DISCARD_FOUND 1
578
579
static int
580
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
581
41.1k
{
582
41.1k
    setentry *entry;
583
41.1k
    PyObject *old_key;
584
41.1k
    int status = set_lookkey(so, key, hash, &entry);
585
41.1k
    if (status < 0) {
586
0
        return -1;
587
0
    }
588
41.1k
    if (status == SET_LOOKKEY_NO_MATCH) {
589
40.1k
        return DISCARD_NOTFOUND;
590
40.1k
    }
591
41.1k
    assert(status == SET_LOOKKEY_FOUND);
592
1.04k
    old_key = entry->key;
593
1.04k
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, -1);
594
1.04k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
595
1.04k
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, dummy);
596
1.04k
    Py_DECREF(old_key);
597
1.04k
    return DISCARD_FOUND;
598
41.1k
}
599
600
static int
601
set_add_key(PySetObject *so, PyObject *key)
602
6.65M
{
603
6.65M
    Py_hash_t hash = _PyObject_HashFast(key);
604
6.65M
    if (hash == -1) {
605
0
        set_unhashable_type(key);
606
0
        return -1;
607
0
    }
608
6.65M
    return set_add_entry(so, key, hash);
609
6.65M
}
610
611
static int
612
set_contains_key(PySetObject *so, PyObject *key)
613
3.01M
{
614
3.01M
    Py_hash_t hash = _PyObject_HashFast(key);
615
3.01M
    if (hash == -1) {
616
0
        set_unhashable_type(key);
617
0
        return -1;
618
0
    }
619
3.01M
    return set_contains_entry(so, key, hash);
620
3.01M
}
621
622
static int
623
set_discard_key(PySetObject *so, PyObject *key)
624
41.1k
{
625
41.1k
    Py_hash_t hash = _PyObject_HashFast(key);
626
41.1k
    if (hash == -1) {
627
0
        set_unhashable_type(key);
628
0
        return -1;
629
0
    }
630
41.1k
    return set_discard_entry(so, key, hash);
631
41.1k
}
632
633
static void
634
set_empty_to_minsize(PySetObject *so)
635
12.2k
{
636
12.2k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, NULL);
637
12.2k
    set_zero_table(so->smalltable, PySet_MINSIZE);
638
12.2k
    so->fill = 0;
639
12.2k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
640
12.2k
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->mask, PySet_MINSIZE - 1);
641
12.2k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
642
12.2k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, so->smalltable);
643
12.2k
}
644
645
static int
646
set_clear_internal(PyObject *self)
647
33.3k
{
648
33.3k
    PySetObject *so = _PySet_CAST(self);
649
33.3k
    setentry *entry;
650
33.3k
    setentry *table = so->table;
651
33.3k
    Py_ssize_t fill = so->fill;
652
33.3k
    Py_ssize_t used = so->used;
653
33.3k
    Py_ssize_t oldsize = (size_t)so->mask + 1;
654
33.3k
    int table_is_malloced = table != so->smalltable;
655
33.3k
    setentry small_copy[PySet_MINSIZE];
656
657
33.3k
    assert (PyAnySet_Check(so));
658
33.3k
    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
33.3k
    if (table_is_malloced)
667
6.79k
        set_empty_to_minsize(so);
668
669
26.5k
    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.50k
        memcpy(small_copy, table, sizeof(small_copy));
675
5.50k
        table = small_copy;
676
5.50k
        set_empty_to_minsize(so);
677
5.50k
    }
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
2.33M
    for (entry = table; used > 0; entry++) {
685
2.29M
        if (entry->key && entry->key != dummy) {
686
669k
            used--;
687
669k
            Py_DECREF(entry->key);
688
669k
        }
689
2.29M
    }
690
691
33.3k
    if (table_is_malloced)
692
6.79k
        free_entries(table, oldsize, SET_IS_SHARED(so));
693
33.3k
    return 0;
694
33.3k
}
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.46M
{
712
5.46M
    Py_ssize_t i;
713
5.46M
    Py_ssize_t mask;
714
5.46M
    setentry *entry;
715
716
5.46M
    assert (PyAnySet_Check(so));
717
5.46M
    i = *pos_ptr;
718
5.46M
    assert(i >= 0);
719
5.46M
    mask = so->mask;
720
5.46M
    entry = &so->table[i];
721
36.2M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
722
30.7M
        i++;
723
30.7M
        entry++;
724
30.7M
    }
725
5.46M
    *pos_ptr = i+1;
726
5.46M
    if (i > mask)
727
3.34M
        return 0;
728
5.46M
    assert(entry != NULL);
729
2.12M
    *entry_ptr = entry;
730
2.12M
    return 1;
731
5.46M
}
732
733
static void
734
set_dealloc(PyObject *self)
735
3.82M
{
736
3.82M
    PySetObject *so = _PySet_CAST(self);
737
3.82M
    setentry *entry;
738
3.82M
    Py_ssize_t used = so->used;
739
3.82M
    Py_ssize_t oldsize = (size_t)so->mask + 1;
740
741
    /* bpo-31095: UnTrack is needed before calling any callbacks */
742
3.82M
    PyObject_GC_UnTrack(so);
743
3.82M
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
744
745
13.3M
    for (entry = so->table; used > 0; entry++) {
746
9.49M
        if (entry->key && entry->key != dummy) {
747
2.66M
                used--;
748
2.66M
                Py_DECREF(entry->key);
749
2.66M
        }
750
9.49M
    }
751
3.82M
    if (so->table != so->smalltable)
752
15.0k
        free_entries(so->table, oldsize, SET_IS_SHARED(so));
753
3.82M
    Py_TYPE(so)->tp_free(so);
754
3.82M
}
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
320k
{
824
320k
    PySetObject *so = _PySet_CAST(self);
825
320k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
826
320k
}
827
828
static int
829
set_merge_lock_held(PySetObject *so, PyObject *otherset)
830
67.3k
{
831
67.3k
    PySetObject *other;
832
67.3k
    PyObject *key;
833
67.3k
    Py_ssize_t i;
834
67.3k
    setentry *so_entry;
835
67.3k
    setentry *other_entry;
836
837
67.3k
    assert (PyAnySet_Check(so));
838
67.3k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
839
67.3k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
840
841
67.3k
    other = _PySet_CAST(otherset);
842
67.3k
    if (other == so || other->used == 0)
843
        /* a.update(a) or a.update(set()); nothing to do */
844
40.0k
        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
27.3k
    if ((so->fill + other->used)*5 >= so->mask*3) {
850
4.48k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
851
0
            return -1;
852
4.48k
    }
853
27.3k
    so_entry = so->table;
854
27.3k
    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
27.3k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
859
211k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
860
193k
            key = other_entry->key;
861
193k
            if (key != NULL) {
862
50.9k
                assert(so_entry->key == NULL);
863
50.9k
                FT_ATOMIC_STORE_SSIZE_RELAXED(so_entry->hash, other_entry->hash);
864
50.9k
                FT_ATOMIC_STORE_PTR_RELEASE(so_entry->key, Py_NewRef(key));
865
50.9k
            }
866
193k
        }
867
17.7k
        so->fill = other->fill;
868
17.7k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
869
17.7k
        return 0;
870
17.7k
    }
871
872
    /* If our table is empty, we can use set_insert_clean() */
873
9.56k
    if (so->fill == 0) {
874
828
        setentry *newtable = so->table;
875
828
        size_t newmask = (size_t)so->mask;
876
828
        so->fill = other->used;
877
828
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
878
33.5k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
879
32.7k
            key = other_entry->key;
880
32.7k
            if (key != NULL && key != dummy) {
881
6.92k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
882
6.92k
                                 other_entry->hash);
883
6.92k
            }
884
32.7k
        }
885
828
        return 0;
886
828
    }
887
888
    /* We can't assure there are no duplicates, so do normal insertions */
889
118k
    for (i = 0; i <= other->mask; i++) {
890
110k
        other_entry = &other->table[i];
891
110k
        key = other_entry->key;
892
110k
        if (key != NULL && key != dummy) {
893
32.5k
            if (set_add_entry(so, key, other_entry->hash))
894
0
                return -1;
895
32.5k
        }
896
110k
    }
897
8.73k
    return 0;
898
8.73k
}
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
285
{
914
    /* Make sure the search finger is in bounds */
915
285
    setentry *entry = so->table + (so->finger & so->mask);
916
285
    setentry *limit = so->table + so->mask;
917
285
    PyObject *key;
918
919
285
    if (so->used == 0) {
920
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
921
0
        return NULL;
922
0
    }
923
1.51k
    while (entry->key == NULL || entry->key==dummy) {
924
1.22k
        entry++;
925
1.22k
        if (entry > limit)
926
0
            entry = so->table;
927
1.22k
    }
928
285
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, -1);
929
285
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
930
285
    key = entry->key;
931
285
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, dummy);
932
285
    so->finger = entry - so->table + 1;   /* next place to start */
933
285
    return key;
934
285
}
935
936
static int
937
set_traverse(PyObject *self, visitproc visit, void *arg)
938
3.31M
{
939
3.31M
    PySetObject *so = _PySet_CAST(self);
940
3.31M
    Py_ssize_t pos = 0;
941
3.31M
    setentry *entry;
942
943
5.32M
    while (set_next(so, &pos, &entry))
944
2.00M
        Py_VISIT(entry->key);
945
3.31M
    return 0;
946
3.31M
}
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
15.2k
{
956
15.2k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
957
15.2k
}
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
481
{
975
481
    PySetObject *so = _PySet_CAST(self);
976
481
    Py_uhash_t hash = 0;
977
481
    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
15.4k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
990
14.9k
        hash ^= _shuffle_bits(entry->hash);
991
992
    /* Remove the effect of an odd number of NULL entries */
993
481
    if ((so->mask + 1 - so->fill) & 1)
994
243
        hash ^= _shuffle_bits(0);
995
996
    /* Remove the effect of an odd number of dummy entries */
997
481
    if ((so->fill - so->used) & 1)
998
0
        hash ^= _shuffle_bits(-1);
999
1000
    /* Factor in the number of active entries */
1001
481
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
1002
1003
    /* Disperse patterns arising in nested frozensets */
1004
481
    hash ^= (hash >> 11) ^ (hash >> 25);
1005
481
    hash = hash * 69069U + 907133923UL;
1006
1007
    /* -1 is reserved as an error code */
1008
481
    if (hash == (Py_uhash_t)-1)
1009
0
        hash = 590923713UL;
1010
1011
481
    return (Py_hash_t)hash;
1012
481
}
1013
1014
static Py_hash_t
1015
frozenset_hash(PyObject *self)
1016
759
{
1017
759
    PySetObject *so = _PySet_CAST(self);
1018
759
    Py_uhash_t hash;
1019
1020
759
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
1021
278
        return FT_ATOMIC_LOAD_SSIZE_ACQUIRE(so->hash);
1022
278
    }
1023
1024
481
    hash = frozenset_hash_impl(self);
1025
481
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->hash, hash);
1026
481
    return hash;
1027
759
}
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
306k
{
1042
306k
    setiterobject *si = (setiterobject*)self;
1043
    /* bpo-31095: UnTrack is needed before calling any callbacks */
1044
306k
    _PyObject_GC_UNTRACK(si);
1045
306k
    Py_XDECREF(si->si_set);
1046
306k
    PyObject_GC_Del(si);
1047
306k
}
1048
1049
static int
1050
setiter_traverse(PyObject *self, visitproc visit, void *arg)
1051
157
{
1052
157
    setiterobject *si = (setiterobject*)self;
1053
157
    Py_VISIT(si->si_set);
1054
157
    return 0;
1055
157
}
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
1.08M
{
1097
1.08M
    setiterobject *si = (setiterobject*)self;
1098
1.08M
    PyObject *key = NULL;
1099
1.08M
    Py_ssize_t i, mask;
1100
1.08M
    setentry *entry;
1101
1.08M
    PySetObject *so = si->si_set;
1102
1103
1.08M
    if (so == NULL)
1104
0
        return NULL;
1105
1.08M
    assert (PyAnySet_Check(so));
1106
1107
1.08M
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
1108
1.08M
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE_RELAXED(si->si_used);
1109
1.08M
    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
1.08M
    Py_BEGIN_CRITICAL_SECTION(so);
1117
1.08M
    i = si->si_pos;
1118
1.08M
    assert(i>=0);
1119
1.08M
    entry = so->table;
1120
1.08M
    mask = so->mask;
1121
4.89M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
1122
3.80M
        i++;
1123
3.80M
    }
1124
1.08M
    if (i <= mask) {
1125
782k
        key = Py_NewRef(entry[i].key);
1126
782k
    }
1127
1.08M
    Py_END_CRITICAL_SECTION();
1128
1.08M
    si->si_pos = i+1;
1129
1.08M
    if (key == NULL) {
1130
306k
        si->si_set = NULL;
1131
306k
        Py_DECREF(so);
1132
306k
        return NULL;
1133
306k
    }
1134
782k
    si->len--;
1135
782k
    return key;
1136
1.08M
}
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
306k
{
1174
306k
    Py_ssize_t size = set_len(so);
1175
306k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
1176
306k
    if (si == NULL)
1177
0
        return NULL;
1178
306k
    si->si_set = (PySetObject*)Py_NewRef(so);
1179
306k
    si->si_used = size;
1180
306k
    si->si_pos = 0;
1181
306k
    si->len = size;
1182
306k
    _PyObject_GC_TRACK(si);
1183
306k
    return (PyObject *)si;
1184
306k
}
1185
1186
static int
1187
set_update_dict_lock_held(PySetObject *so, PyObject *other)
1188
248
{
1189
248
    assert(PyAnyDict_CheckExact(other));
1190
1191
248
    _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
248
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
1203
248
    if ((so->fill + dictsize)*5 >= so->mask*3) {
1204
22
        if (set_table_resize(so, (so->used + dictsize)*2) != 0) {
1205
0
            return -1;
1206
0
        }
1207
22
    }
1208
1209
248
    Py_ssize_t pos = 0;
1210
248
    PyObject *key;
1211
248
    PyObject *value;
1212
248
    Py_hash_t hash;
1213
652
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1214
404
        if (set_add_entry(so, key, hash)) {
1215
0
            return -1;
1216
0
        }
1217
404
    }
1218
248
    return 0;
1219
248
}
1220
1221
static int
1222
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1223
17.2k
{
1224
17.2k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1225
1226
17.2k
    PyObject *it = PyObject_GetIter(other);
1227
17.2k
    if (it == NULL) {
1228
0
        return -1;
1229
0
    }
1230
1231
17.2k
    PyObject *key;
1232
92.4k
    while ((key = PyIter_Next(it)) != NULL) {
1233
75.1k
        if (set_add_key(so, key)) {
1234
0
            Py_DECREF(it);
1235
0
            Py_DECREF(key);
1236
0
            return -1;
1237
0
        }
1238
75.1k
        Py_DECREF(key);
1239
75.1k
    }
1240
17.2k
    Py_DECREF(it);
1241
17.2k
    if (PyErr_Occurred())
1242
0
        return -1;
1243
17.2k
    return 0;
1244
17.2k
}
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
46.9k
{
1262
46.9k
    assert(Py_REFCNT(so) == 1);
1263
46.9k
    if (PyAnySet_Check(other)) {
1264
29.6k
        int rv;
1265
29.6k
        Py_BEGIN_CRITICAL_SECTION(other);
1266
29.6k
        rv = set_merge_lock_held(so, other);
1267
29.6k
        Py_END_CRITICAL_SECTION();
1268
29.6k
        return rv;
1269
29.6k
    }
1270
17.2k
    else if (PyDict_CheckExact(other)) {
1271
248
        int rv;
1272
248
        Py_BEGIN_CRITICAL_SECTION(other);
1273
248
        rv = set_update_dict_lock_held(so, other);
1274
248
        Py_END_CRITICAL_SECTION();
1275
248
        return rv;
1276
248
    }
1277
17.0k
    else if (PyFrozenDict_CheckExact(other)) {
1278
0
        return set_update_dict_lock_held(so, other);
1279
0
    }
1280
17.0k
    return set_update_iterable_lock_held(so, other);
1281
46.9k
}
1282
1283
static int
1284
set_update_internal(PySetObject *so, PyObject *other)
1285
35.6k
{
1286
35.6k
    if (PyAnySet_Check(other)) {
1287
35.4k
        if (Py_Is((PyObject *)so, other)) {
1288
0
            return 0;
1289
0
        }
1290
35.4k
        int rv;
1291
35.4k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1292
35.4k
        rv = set_merge_lock_held(so, other);
1293
35.4k
        Py_END_CRITICAL_SECTION2();
1294
35.4k
        return rv;
1295
35.4k
    }
1296
200
    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
200
    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
200
    else {
1311
200
        int rv;
1312
200
        Py_BEGIN_CRITICAL_SECTION(so);
1313
200
        rv = set_update_iterable_lock_held(so, other);
1314
200
        Py_END_CRITICAL_SECTION();
1315
200
        return rv;
1316
200
    }
1317
35.6k
}
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
76
{
1332
76
    Py_ssize_t i;
1333
1334
152
    for (i = 0; i < others_length; i++) {
1335
76
        PyObject *other = others[i];
1336
76
        if (set_update_internal(so, other))
1337
0
            return NULL;
1338
76
    }
1339
76
    Py_RETURN_NONE;
1340
76
}
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
3.83M
{
1351
3.83M
    assert(PyType_Check(type));
1352
3.83M
    PySetObject *so;
1353
1354
3.83M
    so = (PySetObject *)type->tp_alloc(type, 0);
1355
3.83M
    if (so == NULL)
1356
0
        return NULL;
1357
1358
3.83M
    so->fill = 0;
1359
3.83M
    so->used = 0;
1360
3.83M
    so->mask = PySet_MINSIZE - 1;
1361
3.83M
    so->table = so->smalltable;
1362
3.83M
    so->hash = -1;
1363
3.83M
    so->finger = 0;
1364
3.83M
    so->weakreflist = NULL;
1365
1366
3.83M
    if (iterable != NULL) {
1367
46.8k
        if (set_update_local(so, iterable)) {
1368
0
            Py_DECREF(so);
1369
0
            return NULL;
1370
0
        }
1371
46.8k
    }
1372
1373
3.83M
    return (PyObject *)so;
1374
3.83M
}
1375
1376
static PyObject *
1377
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1378
2.47k
{
1379
2.47k
    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
2.47k
    return make_new_set(type, iterable);
1386
2.47k
}
1387
1388
// gh-140232: check whether a frozenset can be untracked from the GC
1389
static void
1390
_PyFrozenSet_MaybeUntrack(PyObject *op)
1391
4.65k
{
1392
4.65k
    assert(op != NULL);
1393
    // subclasses of a frozenset can generate reference cycles, so do not untrack
1394
4.65k
    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
4.65k
    Py_ssize_t pos = 0;
1399
4.65k
    setentry *entry;
1400
24.5k
    while (set_next((PySetObject *)op, &pos, &entry)) {
1401
20.9k
        if (_PyObject_GC_MAY_BE_TRACKED(entry->key)) {
1402
1.09k
            return;
1403
1.09k
        }
1404
20.9k
    }
1405
3.55k
    _PyObject_GC_UNTRACK(op);
1406
3.55k
}
1407
1408
static PyObject *
1409
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1410
711
{
1411
711
    if (type != &PyFrozenSet_Type) {
1412
0
        return make_new_set(type, iterable);
1413
0
    }
1414
1415
711
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1416
        /* frozenset(f) is idempotent */
1417
0
        return Py_NewRef(iterable);
1418
0
    }
1419
711
    PyObject *obj = make_new_set(type, iterable);
1420
711
    if (obj != NULL) {
1421
711
        _PyFrozenSet_MaybeUntrack(obj);
1422
711
    }
1423
711
    return obj;
1424
711
}
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
711
{
1448
711
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1449
0
        return NULL;
1450
0
    }
1451
1452
711
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1453
711
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1454
0
        return NULL;
1455
0
    }
1456
1457
711
    PyObject *iterable = (nargs ? args[0] : NULL);
1458
711
    return make_new_frozenset(_PyType_CAST(type), iterable);
1459
711
}
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
/*[clinic input]
1549
@critical_section
1550
set.copy
1551
    so: setobject
1552
1553
Return a shallow copy of a set.
1554
[clinic start generated code]*/
1555
1556
static PyObject *
1557
set_copy_impl(PySetObject *so)
1558
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
1559
2.22k
{
1560
2.22k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1561
2.22k
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1562
2.22k
    if (copy == NULL) {
1563
0
        return NULL;
1564
0
    }
1565
2.22k
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1566
0
        Py_DECREF(copy);
1567
0
        return NULL;
1568
0
    }
1569
2.22k
    return copy;
1570
2.22k
}
1571
1572
/*[clinic input]
1573
@critical_section
1574
frozenset.copy
1575
    so: setobject
1576
1577
Return a shallow copy of a set.
1578
[clinic start generated code]*/
1579
1580
static PyObject *
1581
frozenset_copy_impl(PySetObject *so)
1582
/*[clinic end generated code: output=b356263526af9e70 input=fbf5bef131268dd7]*/
1583
0
{
1584
0
    if (PyFrozenSet_CheckExact(so)) {
1585
0
        return Py_NewRef(so);
1586
0
    }
1587
0
    return set_copy_impl(so);
1588
0
}
1589
1590
/*[clinic input]
1591
@critical_section
1592
set.clear
1593
    so: setobject
1594
1595
Remove all elements from this set.
1596
[clinic start generated code]*/
1597
1598
static PyObject *
1599
set_clear_impl(PySetObject *so)
1600
/*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/
1601
33.3k
{
1602
33.3k
    set_clear_internal((PyObject*)so);
1603
33.3k
    Py_RETURN_NONE;
1604
33.3k
}
1605
1606
/*[clinic input]
1607
set.union
1608
    so: setobject
1609
    *others: array
1610
1611
Return a new set with elements from the set and all others.
1612
[clinic start generated code]*/
1613
1614
static PyObject *
1615
set_union_impl(PySetObject *so, PyObject * const *others,
1616
               Py_ssize_t others_length)
1617
/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
1618
4
{
1619
4
    PySetObject *result;
1620
4
    PyObject *other;
1621
4
    Py_ssize_t i;
1622
1623
4
    result = (PySetObject *)set_copy((PyObject *)so, NULL);
1624
4
    if (result == NULL)
1625
0
        return NULL;
1626
1627
8
    for (i = 0; i < others_length; i++) {
1628
4
        other = others[i];
1629
4
        if ((PyObject *)so == other)
1630
0
            continue;
1631
4
        if (set_update_local(result, other)) {
1632
0
            Py_DECREF(result);
1633
0
            return NULL;
1634
0
        }
1635
4
    }
1636
4
    return (PyObject *)result;
1637
4
}
1638
1639
static PyObject *
1640
set_or(PyObject *self, PyObject *other)
1641
84
{
1642
84
    PySetObject *result;
1643
1644
84
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1645
0
        Py_RETURN_NOTIMPLEMENTED;
1646
1647
84
    result = (PySetObject *)set_copy(self, NULL);
1648
84
    if (result == NULL) {
1649
0
        return NULL;
1650
0
    }
1651
84
    if (Py_Is(self, other)) {
1652
0
        return (PyObject *)result;
1653
0
    }
1654
84
    if (set_update_local(result, other)) {
1655
0
        Py_DECREF(result);
1656
0
        return NULL;
1657
0
    }
1658
84
    return (PyObject *)result;
1659
84
}
1660
1661
static PyObject *
1662
set_ior(PyObject *self, PyObject *other)
1663
35.3k
{
1664
35.3k
    if (!PyAnySet_Check(other))
1665
0
        Py_RETURN_NOTIMPLEMENTED;
1666
35.3k
    PySetObject *so = _PySet_CAST(self);
1667
1668
35.3k
    if (set_update_internal(so, other)) {
1669
0
        return NULL;
1670
0
    }
1671
35.3k
    return Py_NewRef(so);
1672
35.3k
}
1673
1674
static PyObject *
1675
set_intersection(PySetObject *so, PyObject *other)
1676
254
{
1677
254
    PySetObject *result;
1678
254
    PyObject *key, *it, *tmp;
1679
254
    Py_hash_t hash;
1680
254
    int rv;
1681
1682
254
    if ((PyObject *)so == other)
1683
0
        return set_copy_impl(so);
1684
1685
254
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1686
254
    if (result == NULL)
1687
0
        return NULL;
1688
1689
254
    if (PyAnySet_Check(other)) {
1690
248
        Py_ssize_t pos = 0;
1691
248
        setentry *entry;
1692
1693
248
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1694
168
            tmp = (PyObject *)so;
1695
168
            so = (PySetObject *)other;
1696
168
            other = tmp;
1697
168
        }
1698
1699
408
        while (set_next((PySetObject *)other, &pos, &entry)) {
1700
160
            key = entry->key;
1701
160
            hash = entry->hash;
1702
160
            Py_INCREF(key);
1703
160
            rv = set_contains_entry(so, key, hash);
1704
160
            if (rv < 0) {
1705
0
                Py_DECREF(result);
1706
0
                Py_DECREF(key);
1707
0
                return NULL;
1708
0
            }
1709
160
            if (rv) {
1710
0
                if (set_add_entry(result, key, hash)) {
1711
0
                    Py_DECREF(result);
1712
0
                    Py_DECREF(key);
1713
0
                    return NULL;
1714
0
                }
1715
0
            }
1716
160
            Py_DECREF(key);
1717
160
        }
1718
248
        return (PyObject *)result;
1719
248
    }
1720
1721
6
    it = PyObject_GetIter(other);
1722
6
    if (it == NULL) {
1723
0
        Py_DECREF(result);
1724
0
        return NULL;
1725
0
    }
1726
1727
62
    while ((key = PyIter_Next(it)) != NULL) {
1728
58
        hash = PyObject_Hash(key);
1729
58
        if (hash == -1)
1730
0
            goto error;
1731
58
        rv = set_contains_entry(so, key, hash);
1732
58
        if (rv < 0)
1733
0
            goto error;
1734
58
        if (rv) {
1735
58
            if (set_add_entry(result, key, hash))
1736
0
                goto error;
1737
58
            if (PySet_GET_SIZE(result) >= PySet_GET_SIZE(so)) {
1738
2
                Py_DECREF(key);
1739
2
                break;
1740
2
            }
1741
58
        }
1742
56
        Py_DECREF(key);
1743
56
    }
1744
6
    Py_DECREF(it);
1745
6
    if (PyErr_Occurred()) {
1746
0
        Py_DECREF(result);
1747
0
        return NULL;
1748
0
    }
1749
6
    return (PyObject *)result;
1750
0
  error:
1751
0
    Py_DECREF(it);
1752
0
    Py_DECREF(result);
1753
0
    Py_DECREF(key);
1754
0
    return NULL;
1755
6
}
1756
1757
/*[clinic input]
1758
set.intersection as set_intersection_multi
1759
    so: setobject
1760
    *others: array
1761
1762
Return a new set with elements common to the set and all others.
1763
[clinic start generated code]*/
1764
1765
static PyObject *
1766
set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
1767
                            Py_ssize_t others_length)
1768
/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
1769
4
{
1770
4
    Py_ssize_t i;
1771
1772
4
    if (others_length == 0) {
1773
0
        return set_copy((PyObject *)so, NULL);
1774
0
    }
1775
1776
4
    PyObject *result = Py_NewRef(so);
1777
8
    for (i = 0; i < others_length; i++) {
1778
4
        PyObject *other = others[i];
1779
4
        PyObject *newresult;
1780
4
        Py_BEGIN_CRITICAL_SECTION2(result, other);
1781
4
        newresult = set_intersection((PySetObject *)result, other);
1782
4
        Py_END_CRITICAL_SECTION2();
1783
4
        if (newresult == NULL) {
1784
0
            Py_DECREF(result);
1785
0
            return NULL;
1786
0
        }
1787
4
        Py_SETREF(result, newresult);
1788
4
    }
1789
4
    return result;
1790
4
}
1791
1792
static PyObject *
1793
set_intersection_update(PySetObject *so, PyObject *other)
1794
0
{
1795
0
    PyObject *tmp;
1796
1797
0
    tmp = set_intersection(so, other);
1798
0
    if (tmp == NULL)
1799
0
        return NULL;
1800
0
    set_swap_bodies(so, (PySetObject *)tmp);
1801
0
    Py_DECREF(tmp);
1802
0
    Py_RETURN_NONE;
1803
0
}
1804
1805
/*[clinic input]
1806
set.intersection_update as set_intersection_update_multi
1807
    so: setobject
1808
    *others: array
1809
1810
Update the set, keeping only elements found in it and all others.
1811
[clinic start generated code]*/
1812
1813
static PyObject *
1814
set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
1815
                                   Py_ssize_t others_length)
1816
/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
1817
0
{
1818
0
    PyObject *tmp;
1819
1820
0
    tmp = set_intersection_multi_impl(so, others, others_length);
1821
0
    if (tmp == NULL)
1822
0
        return NULL;
1823
0
    Py_BEGIN_CRITICAL_SECTION(so);
1824
0
    set_swap_bodies(so, (PySetObject *)tmp);
1825
0
    Py_END_CRITICAL_SECTION();
1826
0
    Py_DECREF(tmp);
1827
0
    Py_RETURN_NONE;
1828
0
}
1829
1830
static PyObject *
1831
set_and(PyObject *self, PyObject *other)
1832
248
{
1833
248
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1834
0
        Py_RETURN_NOTIMPLEMENTED;
1835
248
    PySetObject *so = _PySet_CAST(self);
1836
1837
248
    PyObject *rv;
1838
248
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1839
248
    rv = set_intersection(so, other);
1840
248
    Py_END_CRITICAL_SECTION2();
1841
1842
248
    return rv;
1843
248
}
1844
1845
static PyObject *
1846
set_iand(PyObject *self, PyObject *other)
1847
0
{
1848
0
    PyObject *result;
1849
1850
0
    if (!PyAnySet_Check(other))
1851
0
        Py_RETURN_NOTIMPLEMENTED;
1852
0
    PySetObject *so = _PySet_CAST(self);
1853
1854
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1855
0
    result = set_intersection_update(so, other);
1856
0
    Py_END_CRITICAL_SECTION2();
1857
1858
0
    if (result == NULL)
1859
0
        return NULL;
1860
0
    Py_DECREF(result);
1861
0
    return Py_NewRef(so);
1862
0
}
1863
1864
/*[clinic input]
1865
@critical_section so other
1866
set.isdisjoint
1867
    so: setobject
1868
    other: object
1869
    /
1870
1871
Return True if two sets have a null intersection.
1872
[clinic start generated code]*/
1873
1874
static PyObject *
1875
set_isdisjoint_impl(PySetObject *so, PyObject *other)
1876
/*[clinic end generated code: output=273493f2d57c565e input=32f8dcab5e0fc7d6]*/
1877
64.0k
{
1878
64.0k
    PyObject *key, *it, *tmp;
1879
64.0k
    int rv;
1880
1881
64.0k
    if ((PyObject *)so == other) {
1882
0
        if (PySet_GET_SIZE(so) == 0)
1883
0
            Py_RETURN_TRUE;
1884
0
        else
1885
0
            Py_RETURN_FALSE;
1886
0
    }
1887
1888
64.0k
    if (PyAnySet_CheckExact(other)) {
1889
18
        Py_ssize_t pos = 0;
1890
18
        setentry *entry;
1891
1892
18
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1893
2
            tmp = (PyObject *)so;
1894
2
            so = (PySetObject *)other;
1895
2
            other = tmp;
1896
2
        }
1897
18
        while (set_next((PySetObject *)other, &pos, &entry)) {
1898
0
            PyObject *key = entry->key;
1899
0
            Py_INCREF(key);
1900
0
            rv = set_contains_entry(so, key, entry->hash);
1901
0
            Py_DECREF(key);
1902
0
            if (rv < 0) {
1903
0
                return NULL;
1904
0
            }
1905
0
            if (rv) {
1906
0
                Py_RETURN_FALSE;
1907
0
            }
1908
0
        }
1909
18
        Py_RETURN_TRUE;
1910
18
    }
1911
1912
64.0k
    it = PyObject_GetIter(other);
1913
64.0k
    if (it == NULL)
1914
0
        return NULL;
1915
1916
2.92M
    while ((key = PyIter_Next(it)) != NULL) {
1917
2.87M
        rv = set_contains_key(so, key);
1918
2.87M
        Py_DECREF(key);
1919
2.87M
        if (rv < 0) {
1920
0
            Py_DECREF(it);
1921
0
            return NULL;
1922
0
        }
1923
2.87M
        if (rv) {
1924
15.5k
            Py_DECREF(it);
1925
15.5k
            Py_RETURN_FALSE;
1926
15.5k
        }
1927
2.87M
    }
1928
48.5k
    Py_DECREF(it);
1929
48.5k
    if (PyErr_Occurred())
1930
0
        return NULL;
1931
48.5k
    Py_RETURN_TRUE;
1932
48.5k
}
1933
1934
static int
1935
set_difference_update_internal(PySetObject *so, PyObject *other)
1936
44
{
1937
44
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1938
44
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1939
1940
44
    if ((PyObject *)so == other)
1941
0
        return set_clear_internal((PyObject*)so);
1942
1943
44
    if (PyAnySet_Check(other)) {
1944
44
        setentry *entry;
1945
44
        Py_ssize_t pos = 0;
1946
1947
        /* Optimization:  When the other set is more than 8 times
1948
           larger than the base set, replace the other set with
1949
           intersection of the two sets.
1950
        */
1951
44
        if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
1952
0
            other = set_intersection(so, other);
1953
0
            if (other == NULL)
1954
0
                return -1;
1955
44
        } else {
1956
44
            Py_INCREF(other);
1957
44
        }
1958
1959
70
        while (set_next((PySetObject *)other, &pos, &entry)) {
1960
26
            PyObject *key = entry->key;
1961
26
            Py_INCREF(key);
1962
26
            if (set_discard_entry(so, key, entry->hash) < 0) {
1963
0
                Py_DECREF(other);
1964
0
                Py_DECREF(key);
1965
0
                return -1;
1966
0
            }
1967
26
            Py_DECREF(key);
1968
26
        }
1969
1970
44
        Py_DECREF(other);
1971
44
    } else {
1972
0
        PyObject *key, *it;
1973
0
        it = PyObject_GetIter(other);
1974
0
        if (it == NULL)
1975
0
            return -1;
1976
1977
0
        while ((key = PyIter_Next(it)) != NULL) {
1978
0
            if (set_discard_key(so, key) < 0) {
1979
0
                Py_DECREF(it);
1980
0
                Py_DECREF(key);
1981
0
                return -1;
1982
0
            }
1983
0
            Py_DECREF(key);
1984
0
        }
1985
0
        Py_DECREF(it);
1986
0
        if (PyErr_Occurred())
1987
0
            return -1;
1988
0
    }
1989
    /* If more than 1/4th are dummies, then resize them away. */
1990
44
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1991
44
        return 0;
1992
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1993
44
}
1994
1995
/*[clinic input]
1996
set.difference_update
1997
    so: setobject
1998
    *others: array
1999
2000
Update the set, removing elements found in others.
2001
[clinic start generated code]*/
2002
2003
static PyObject *
2004
set_difference_update_impl(PySetObject *so, PyObject * const *others,
2005
                           Py_ssize_t others_length)
2006
/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
2007
0
{
2008
0
    Py_ssize_t i;
2009
2010
0
    for (i = 0; i < others_length; i++) {
2011
0
        PyObject *other = others[i];
2012
0
        int rv;
2013
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2014
0
        rv = set_difference_update_internal(so, other);
2015
0
        Py_END_CRITICAL_SECTION2();
2016
0
        if (rv) {
2017
0
            return NULL;
2018
0
        }
2019
0
    }
2020
0
    Py_RETURN_NONE;
2021
0
}
2022
2023
static PyObject *
2024
set_copy_and_difference(PySetObject *so, PyObject *other)
2025
16
{
2026
16
    PyObject *result;
2027
2028
16
    result = set_copy_impl(so);
2029
16
    if (result == NULL)
2030
0
        return NULL;
2031
16
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
2032
16
        return result;
2033
0
    Py_DECREF(result);
2034
0
    return NULL;
2035
16
}
2036
2037
static PyObject *
2038
set_difference(PySetObject *so, PyObject *other)
2039
18
{
2040
18
    PyObject *result;
2041
18
    PyObject *key;
2042
18
    Py_hash_t hash;
2043
18
    setentry *entry;
2044
18
    Py_ssize_t pos = 0, other_size;
2045
18
    int rv;
2046
2047
18
    if (PyAnySet_Check(other)) {
2048
18
        other_size = PySet_GET_SIZE(other);
2049
18
    }
2050
0
    else if (PyAnyDict_CheckExact(other)) {
2051
0
        other_size = PyDict_GET_SIZE(other);
2052
0
    }
2053
0
    else {
2054
0
        return set_copy_and_difference(so, other);
2055
0
    }
2056
2057
    /* If len(so) much more than len(other), it's more efficient to simply copy
2058
     * so and then iterate other looking for common elements. */
2059
18
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
2060
16
        return set_copy_and_difference(so, other);
2061
16
    }
2062
2063
2
    result = make_new_set_basetype(Py_TYPE(so), NULL);
2064
2
    if (result == NULL)
2065
0
        return NULL;
2066
2067
2
    if (PyAnyDict_CheckExact(other)) {
2068
0
        while (set_next(so, &pos, &entry)) {
2069
0
            key = entry->key;
2070
0
            hash = entry->hash;
2071
0
            Py_INCREF(key);
2072
0
            rv = _PyDict_Contains_KnownHash(other, key, hash);
2073
0
            if (rv < 0) {
2074
0
                Py_DECREF(result);
2075
0
                Py_DECREF(key);
2076
0
                return NULL;
2077
0
            }
2078
0
            if (!rv) {
2079
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
2080
0
                    Py_DECREF(result);
2081
0
                    Py_DECREF(key);
2082
0
                    return NULL;
2083
0
                }
2084
0
            }
2085
0
            Py_DECREF(key);
2086
0
        }
2087
0
        return result;
2088
0
    }
2089
2090
    /* Iterate over so, checking for common elements in other. */
2091
28
    while (set_next(so, &pos, &entry)) {
2092
26
        key = entry->key;
2093
26
        hash = entry->hash;
2094
26
        Py_INCREF(key);
2095
26
        rv = set_contains_entry((PySetObject *)other, key, hash);
2096
26
        if (rv < 0) {
2097
0
            Py_DECREF(result);
2098
0
            Py_DECREF(key);
2099
0
            return NULL;
2100
0
        }
2101
26
        if (!rv) {
2102
20
            if (set_add_entry((PySetObject *)result, key, hash)) {
2103
0
                Py_DECREF(result);
2104
0
                Py_DECREF(key);
2105
0
                return NULL;
2106
0
            }
2107
20
        }
2108
26
        Py_DECREF(key);
2109
26
    }
2110
2
    return result;
2111
2
}
2112
2113
/*[clinic input]
2114
set.difference as set_difference_multi
2115
    so: setobject
2116
    *others: array
2117
2118
Return a new set with elements in the set that are not in the others.
2119
[clinic start generated code]*/
2120
2121
static PyObject *
2122
set_difference_multi_impl(PySetObject *so, PyObject * const *others,
2123
                          Py_ssize_t others_length)
2124
/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
2125
0
{
2126
0
    Py_ssize_t i;
2127
0
    PyObject *result, *other;
2128
2129
0
    if (others_length == 0) {
2130
0
        return set_copy((PyObject *)so, NULL);
2131
0
    }
2132
2133
0
    other = others[0];
2134
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2135
0
    result = set_difference(so, other);
2136
0
    Py_END_CRITICAL_SECTION2();
2137
0
    if (result == NULL)
2138
0
        return NULL;
2139
2140
0
    for (i = 1; i < others_length; i++) {
2141
0
        other = others[i];
2142
0
        int rv;
2143
0
        Py_BEGIN_CRITICAL_SECTION(other);
2144
0
        rv = set_difference_update_internal((PySetObject *)result, other);
2145
0
        Py_END_CRITICAL_SECTION();
2146
0
        if (rv) {
2147
0
            Py_DECREF(result);
2148
0
            return NULL;
2149
0
        }
2150
0
    }
2151
0
    return result;
2152
0
}
2153
2154
static PyObject *
2155
set_sub(PyObject *self, PyObject *other)
2156
18
{
2157
18
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2158
0
        Py_RETURN_NOTIMPLEMENTED;
2159
18
    PySetObject *so = _PySet_CAST(self);
2160
2161
18
    PyObject *rv;
2162
18
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2163
18
    rv = set_difference(so, other);
2164
18
    Py_END_CRITICAL_SECTION2();
2165
18
    return rv;
2166
18
}
2167
2168
static PyObject *
2169
set_isub(PyObject *self, PyObject *other)
2170
28
{
2171
28
    if (!PyAnySet_Check(other))
2172
0
        Py_RETURN_NOTIMPLEMENTED;
2173
28
    PySetObject *so = _PySet_CAST(self);
2174
2175
28
    int rv;
2176
28
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2177
28
    rv = set_difference_update_internal(so, other);
2178
28
    Py_END_CRITICAL_SECTION2();
2179
28
    if (rv < 0) {
2180
0
        return NULL;
2181
0
    }
2182
28
    return Py_NewRef(so);
2183
28
}
2184
2185
static int
2186
set_symmetric_difference_update_dict(PySetObject *so, PyObject *other)
2187
0
{
2188
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
2189
#ifdef Py_DEBUG
2190
    if (!PyFrozenDict_CheckExact(other)) {
2191
        _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
2192
    }
2193
#endif
2194
2195
0
    Py_ssize_t pos = 0;
2196
0
    PyObject *key, *value;
2197
0
    Py_hash_t hash;
2198
0
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
2199
0
        Py_INCREF(key);
2200
0
        int rv = set_discard_entry(so, key, hash);
2201
0
        if (rv < 0) {
2202
0
            Py_DECREF(key);
2203
0
            return -1;
2204
0
        }
2205
0
        if (rv == DISCARD_NOTFOUND) {
2206
0
            if (set_add_entry(so, key, hash)) {
2207
0
                Py_DECREF(key);
2208
0
                return -1;
2209
0
            }
2210
0
        }
2211
0
        Py_DECREF(key);
2212
0
    }
2213
0
    return 0;
2214
0
}
2215
2216
static int
2217
set_symmetric_difference_update_set(PySetObject *so, PySetObject *other)
2218
0
{
2219
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
2220
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
2221
2222
0
    Py_ssize_t pos = 0;
2223
0
    setentry *entry;
2224
0
    while (set_next(other, &pos, &entry)) {
2225
0
        PyObject *key = Py_NewRef(entry->key);
2226
0
        Py_hash_t hash = entry->hash;
2227
0
        int rv = set_discard_entry(so, key, hash);
2228
0
        if (rv < 0) {
2229
0
            Py_DECREF(key);
2230
0
            return -1;
2231
0
        }
2232
0
        if (rv == DISCARD_NOTFOUND) {
2233
0
            if (set_add_entry(so, key, hash)) {
2234
0
                Py_DECREF(key);
2235
0
                return -1;
2236
0
            }
2237
0
        }
2238
0
        Py_DECREF(key);
2239
0
    }
2240
0
    return 0;
2241
0
}
2242
2243
/*[clinic input]
2244
@permit_long_summary
2245
set.symmetric_difference_update
2246
    so: setobject
2247
    other: object
2248
    /
2249
2250
Update the set, keeping only elements found in either set, but not in both.
2251
[clinic start generated code]*/
2252
2253
static PyObject *
2254
set_symmetric_difference_update_impl(PySetObject *so, PyObject *other)
2255
/*[clinic end generated code: output=79f80b4ee5da66c1 input=86a3dddac9bfb15e]*/
2256
0
{
2257
0
    if (Py_Is((PyObject *)so, other)) {
2258
0
        return set_clear((PyObject *)so, NULL);
2259
0
    }
2260
2261
0
    int rv;
2262
0
    if (PyDict_CheckExact(other)) {
2263
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2264
0
        rv = set_symmetric_difference_update_dict(so, other);
2265
0
        Py_END_CRITICAL_SECTION2();
2266
0
    }
2267
0
    else if (PyFrozenDict_CheckExact(other)) {
2268
0
        Py_BEGIN_CRITICAL_SECTION(so);
2269
0
        rv = set_symmetric_difference_update_dict(so, other);
2270
0
        Py_END_CRITICAL_SECTION();
2271
0
    }
2272
0
    else if (PyAnySet_Check(other)) {
2273
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2274
0
        rv = set_symmetric_difference_update_set(so, (PySetObject *)other);
2275
0
        Py_END_CRITICAL_SECTION2();
2276
0
    }
2277
0
    else {
2278
0
        PySetObject *otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
2279
0
        if (otherset == NULL) {
2280
0
            return NULL;
2281
0
        }
2282
2283
0
        Py_BEGIN_CRITICAL_SECTION(so);
2284
0
        rv = set_symmetric_difference_update_set(so, otherset);
2285
0
        Py_END_CRITICAL_SECTION();
2286
2287
0
        Py_DECREF(otherset);
2288
0
    }
2289
0
    if (rv < 0) {
2290
0
        return NULL;
2291
0
    }
2292
0
    Py_RETURN_NONE;
2293
0
}
2294
2295
/*[clinic input]
2296
@critical_section so other
2297
set.symmetric_difference
2298
    so: setobject
2299
    other: object
2300
    /
2301
2302
Return a new set with elements in either the set or other but not both.
2303
[clinic start generated code]*/
2304
2305
static PyObject *
2306
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
2307
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
2308
0
{
2309
0
    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
2310
0
    if (result == NULL) {
2311
0
        return NULL;
2312
0
    }
2313
0
    if (set_update_lock_held(result, other) < 0) {
2314
0
        Py_DECREF(result);
2315
0
        return NULL;
2316
0
    }
2317
0
    if (set_symmetric_difference_update_set(result, so) < 0) {
2318
0
        Py_DECREF(result);
2319
0
        return NULL;
2320
0
    }
2321
0
    return (PyObject *)result;
2322
0
}
2323
2324
static PyObject *
2325
set_xor(PyObject *self, PyObject *other)
2326
0
{
2327
0
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2328
0
        Py_RETURN_NOTIMPLEMENTED;
2329
0
    PySetObject *so = _PySet_CAST(self);
2330
0
    return set_symmetric_difference((PyObject*)so, other);
2331
0
}
2332
2333
static PyObject *
2334
set_ixor(PyObject *self, PyObject *other)
2335
0
{
2336
0
    PyObject *result;
2337
2338
0
    if (!PyAnySet_Check(other))
2339
0
        Py_RETURN_NOTIMPLEMENTED;
2340
0
    PySetObject *so = _PySet_CAST(self);
2341
2342
0
    result = set_symmetric_difference_update((PyObject*)so, other);
2343
0
    if (result == NULL)
2344
0
        return NULL;
2345
0
    Py_DECREF(result);
2346
0
    return Py_NewRef(so);
2347
0
}
2348
2349
/*[clinic input]
2350
@critical_section so other
2351
set.issubset
2352
    so: setobject
2353
    other: object
2354
    /
2355
2356
Report whether another set contains this set.
2357
[clinic start generated code]*/
2358
2359
static PyObject *
2360
set_issubset_impl(PySetObject *so, PyObject *other)
2361
/*[clinic end generated code: output=b2b59d5f314555ce input=f2a4fd0f2537758b]*/
2362
232
{
2363
232
    setentry *entry;
2364
232
    Py_ssize_t pos = 0;
2365
232
    int rv;
2366
2367
232
    if (!PyAnySet_Check(other)) {
2368
2
        PyObject *tmp = set_intersection(so, other);
2369
2
        if (tmp == NULL) {
2370
0
            return NULL;
2371
0
        }
2372
2
        int result = (PySet_GET_SIZE(tmp) == PySet_GET_SIZE(so));
2373
2
        Py_DECREF(tmp);
2374
2
        return PyBool_FromLong(result);
2375
2
    }
2376
230
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2377
0
        Py_RETURN_FALSE;
2378
2379
1.43k
    while (set_next(so, &pos, &entry)) {
2380
1.20k
        PyObject *key = entry->key;
2381
1.20k
        Py_INCREF(key);
2382
1.20k
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2383
1.20k
        Py_DECREF(key);
2384
1.20k
        if (rv < 0) {
2385
0
            return NULL;
2386
0
        }
2387
1.20k
        if (!rv) {
2388
0
            Py_RETURN_FALSE;
2389
0
        }
2390
1.20k
    }
2391
230
    Py_RETURN_TRUE;
2392
230
}
2393
2394
/*[clinic input]
2395
@critical_section so other
2396
set.issuperset
2397
    so: setobject
2398
    other: object
2399
    /
2400
2401
Report whether this set contains another set.
2402
[clinic start generated code]*/
2403
2404
static PyObject *
2405
set_issuperset_impl(PySetObject *so, PyObject *other)
2406
/*[clinic end generated code: output=ecf00ce552c09461 input=5f2e1f262e6e4ccc]*/
2407
6.47k
{
2408
6.47k
    if (PyAnySet_Check(other)) {
2409
0
        return set_issubset(other, (PyObject *)so);
2410
0
    }
2411
2412
6.47k
    PyObject *key, *it = PyObject_GetIter(other);
2413
6.47k
    if (it == NULL) {
2414
0
        return NULL;
2415
0
    }
2416
45.9k
    while ((key = PyIter_Next(it)) != NULL) {
2417
39.4k
        int rv = set_contains_key(so, key);
2418
39.4k
        Py_DECREF(key);
2419
39.4k
        if (rv < 0) {
2420
0
            Py_DECREF(it);
2421
0
            return NULL;
2422
0
        }
2423
39.4k
        if (!rv) {
2424
22
            Py_DECREF(it);
2425
22
            Py_RETURN_FALSE;
2426
22
        }
2427
39.4k
    }
2428
6.45k
    Py_DECREF(it);
2429
6.45k
    if (PyErr_Occurred()) {
2430
0
        return NULL;
2431
0
    }
2432
6.45k
    Py_RETURN_TRUE;
2433
6.45k
}
2434
2435
static PyObject *
2436
set_richcompare(PyObject *self, PyObject *w, int op)
2437
288
{
2438
288
    PySetObject *v = _PySet_CAST(self);
2439
288
    PyObject *r1;
2440
288
    int r2;
2441
2442
288
    if(!PyAnySet_Check(w))
2443
0
        Py_RETURN_NOTIMPLEMENTED;
2444
2445
288
    switch (op) {
2446
182
    case Py_EQ:
2447
182
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
2448
58
            Py_RETURN_FALSE;
2449
124
        Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
2450
124
        Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject *)w)->hash);
2451
124
        if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
2452
0
            Py_RETURN_FALSE;
2453
124
        return set_issubset((PyObject*)v, w);
2454
0
    case Py_NE:
2455
0
        r1 = set_richcompare((PyObject*)v, w, Py_EQ);
2456
0
        if (r1 == NULL)
2457
0
            return NULL;
2458
0
        r2 = PyObject_IsTrue(r1);
2459
0
        Py_DECREF(r1);
2460
0
        if (r2 < 0)
2461
0
            return NULL;
2462
0
        return PyBool_FromLong(!r2);
2463
106
    case Py_LE:
2464
106
        return set_issubset((PyObject*)v, w);
2465
0
    case Py_GE:
2466
0
        return set_issuperset((PyObject*)v, w);
2467
0
    case Py_LT:
2468
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
2469
0
            Py_RETURN_FALSE;
2470
0
        return set_issubset((PyObject*)v, w);
2471
0
    case Py_GT:
2472
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
2473
0
            Py_RETURN_FALSE;
2474
0
        return set_issuperset((PyObject*)v, w);
2475
288
    }
2476
288
    Py_RETURN_NOTIMPLEMENTED;
2477
288
}
2478
2479
/*[clinic input]
2480
@critical_section
2481
set.add
2482
    so: setobject
2483
    object as key: object
2484
    /
2485
2486
Add an element to a set.
2487
2488
This has no effect if the element is already present.
2489
[clinic start generated code]*/
2490
2491
static PyObject *
2492
set_add_impl(PySetObject *so, PyObject *key)
2493
/*[clinic end generated code: output=4cc4a937f1425c96 input=03baf62cb0e66514]*/
2494
6.54M
{
2495
6.54M
    if (set_add_key(so, key))
2496
0
        return NULL;
2497
6.54M
    Py_RETURN_NONE;
2498
6.54M
}
2499
2500
int
2501
_PySet_Contains(PySetObject *so, PyObject *key)
2502
271M
{
2503
271M
    assert(so);
2504
2505
271M
    Py_hash_t hash = _PyObject_HashFast(key);
2506
271M
    if (hash == -1) {
2507
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
2508
0
            set_unhashable_type(key);
2509
0
            return -1;
2510
0
        }
2511
0
        PyErr_Clear();
2512
        // Note that 'key' could be a set() or frozenset() object.  Unlike most
2513
        // container types, set allows membership testing with a set key, even
2514
        // though it is not hashable.
2515
0
        Py_BEGIN_CRITICAL_SECTION(key);
2516
0
        hash = frozenset_hash_impl(key);
2517
0
        Py_END_CRITICAL_SECTION();
2518
0
    }
2519
271M
    return set_contains_entry(so, key, hash);
2520
271M
}
2521
2522
static int
2523
set_contains(PyObject *self, PyObject *key)
2524
768
{
2525
768
    PySetObject *so = _PySet_CAST(self);
2526
768
    return _PySet_Contains(so, key);
2527
768
}
2528
2529
/*[clinic input]
2530
@coexist
2531
set.__contains__
2532
    so: setobject
2533
    object as key: object
2534
    /
2535
2536
x.__contains__(y) <==> y in x.
2537
[clinic start generated code]*/
2538
2539
static PyObject *
2540
set___contains___impl(PySetObject *so, PyObject *key)
2541
/*[clinic end generated code: output=b44863d034b3c70e input=cf4c72db704e4cf0]*/
2542
21.5M
{
2543
21.5M
    long result;
2544
2545
21.5M
    result = _PySet_Contains(so, key);
2546
21.5M
    if (result < 0)
2547
0
        return NULL;
2548
21.5M
    return PyBool_FromLong(result);
2549
21.5M
}
2550
2551
/*[clinic input]
2552
@coexist
2553
frozenset.__contains__
2554
    so: setobject
2555
    object as key: object
2556
    /
2557
2558
x.__contains__(y) <==> y in x.
2559
[clinic start generated code]*/
2560
2561
static PyObject *
2562
frozenset___contains___impl(PySetObject *so, PyObject *key)
2563
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
2564
2.94k
{
2565
2.94k
    Py_hash_t hash = _PyObject_HashFast(key);
2566
2.94k
    if (hash == -1) {
2567
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
2568
0
            set_unhashable_type(key);
2569
0
            return NULL;
2570
0
        }
2571
0
        PyErr_Clear();
2572
0
        Py_BEGIN_CRITICAL_SECTION(key);
2573
0
        hash = frozenset_hash_impl(key);
2574
0
        Py_END_CRITICAL_SECTION();
2575
0
    }
2576
2.94k
    setentry *entry; // unused
2577
2.94k
    int status = set_do_lookup(so, so->table, so->mask, key, hash, &entry,
2578
2.94k
                           set_compare_frozenset);
2579
2.94k
    if (status < 0)
2580
0
        return NULL;
2581
2.94k
    return PyBool_FromLong(status);
2582
2.94k
}
2583
2584
/*[clinic input]
2585
@critical_section
2586
set.remove
2587
    so: setobject
2588
    object as key: object
2589
    /
2590
2591
Remove an element from a set; it must be a member.
2592
2593
If the element is not a member, raise a KeyError.
2594
[clinic start generated code]*/
2595
2596
static PyObject *
2597
set_remove_impl(PySetObject *so, PyObject *key)
2598
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2599
0
{
2600
0
    int rv;
2601
2602
0
    rv = set_discard_key(so, key);
2603
0
    if (rv < 0) {
2604
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2605
0
            return NULL;
2606
0
        PyErr_Clear();
2607
0
        Py_hash_t hash;
2608
0
        Py_BEGIN_CRITICAL_SECTION(key);
2609
0
        hash = frozenset_hash_impl(key);
2610
0
        Py_END_CRITICAL_SECTION();
2611
0
        rv = set_discard_entry(so, key, hash);
2612
0
        if (rv < 0)
2613
0
            return NULL;
2614
0
    }
2615
2616
0
    if (rv == DISCARD_NOTFOUND) {
2617
0
        _PyErr_SetKeyError(key);
2618
0
        return NULL;
2619
0
    }
2620
0
    Py_RETURN_NONE;
2621
0
}
2622
2623
/*[clinic input]
2624
@critical_section
2625
set.discard
2626
    so: setobject
2627
    object as key: object
2628
    /
2629
2630
Remove an element from a set if it is a member.
2631
2632
Unlike set.remove(), the discard() method does not raise
2633
an exception when an element is missing from the set.
2634
[clinic start generated code]*/
2635
2636
static PyObject *
2637
set_discard_impl(PySetObject *so, PyObject *key)
2638
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2639
128
{
2640
128
    int rv;
2641
2642
128
    rv = set_discard_key(so, key);
2643
128
    if (rv < 0) {
2644
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2645
0
            return NULL;
2646
0
        PyErr_Clear();
2647
0
        Py_hash_t hash;
2648
0
        Py_BEGIN_CRITICAL_SECTION(key);
2649
0
        hash = frozenset_hash_impl(key);
2650
0
        Py_END_CRITICAL_SECTION();
2651
0
        rv = set_discard_entry(so, key, hash);
2652
0
        if (rv < 0)
2653
0
            return NULL;
2654
0
    }
2655
128
    Py_RETURN_NONE;
2656
128
}
2657
2658
/*[clinic input]
2659
@critical_section
2660
set.__reduce__
2661
    so: setobject
2662
2663
Return state information for pickling.
2664
[clinic start generated code]*/
2665
2666
static PyObject *
2667
set___reduce___impl(PySetObject *so)
2668
/*[clinic end generated code: output=9af7d0e029df87ee input=59405a4249e82f71]*/
2669
0
{
2670
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
2671
2672
0
    keys = PySequence_List((PyObject *)so);
2673
0
    if (keys == NULL)
2674
0
        goto done;
2675
0
    args = PyTuple_Pack(1, keys);
2676
0
    if (args == NULL)
2677
0
        goto done;
2678
0
    state = _PyObject_GetState((PyObject *)so);
2679
0
    if (state == NULL)
2680
0
        goto done;
2681
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, state);
2682
0
done:
2683
0
    Py_XDECREF(args);
2684
0
    Py_XDECREF(keys);
2685
0
    Py_XDECREF(state);
2686
0
    return result;
2687
0
}
2688
2689
/*[clinic input]
2690
@critical_section
2691
set.__sizeof__
2692
    so: setobject
2693
2694
S.__sizeof__() -> size of S in memory, in bytes.
2695
[clinic start generated code]*/
2696
2697
static PyObject *
2698
set___sizeof___impl(PySetObject *so)
2699
/*[clinic end generated code: output=4bfa3df7bd38ed88 input=09e1a09f168eaa23]*/
2700
0
{
2701
0
    size_t res = _PyObject_SIZE(Py_TYPE(so));
2702
0
    if (so->table != so->smalltable) {
2703
0
        res += ((size_t)so->mask + 1) * sizeof(setentry);
2704
0
    }
2705
0
    return PyLong_FromSize_t(res);
2706
0
}
2707
2708
static int
2709
set_init(PyObject *so, PyObject *args, PyObject *kwds)
2710
0
{
2711
0
    PySetObject *self = _PySet_CAST(so);
2712
0
    PyObject *iterable = NULL;
2713
2714
0
    if (!_PyArg_NoKeywords("set", kwds))
2715
0
        return -1;
2716
0
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
2717
0
        return -1;
2718
2719
0
    if (_PyObject_IsUniquelyReferenced((PyObject *)self) && self->fill == 0) {
2720
0
        self->hash = -1;
2721
0
        if (iterable == NULL) {
2722
0
            return 0;
2723
0
        }
2724
0
        return set_update_local(self, iterable);
2725
0
    }
2726
0
    Py_BEGIN_CRITICAL_SECTION(self);
2727
0
    if (self->fill)
2728
0
        set_clear_internal((PyObject*)self);
2729
0
    self->hash = -1;
2730
0
    Py_END_CRITICAL_SECTION();
2731
2732
0
    if (iterable == NULL)
2733
0
        return 0;
2734
0
    return set_update_internal(self, iterable);
2735
0
}
2736
2737
static PyObject*
2738
set_vectorcall(PyObject *type, PyObject * const*args,
2739
               size_t nargsf, PyObject *kwnames)
2740
3.75M
{
2741
3.75M
    assert(PyType_Check(type));
2742
2743
3.75M
    if (!_PyArg_NoKwnames("set", kwnames)) {
2744
0
        return NULL;
2745
0
    }
2746
2747
3.75M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2748
3.75M
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2749
0
        return NULL;
2750
0
    }
2751
2752
3.75M
    if (nargs) {
2753
16.2k
        return make_new_set(_PyType_CAST(type), args[0]);
2754
16.2k
    }
2755
2756
3.73M
    return make_new_set(_PyType_CAST(type), NULL);
2757
3.75M
}
2758
2759
static PySequenceMethods set_as_sequence = {
2760
    set_len,                            /* sq_length */
2761
    0,                                  /* sq_concat */
2762
    0,                                  /* sq_repeat */
2763
    0,                                  /* sq_item */
2764
    0,                                  /* sq_slice */
2765
    0,                                  /* sq_ass_item */
2766
    0,                                  /* sq_ass_slice */
2767
    set_contains,                       /* sq_contains */
2768
};
2769
2770
/* set object ********************************************************/
2771
2772
static PyMethodDef set_methods[] = {
2773
    SET_ADD_METHODDEF
2774
    SET_CLEAR_METHODDEF
2775
    SET___CONTAINS___METHODDEF
2776
    SET_COPY_METHODDEF
2777
    SET_DISCARD_METHODDEF
2778
    SET_DIFFERENCE_MULTI_METHODDEF
2779
    SET_DIFFERENCE_UPDATE_METHODDEF
2780
    SET_INTERSECTION_MULTI_METHODDEF
2781
    SET_INTERSECTION_UPDATE_MULTI_METHODDEF
2782
    SET_ISDISJOINT_METHODDEF
2783
    SET_ISSUBSET_METHODDEF
2784
    SET_ISSUPERSET_METHODDEF
2785
    SET_POP_METHODDEF
2786
    SET___REDUCE___METHODDEF
2787
    SET_REMOVE_METHODDEF
2788
    SET___SIZEOF___METHODDEF
2789
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2790
    SET_SYMMETRIC_DIFFERENCE_UPDATE_METHODDEF
2791
    SET_UNION_METHODDEF
2792
    SET_UPDATE_METHODDEF
2793
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2794
    {NULL,              NULL}   /* sentinel */
2795
};
2796
2797
static PyNumberMethods set_as_number = {
2798
    0,                                  /*nb_add*/
2799
    set_sub,                            /*nb_subtract*/
2800
    0,                                  /*nb_multiply*/
2801
    0,                                  /*nb_remainder*/
2802
    0,                                  /*nb_divmod*/
2803
    0,                                  /*nb_power*/
2804
    0,                                  /*nb_negative*/
2805
    0,                                  /*nb_positive*/
2806
    0,                                  /*nb_absolute*/
2807
    0,                                  /*nb_bool*/
2808
    0,                                  /*nb_invert*/
2809
    0,                                  /*nb_lshift*/
2810
    0,                                  /*nb_rshift*/
2811
    set_and,                            /*nb_and*/
2812
    set_xor,                            /*nb_xor*/
2813
    set_or,                             /*nb_or*/
2814
    0,                                  /*nb_int*/
2815
    0,                                  /*nb_reserved*/
2816
    0,                                  /*nb_float*/
2817
    0,                                  /*nb_inplace_add*/
2818
    set_isub,                           /*nb_inplace_subtract*/
2819
    0,                                  /*nb_inplace_multiply*/
2820
    0,                                  /*nb_inplace_remainder*/
2821
    0,                                  /*nb_inplace_power*/
2822
    0,                                  /*nb_inplace_lshift*/
2823
    0,                                  /*nb_inplace_rshift*/
2824
    set_iand,                           /*nb_inplace_and*/
2825
    set_ixor,                           /*nb_inplace_xor*/
2826
    set_ior,                            /*nb_inplace_or*/
2827
};
2828
2829
PyDoc_STRVAR(set_doc,
2830
"set(iterable=(), /)\n\
2831
--\n\
2832
\n\
2833
Build an unordered collection of unique elements.");
2834
2835
PyTypeObject PySet_Type = {
2836
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2837
    "set",                              /* tp_name */
2838
    sizeof(PySetObject),                /* tp_basicsize */
2839
    0,                                  /* tp_itemsize */
2840
    /* methods */
2841
    set_dealloc,                        /* tp_dealloc */
2842
    0,                                  /* tp_vectorcall_offset */
2843
    0,                                  /* tp_getattr */
2844
    0,                                  /* tp_setattr */
2845
    0,                                  /* tp_as_async */
2846
    set_repr,                           /* tp_repr */
2847
    &set_as_number,                     /* tp_as_number */
2848
    &set_as_sequence,                   /* tp_as_sequence */
2849
    0,                                  /* tp_as_mapping */
2850
    PyObject_HashNotImplemented,        /* tp_hash */
2851
    0,                                  /* tp_call */
2852
    0,                                  /* tp_str */
2853
    PyObject_GenericGetAttr,            /* tp_getattro */
2854
    0,                                  /* tp_setattro */
2855
    0,                                  /* tp_as_buffer */
2856
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2857
        Py_TPFLAGS_BASETYPE |
2858
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2859
    set_doc,                            /* tp_doc */
2860
    set_traverse,                       /* tp_traverse */
2861
    set_clear_internal,                 /* tp_clear */
2862
    set_richcompare,                    /* tp_richcompare */
2863
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2864
    set_iter,                           /* tp_iter */
2865
    0,                                  /* tp_iternext */
2866
    set_methods,                        /* tp_methods */
2867
    0,                                  /* tp_members */
2868
    0,                                  /* tp_getset */
2869
    0,                                  /* tp_base */
2870
    0,                                  /* tp_dict */
2871
    0,                                  /* tp_descr_get */
2872
    0,                                  /* tp_descr_set */
2873
    0,                                  /* tp_dictoffset */
2874
    set_init,                           /* tp_init */
2875
    PyType_GenericAlloc,                /* tp_alloc */
2876
    set_new,                            /* tp_new */
2877
    PyObject_GC_Del,                    /* tp_free */
2878
    .tp_vectorcall = set_vectorcall,
2879
    .tp_version_tag = _Py_TYPE_VERSION_SET,
2880
};
2881
2882
/* frozenset object ********************************************************/
2883
2884
2885
static PyMethodDef frozenset_methods[] = {
2886
    FROZENSET___CONTAINS___METHODDEF
2887
    FROZENSET_COPY_METHODDEF
2888
    SET_DIFFERENCE_MULTI_METHODDEF
2889
    SET_INTERSECTION_MULTI_METHODDEF
2890
    SET_ISDISJOINT_METHODDEF
2891
    SET_ISSUBSET_METHODDEF
2892
    SET_ISSUPERSET_METHODDEF
2893
    SET___REDUCE___METHODDEF
2894
    SET___SIZEOF___METHODDEF
2895
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2896
    SET_UNION_METHODDEF
2897
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2898
    {NULL,              NULL}   /* sentinel */
2899
};
2900
2901
static PyNumberMethods frozenset_as_number = {
2902
    0,                                  /*nb_add*/
2903
    set_sub,                            /*nb_subtract*/
2904
    0,                                  /*nb_multiply*/
2905
    0,                                  /*nb_remainder*/
2906
    0,                                  /*nb_divmod*/
2907
    0,                                  /*nb_power*/
2908
    0,                                  /*nb_negative*/
2909
    0,                                  /*nb_positive*/
2910
    0,                                  /*nb_absolute*/
2911
    0,                                  /*nb_bool*/
2912
    0,                                  /*nb_invert*/
2913
    0,                                  /*nb_lshift*/
2914
    0,                                  /*nb_rshift*/
2915
    set_and,                            /*nb_and*/
2916
    set_xor,                            /*nb_xor*/
2917
    set_or,                             /*nb_or*/
2918
};
2919
2920
PyDoc_STRVAR(frozenset_doc,
2921
"frozenset(iterable=(), /)\n\
2922
--\n\
2923
\n\
2924
Build an immutable unordered collection of unique elements.");
2925
2926
PyTypeObject PyFrozenSet_Type = {
2927
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2928
    "frozenset",                        /* tp_name */
2929
    sizeof(PySetObject),                /* tp_basicsize */
2930
    0,                                  /* tp_itemsize */
2931
    /* methods */
2932
    set_dealloc,                        /* tp_dealloc */
2933
    0,                                  /* tp_vectorcall_offset */
2934
    0,                                  /* tp_getattr */
2935
    0,                                  /* tp_setattr */
2936
    0,                                  /* tp_as_async */
2937
    set_repr,                           /* tp_repr */
2938
    &frozenset_as_number,               /* tp_as_number */
2939
    &set_as_sequence,                   /* tp_as_sequence */
2940
    0,                                  /* tp_as_mapping */
2941
    frozenset_hash,                     /* tp_hash */
2942
    0,                                  /* tp_call */
2943
    0,                                  /* tp_str */
2944
    PyObject_GenericGetAttr,            /* tp_getattro */
2945
    0,                                  /* tp_setattro */
2946
    0,                                  /* tp_as_buffer */
2947
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2948
        Py_TPFLAGS_BASETYPE |
2949
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2950
    frozenset_doc,                      /* tp_doc */
2951
    set_traverse,                       /* tp_traverse */
2952
    set_clear_internal,                 /* tp_clear */
2953
    set_richcompare,                    /* tp_richcompare */
2954
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2955
    set_iter,                           /* tp_iter */
2956
    0,                                  /* tp_iternext */
2957
    frozenset_methods,                  /* tp_methods */
2958
    0,                                  /* tp_members */
2959
    0,                                  /* tp_getset */
2960
    0,                                  /* tp_base */
2961
    0,                                  /* tp_dict */
2962
    0,                                  /* tp_descr_get */
2963
    0,                                  /* tp_descr_set */
2964
    0,                                  /* tp_dictoffset */
2965
    0,                                  /* tp_init */
2966
    PyType_GenericAlloc,                /* tp_alloc */
2967
    frozenset_new,                      /* tp_new */
2968
    PyObject_GC_Del,                    /* tp_free */
2969
    .tp_vectorcall = frozenset_vectorcall,
2970
    .tp_version_tag = _Py_TYPE_VERSION_FROZEN_SET,
2971
};
2972
2973
2974
/***** C API functions *************************************************/
2975
2976
PyObject *
2977
PySet_New(PyObject *iterable)
2978
72.5k
{
2979
72.5k
    return make_new_set(&PySet_Type, iterable);
2980
72.5k
}
2981
2982
PyObject *
2983
PyFrozenSet_New(PyObject *iterable)
2984
3.93k
{
2985
3.93k
    PyObject *result = make_new_set(&PyFrozenSet_Type, iterable);
2986
3.93k
    if (result != NULL) {
2987
3.93k
        _PyFrozenSet_MaybeUntrack(result);
2988
3.93k
    }
2989
3.93k
    return result;
2990
3.93k
}
2991
2992
Py_ssize_t
2993
PySet_Size(PyObject *anyset)
2994
217
{
2995
217
    if (!PyAnySet_Check(anyset)) {
2996
0
        PyErr_BadInternalCall();
2997
0
        return -1;
2998
0
    }
2999
217
    return set_len(anyset);
3000
217
}
3001
3002
int
3003
PySet_Clear(PyObject *set)
3004
457
{
3005
457
    if (!PySet_Check(set)) {
3006
0
        PyErr_BadInternalCall();
3007
0
        return -1;
3008
0
    }
3009
457
    (void)set_clear(set, NULL);
3010
457
    return 0;
3011
457
}
3012
3013
void
3014
_PySet_ClearInternal(PySetObject *so)
3015
0
{
3016
0
    (void)set_clear_internal((PyObject*)so);
3017
0
}
3018
3019
int
3020
PySet_Contains(PyObject *anyset, PyObject *key)
3021
100k
{
3022
100k
    if (!PyAnySet_Check(anyset)) {
3023
0
        PyErr_BadInternalCall();
3024
0
        return -1;
3025
0
    }
3026
100k
    if (PyFrozenSet_CheckExact(anyset)) {
3027
0
        return set_contains_key((PySetObject *)anyset, key);
3028
0
    }
3029
100k
    int rv;
3030
100k
    Py_BEGIN_CRITICAL_SECTION(anyset);
3031
100k
    rv = set_contains_key((PySetObject *)anyset, key);
3032
100k
    Py_END_CRITICAL_SECTION();
3033
100k
    return rv;
3034
100k
}
3035
3036
int
3037
PySet_Discard(PyObject *set, PyObject *key)
3038
41.0k
{
3039
41.0k
    if (!PySet_Check(set)) {
3040
0
        PyErr_BadInternalCall();
3041
0
        return -1;
3042
0
    }
3043
3044
41.0k
    int rv;
3045
41.0k
    Py_BEGIN_CRITICAL_SECTION(set);
3046
41.0k
    rv = set_discard_key((PySetObject *)set, key);
3047
41.0k
    Py_END_CRITICAL_SECTION();
3048
41.0k
    return rv;
3049
41.0k
}
3050
3051
int
3052
PySet_Add(PyObject *anyset, PyObject *key)
3053
33.0k
{
3054
33.0k
    if (PySet_Check(anyset)) {
3055
29.2k
        int rv;
3056
29.2k
        Py_BEGIN_CRITICAL_SECTION(anyset);
3057
29.2k
        rv = set_add_key((PySetObject *)anyset, key);
3058
29.2k
        Py_END_CRITICAL_SECTION();
3059
29.2k
        return rv;
3060
29.2k
    }
3061
3062
3.79k
    if (PyFrozenSet_Check(anyset) && _PyObject_IsUniquelyReferenced(anyset)) {
3063
        // We can only change frozensets if they are uniquely referenced. The
3064
        // API limits the usage of `PySet_Add` to "fill in the values of brand
3065
        // new frozensets before they are exposed to other code". In this case,
3066
        // this can be done without a lock.
3067
        // Since another key is added to the set, we must track the frozenset
3068
        // if needed.
3069
3.79k
        if (PyFrozenSet_CheckExact(anyset) && !PyObject_GC_IsTracked(anyset) && PyObject_GC_IsTracked(key)) {
3070
8
            _PyObject_GC_TRACK(anyset);
3071
8
        }
3072
3.79k
        return set_add_key((PySetObject *)anyset, key);
3073
3.79k
    }
3074
3075
0
    PyErr_BadInternalCall();
3076
0
    return -1;
3077
3.79k
}
3078
3079
int
3080
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
3081
3.03k
{
3082
3.03k
    setentry *entry;
3083
3084
3.03k
    if (!PyAnySet_Check(set)) {
3085
0
        PyErr_BadInternalCall();
3086
0
        return -1;
3087
0
    }
3088
3.03k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
3089
667
        return 0;
3090
2.37k
    *key = entry->key;
3091
2.37k
    *hash = entry->hash;
3092
2.37k
    return 1;
3093
3.03k
}
3094
3095
int
3096
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
3097
109k
{
3098
109k
    setentry *entry;
3099
3100
109k
    if (!PyAnySet_Check(set)) {
3101
0
        PyErr_BadInternalCall();
3102
0
        return -1;
3103
0
    }
3104
109k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
3105
109k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
3106
18.1k
        return 0;
3107
91.6k
    *key = Py_NewRef(entry->key);
3108
91.6k
    *hash = entry->hash;
3109
91.6k
    return 1;
3110
109k
}
3111
3112
PyObject *
3113
PySet_Pop(PyObject *set)
3114
5
{
3115
5
    if (!PySet_Check(set)) {
3116
0
        PyErr_BadInternalCall();
3117
0
        return NULL;
3118
0
    }
3119
5
    return set_pop(set, NULL);
3120
5
}
3121
3122
int
3123
_PySet_Update(PyObject *set, PyObject *iterable)
3124
215
{
3125
215
    if (!PySet_Check(set)) {
3126
0
        PyErr_BadInternalCall();
3127
0
        return -1;
3128
0
    }
3129
215
    return set_update_internal((PySetObject *)set, iterable);
3130
215
}
3131
3132
/* Exported for the gdb plugin's benefit. */
3133
PyObject *_PySet_Dummy = dummy;
3134
3135
/***** Dummy Struct  *************************************************/
3136
3137
static PyObject *
3138
dummy_repr(PyObject *op)
3139
0
{
3140
0
    return PyUnicode_FromString("<dummy key>");
3141
0
}
3142
3143
static void _Py_NO_RETURN
3144
dummy_dealloc(PyObject* ignore)
3145
0
{
3146
0
    Py_FatalError("deallocating <dummy key>");
3147
0
}
3148
3149
static PyTypeObject _PySetDummy_Type = {
3150
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3151
    "<dummy key> type",
3152
    0,
3153
    0,
3154
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
3155
    0,                  /*tp_vectorcall_offset*/
3156
    0,                  /*tp_getattr*/
3157
    0,                  /*tp_setattr*/
3158
    0,                  /*tp_as_async*/
3159
    dummy_repr,         /*tp_repr*/
3160
    0,                  /*tp_as_number*/
3161
    0,                  /*tp_as_sequence*/
3162
    0,                  /*tp_as_mapping*/
3163
    0,                  /*tp_hash */
3164
    0,                  /*tp_call */
3165
    0,                  /*tp_str */
3166
    0,                  /*tp_getattro */
3167
    0,                  /*tp_setattro */
3168
    0,                  /*tp_as_buffer */
3169
    Py_TPFLAGS_DEFAULT, /*tp_flags */
3170
};
3171
3172
static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type);