Coverage Report

Created: 2026-01-17 06:16

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.45M
#define dummy (&_dummy_struct)
65
66
97.8M
#define SET_LOOKKEY_FOUND 1
67
480M
#define SET_LOOKKEY_NO_MATCH 0
68
0
#define SET_LOOKKEY_ERROR (-1)
69
82.7M
#define SET_LOOKKEY_CHANGED (-2)
70
384M
#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
34.5k
#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
99.8M
{
141
99.8M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
142
99.8M
    if (entry->hash == 0 && entry->key == NULL)
143
39.3M
        return SET_LOOKKEY_EMPTY;
144
60.5M
    if (entry->hash == hash) {
145
43.4M
        PyObject *startkey = entry->key;
146
43.4M
        assert(startkey != dummy);
147
43.4M
        if (startkey == key)
148
43.4M
            return SET_LOOKKEY_FOUND;
149
20.1k
        if (PyUnicode_CheckExact(startkey)
150
20.1k
            && PyUnicode_CheckExact(key)
151
6.00k
            && unicode_eq(startkey, key))
152
6.00k
            return SET_LOOKKEY_FOUND;
153
14.1k
        table = so->table;
154
14.1k
        Py_INCREF(startkey);
155
14.1k
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
156
14.1k
        Py_DECREF(startkey);
157
14.1k
        if (cmp < 0)
158
0
            return SET_LOOKKEY_ERROR;
159
14.1k
        if (table != so->table || entry->key != startkey)
160
0
            return SET_LOOKKEY_CHANGED;
161
14.1k
        if (cmp > 0)
162
14.1k
            return SET_LOOKKEY_FOUND;
163
14.1k
    }
164
17.1M
    return SET_LOOKKEY_NO_MATCH;
165
60.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
189M
{
175
189M
    assert(PyFrozenSet_Check(so));
176
189M
    PyObject *startkey = ep->key;
177
189M
    if (startkey == NULL) {
178
104M
        return SET_LOOKKEY_EMPTY;
179
104M
    }
180
84.9M
    if (startkey == key) {
181
54.3M
        return SET_LOOKKEY_FOUND;
182
54.3M
    }
183
30.6M
    Py_ssize_t ep_hash = ep->hash;
184
30.6M
    if (ep_hash == hash) {
185
447
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
186
447
        if (cmp < 0) {
187
0
            return SET_LOOKKEY_ERROR;
188
0
        }
189
447
        assert(cmp == SET_LOOKKEY_FOUND || cmp == SET_LOOKKEY_NO_MATCH);
190
447
        return cmp;
191
447
    }
192
30.6M
    return SET_LOOKKEY_NO_MATCH;
193
30.6M
}
194
195
static void
196
set_zero_table(setentry *table, size_t size)
197
43.9k
{
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
43.9k
    memset(table, 0, sizeof(setentry)*size);
206
43.9k
#endif
207
43.9k
}
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
365M
#define LINEAR_PROBES 9
215
#endif
216
217
/* This must be >= 1 */
218
13.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
241M
{
224
241M
    setentry *entry;
225
241M
    size_t perturb = hash;
226
241M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
227
241M
    int probes;
228
241M
    int status;
229
230
255M
    while (1) {
231
255M
        entry = &table[i];
232
255M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
233
289M
        do {
234
289M
            status = compare_entry(so, table, entry, key, hash);
235
289M
            if (status != SET_LOOKKEY_NO_MATCH) {
236
241M
                if (status == SET_LOOKKEY_EMPTY) {
237
143M
                    return SET_LOOKKEY_NO_MATCH;
238
143M
                }
239
97.8M
                *epp = entry;
240
97.8M
                return status;
241
241M
            }
242
47.7M
            entry++;
243
47.7M
        } while (probes--);
244
13.7M
        perturb >>= PERTURB_SHIFT;
245
13.7M
        i = (i * 5 + 1 + perturb) & mask;
246
13.7M
    }
247
241M
    Py_UNREACHABLE();
248
241M
}
249
250
static int set_table_resize(PySetObject *, Py_ssize_t);
251
252
static int
253
set_add_entry_takeref(PySetObject *so, PyObject *key, Py_hash_t hash)
254
7.40M
{
255
7.40M
    setentry *table;
256
7.40M
    setentry *freeslot;
257
7.40M
    setentry *entry;
258
7.40M
    size_t perturb;
259
7.40M
    size_t mask;
260
7.40M
    size_t i;                       /* Unsigned for defined overflow behavior */
261
7.40M
    int probes;
262
7.40M
    int cmp;
263
264
7.40M
  restart:
265
266
7.40M
    mask = so->mask;
267
7.40M
    i = (size_t)hash & mask;
268
7.40M
    freeslot = NULL;
269
7.40M
    perturb = hash;
270
271
7.63M
    while (1) {
272
7.63M
        entry = &so->table[i];
273
7.63M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
274
10.1M
        do {
275
10.1M
            if (entry->hash == 0 && entry->key == NULL)
276
2.80M
                goto found_unused_or_dummy;
277
7.36M
            if (entry->hash == hash) {
278
4.59M
                PyObject *startkey = entry->key;
279
4.59M
                assert(startkey != dummy);
280
4.59M
                if (startkey == key)
281
48.2k
                    goto found_active;
282
4.55M
                if (PyUnicode_CheckExact(startkey)
283
4.55M
                    && PyUnicode_CheckExact(key)
284
434k
                    && unicode_eq(startkey, key))
285
434k
                    goto found_active;
286
4.11M
                table = so->table;
287
4.11M
                Py_INCREF(startkey);
288
4.11M
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
289
4.11M
                Py_DECREF(startkey);
290
4.11M
                if (cmp > 0)
291
4.11M
                    goto found_active;
292
199
                if (cmp < 0)
293
0
                    goto comparison_error;
294
199
                if (table != so->table || entry->key != startkey)
295
0
                    goto restart;
296
199
                mask = so->mask;
297
199
            }
298
2.76M
            else if (entry->hash == -1) {
299
0
                assert (entry->key == dummy);
300
0
                freeslot = entry;
301
0
            }
302
2.76M
            entry++;
303
2.76M
        } while (probes--);
304
231k
        perturb >>= PERTURB_SHIFT;
305
231k
        i = (i * 5 + 1 + perturb) & mask;
306
231k
    }
307
308
2.80M
  found_unused_or_dummy:
309
2.80M
    if (freeslot == NULL)
310
2.80M
        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
2.80M
  found_unused:
320
2.80M
    so->fill++;
321
2.80M
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
322
2.80M
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, hash);
323
2.80M
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, key);
324
2.80M
    if ((size_t)so->fill*5 < mask*3)
325
2.77M
        return 0;
326
28.0k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
327
328
4.59M
  found_active:
329
4.59M
    Py_DECREF(key);
330
4.59M
    return 0;
331
332
0
  comparison_error:
333
0
    Py_DECREF(key);
334
0
    return -1;
335
2.80M
}
336
337
static int
338
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
339
7.39M
{
340
7.39M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
341
342
7.39M
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
343
7.39M
}
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
3.62k
{
364
3.62k
    Py_hash_t hash = _PyObject_HashFast(key);
365
3.62k
    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
3.62k
    return set_add_entry_takeref(so, key, hash);
373
3.62k
}
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.53M
{
386
1.53M
    setentry *entry;
387
1.53M
    size_t perturb = hash;
388
1.53M
    size_t i = (size_t)hash & mask;
389
1.53M
    size_t j;
390
391
1.54M
    while (1) {
392
1.54M
        entry = &table[i];
393
1.54M
        if (entry->key == NULL)
394
1.42M
            goto found_null;
395
114k
        if (i + LINEAR_PROBES <= mask) {
396
127k
            for (j = 0; j < LINEAR_PROBES; j++) {
397
127k
                entry++;
398
127k
                if (entry->key == NULL)
399
109k
                    goto found_null;
400
127k
            }
401
109k
        }
402
4.27k
        perturb >>= PERTURB_SHIFT;
403
4.27k
        i = (i * 5 + 1 + perturb) & mask;
404
4.27k
    }
405
1.53M
  found_null:
406
1.53M
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, hash);
407
1.53M
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, key);
408
1.53M
}
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
241M
{
416
241M
    int status;
417
241M
    if (PyFrozenSet_CheckExact(so)) {
418
158M
        status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
419
158M
                               set_compare_frozenset);
420
158M
    }
421
82.7M
    else {
422
82.7M
        Py_BEGIN_CRITICAL_SECTION(so);
423
82.7M
        do {
424
82.7M
            status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
425
82.7M
                                   set_compare_entry_lock_held);
426
82.7M
        } while (status == SET_LOOKKEY_CHANGED);
427
82.7M
        Py_END_CRITICAL_SECTION();
428
82.7M
    }
429
241M
    assert(status == SET_LOOKKEY_FOUND ||
430
241M
           status == SET_LOOKKEY_NO_MATCH ||
431
241M
           status == SET_LOOKKEY_ERROR);
432
241M
    return status;
433
241M
}
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
34.5k
{
469
#ifdef Py_GIL_DISABLED
470
    if (use_qsbr) {
471
        _PyMem_FreeDelayed(entries, size * sizeof(setentry));
472
        return;
473
    }
474
#endif
475
34.5k
    PyMem_Free(entries);
476
34.5k
}
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.3k
{
486
35.3k
    setentry *oldtable, *newtable, *entry;
487
35.3k
    Py_ssize_t oldmask = so->mask;
488
35.3k
    Py_ssize_t oldsize = (size_t)oldmask + 1;
489
35.3k
    size_t newmask;
490
35.3k
    int is_oldtable_malloced;
491
35.3k
    setentry small_copy[PySet_MINSIZE];
492
493
35.3k
    assert(minused >= 0);
494
495
    /* Find the smallest table size > minused. */
496
    /* XXX speed-up with intrinsics */
497
35.3k
    size_t newsize = PySet_MINSIZE;
498
134k
    while (newsize <= (size_t)minused) {
499
98.9k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
500
98.9k
    }
501
502
    /* Get space for a new table. */
503
35.3k
    oldtable = so->table;
504
35.3k
    assert(oldtable != NULL);
505
35.3k
    is_oldtable_malloced = oldtable != so->smalltable;
506
507
35.3k
    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.3k
    else {
527
35.3k
        newtable = PyMem_NEW(setentry, newsize);
528
35.3k
        if (newtable == NULL) {
529
0
            PyErr_NoMemory();
530
0
            return -1;
531
0
        }
532
35.3k
    }
533
534
    /* Make the set empty, using the new table. */
535
35.3k
    assert(newtable != oldtable);
536
35.3k
    set_zero_table(newtable, newsize);
537
35.3k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, NULL);
538
35.3k
    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.3k
    newmask = (size_t)so->mask;
543
35.3k
    if (so->fill == so->used) {
544
2.62M
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
545
2.58M
            if (entry->key != NULL) {
546
1.52M
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
547
1.52M
            }
548
2.58M
        }
549
35.3k
    } 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.3k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, newtable);
559
560
35.3k
    if (is_oldtable_malloced)
561
11.0k
        free_entries(oldtable, oldsize, SET_IS_SHARED(so));
562
35.3k
    return 0;
563
35.3k
}
564
565
static int
566
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
567
241M
{
568
#ifdef Py_GIL_DISABLED
569
    return set_lookkey_threadsafe(so, key, hash);
570
#else
571
241M
    setentry *entry; // unused
572
241M
    return set_lookkey(so, key, hash, &entry);
573
241M
#endif
574
241M
}
575
576
85.1k
#define DISCARD_NOTFOUND 0
577
1.61k
#define DISCARD_FOUND 1
578
579
static int
580
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
581
86.7k
{
582
86.7k
    setentry *entry;
583
86.7k
    PyObject *old_key;
584
86.7k
    int status = set_lookkey(so, key, hash, &entry);
585
86.7k
    if (status < 0) {
586
0
        return -1;
587
0
    }
588
86.7k
    if (status == SET_LOOKKEY_NO_MATCH) {
589
85.1k
        return DISCARD_NOTFOUND;
590
85.1k
    }
591
86.7k
    assert(status == SET_LOOKKEY_FOUND);
592
1.61k
    old_key = entry->key;
593
1.61k
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, -1);
594
1.61k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
595
1.61k
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, dummy);
596
1.61k
    Py_DECREF(old_key);
597
1.61k
    return DISCARD_FOUND;
598
86.7k
}
599
600
static int
601
set_add_key(PySetObject *so, PyObject *key)
602
7.35M
{
603
7.35M
    Py_hash_t hash = _PyObject_HashFast(key);
604
7.35M
    if (hash == -1) {
605
0
        set_unhashable_type(key);
606
0
        return -1;
607
0
    }
608
7.35M
    return set_add_entry(so, key, hash);
609
7.35M
}
610
611
static int
612
set_contains_key(PySetObject *so, PyObject *key)
613
4.47M
{
614
4.47M
    Py_hash_t hash = _PyObject_HashFast(key);
615
4.47M
    if (hash == -1) {
616
0
        set_unhashable_type(key);
617
0
        return -1;
618
0
    }
619
4.47M
    return set_contains_entry(so, key, hash);
620
4.47M
}
621
622
static int
623
set_discard_key(PySetObject *so, PyObject *key)
624
86.7k
{
625
86.7k
    Py_hash_t hash = _PyObject_HashFast(key);
626
86.7k
    if (hash == -1) {
627
0
        set_unhashable_type(key);
628
0
        return -1;
629
0
    }
630
86.7k
    return set_discard_entry(so, key, hash);
631
86.7k
}
632
633
static void
634
set_empty_to_minsize(PySetObject *so)
635
8.55k
{
636
8.55k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, NULL);
637
8.55k
    set_zero_table(so->smalltable, PySet_MINSIZE);
638
8.55k
    so->fill = 0;
639
8.55k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
640
8.55k
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->mask, PySet_MINSIZE - 1);
641
8.55k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
642
8.55k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, so->smalltable);
643
8.55k
}
644
645
static int
646
set_clear_internal(PyObject *self)
647
32.3k
{
648
32.3k
    PySetObject *so = _PySet_CAST(self);
649
32.3k
    setentry *entry;
650
32.3k
    setentry *table = so->table;
651
32.3k
    Py_ssize_t fill = so->fill;
652
32.3k
    Py_ssize_t used = so->used;
653
32.3k
    Py_ssize_t oldsize = (size_t)so->mask + 1;
654
32.3k
    int table_is_malloced = table != so->smalltable;
655
32.3k
    setentry small_copy[PySet_MINSIZE];
656
657
32.3k
    assert (PyAnySet_Check(so));
658
32.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
32.3k
    if (table_is_malloced)
667
4.90k
        set_empty_to_minsize(so);
668
669
27.4k
    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
3.65k
        memcpy(small_copy, table, sizeof(small_copy));
675
3.65k
        table = small_copy;
676
3.65k
        set_empty_to_minsize(so);
677
3.65k
    }
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.08M
    for (entry = table; used > 0; entry++) {
685
2.05M
        if (entry->key && entry->key != dummy) {
686
577k
            used--;
687
577k
            Py_DECREF(entry->key);
688
577k
        }
689
2.05M
    }
690
691
32.3k
    if (table_is_malloced)
692
4.90k
        free_entries(table, oldsize, SET_IS_SHARED(so));
693
32.3k
    return 0;
694
32.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.60M
{
712
5.60M
    Py_ssize_t i;
713
5.60M
    Py_ssize_t mask;
714
5.60M
    setentry *entry;
715
716
5.60M
    assert (PyAnySet_Check(so));
717
5.60M
    i = *pos_ptr;
718
5.60M
    assert(i >= 0);
719
5.60M
    mask = so->mask;
720
5.60M
    entry = &so->table[i];
721
32.4M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
722
26.8M
        i++;
723
26.8M
        entry++;
724
26.8M
    }
725
5.60M
    *pos_ptr = i+1;
726
5.60M
    if (i > mask)
727
2.78M
        return 0;
728
5.60M
    assert(entry != NULL);
729
2.82M
    *entry_ptr = entry;
730
2.82M
    return 1;
731
5.60M
}
732
733
static void
734
set_dealloc(PyObject *self)
735
3.29M
{
736
3.29M
    PySetObject *so = _PySet_CAST(self);
737
3.29M
    setentry *entry;
738
3.29M
    Py_ssize_t used = so->used;
739
3.29M
    Py_ssize_t oldsize = (size_t)so->mask + 1;
740
741
    /* bpo-31095: UnTrack is needed before calling any callbacks */
742
3.29M
    PyObject_GC_UnTrack(so);
743
3.29M
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
744
745
10.7M
    for (entry = so->table; used > 0; entry++) {
746
7.47M
        if (entry->key && entry->key != dummy) {
747
2.28M
                used--;
748
2.28M
                Py_DECREF(entry->key);
749
2.28M
        }
750
7.47M
    }
751
3.29M
    if (so->table != so->smalltable)
752
18.5k
        free_entries(so->table, oldsize, SET_IS_SHARED(so));
753
3.29M
    Py_TYPE(so)->tp_free(so);
754
3.29M
}
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
327k
{
824
327k
    PySetObject *so = _PySet_CAST(self);
825
327k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
826
327k
}
827
828
static int
829
set_merge_lock_held(PySetObject *so, PyObject *otherset)
830
127k
{
831
127k
    PySetObject *other;
832
127k
    PyObject *key;
833
127k
    Py_ssize_t i;
834
127k
    setentry *so_entry;
835
127k
    setentry *other_entry;
836
837
127k
    assert (PyAnySet_Check(so));
838
127k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
839
127k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
840
841
127k
    other = _PySet_CAST(otherset);
842
127k
    if (other == so || other->used == 0)
843
        /* a.update(a) or a.update(set()); nothing to do */
844
73.5k
        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
54.2k
    if ((so->fill + other->used)*5 >= so->mask*3) {
850
7.28k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
851
0
            return -1;
852
7.28k
    }
853
54.2k
    so_entry = so->table;
854
54.2k
    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
54.2k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
859
393k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
860
356k
            key = other_entry->key;
861
356k
            if (key != NULL) {
862
90.6k
                assert(so_entry->key == NULL);
863
90.6k
                FT_ATOMIC_STORE_SSIZE_RELAXED(so_entry->hash, other_entry->hash);
864
90.6k
                FT_ATOMIC_STORE_PTR_RELEASE(so_entry->key, Py_NewRef(key));
865
90.6k
            }
866
356k
        }
867
36.8k
        so->fill = other->fill;
868
36.8k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
869
36.8k
        return 0;
870
36.8k
    }
871
872
    /* If our table is empty, we can use set_insert_clean() */
873
17.3k
    if (so->fill == 0) {
874
1.15k
        setentry *newtable = so->table;
875
1.15k
        size_t newmask = (size_t)so->mask;
876
1.15k
        so->fill = other->used;
877
1.15k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
878
44.6k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
879
43.4k
            key = other_entry->key;
880
43.4k
            if (key != NULL && key != dummy) {
881
9.22k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
882
9.22k
                                 other_entry->hash);
883
9.22k
            }
884
43.4k
        }
885
1.15k
        return 0;
886
1.15k
    }
887
888
    /* We can't assure there are no duplicates, so do normal insertions */
889
182k
    for (i = 0; i <= other->mask; i++) {
890
165k
        other_entry = &other->table[i];
891
165k
        key = other_entry->key;
892
165k
        if (key != NULL && key != dummy) {
893
47.6k
            if (set_add_entry(so, key, other_entry->hash))
894
0
                return -1;
895
47.6k
        }
896
165k
    }
897
16.2k
    return 0;
898
16.2k
}
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
235
{
914
    /* Make sure the search finger is in bounds */
915
235
    setentry *entry = so->table + (so->finger & so->mask);
916
235
    setentry *limit = so->table + so->mask;
917
235
    PyObject *key;
918
919
235
    if (so->used == 0) {
920
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
921
0
        return NULL;
922
0
    }
923
942
    while (entry->key == NULL || entry->key==dummy) {
924
707
        entry++;
925
707
        if (entry > limit)
926
0
            entry = so->table;
927
707
    }
928
235
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, -1);
929
235
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
930
235
    key = entry->key;
931
235
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, dummy);
932
235
    so->finger = entry - so->table + 1;   /* next place to start */
933
235
    return key;
934
235
}
935
936
static int
937
set_traverse(PyObject *self, visitproc visit, void *arg)
938
2.76M
{
939
2.76M
    PySetObject *so = _PySet_CAST(self);
940
2.76M
    Py_ssize_t pos = 0;
941
2.76M
    setentry *entry;
942
943
5.49M
    while (set_next(so, &pos, &entry))
944
2.73M
        Py_VISIT(entry->key);
945
2.76M
    return 0;
946
2.76M
}
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
4.18k
{
956
4.18k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
957
4.18k
}
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
static Py_hash_t
970
frozenset_hash_impl(PyObject *self)
971
210
{
972
210
    PySetObject *so = _PySet_CAST(self);
973
210
    Py_uhash_t hash = 0;
974
210
    setentry *entry;
975
976
    /* Xor-in shuffled bits from every entry's hash field because xor is
977
       commutative and a frozenset hash should be independent of order.
978
979
       For speed, include null entries and dummy entries and then
980
       subtract out their effect afterwards so that the final hash
981
       depends only on active entries.  This allows the code to be
982
       vectorized by the compiler and it saves the unpredictable
983
       branches that would arise when trying to exclude null and dummy
984
       entries on every iteration. */
985
986
4.33k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
987
4.12k
        hash ^= _shuffle_bits(entry->hash);
988
989
    /* Remove the effect of an odd number of NULL entries */
990
210
    if ((so->mask + 1 - so->fill) & 1)
991
60
        hash ^= _shuffle_bits(0);
992
993
    /* Remove the effect of an odd number of dummy entries */
994
210
    if ((so->fill - so->used) & 1)
995
0
        hash ^= _shuffle_bits(-1);
996
997
    /* Factor in the number of active entries */
998
210
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
999
1000
    /* Disperse patterns arising in nested frozensets */
1001
210
    hash ^= (hash >> 11) ^ (hash >> 25);
1002
210
    hash = hash * 69069U + 907133923UL;
1003
1004
    /* -1 is reserved as an error code */
1005
210
    if (hash == (Py_uhash_t)-1)
1006
0
        hash = 590923713UL;
1007
1008
210
    return (Py_hash_t)hash;
1009
210
}
1010
1011
static Py_hash_t
1012
frozenset_hash(PyObject *self)
1013
350
{
1014
350
    PySetObject *so = _PySet_CAST(self);
1015
350
    Py_uhash_t hash;
1016
1017
350
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
1018
140
        return FT_ATOMIC_LOAD_SSIZE_ACQUIRE(so->hash);
1019
140
    }
1020
1021
210
    hash = frozenset_hash_impl(self);
1022
210
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->hash, hash);
1023
210
    return hash;
1024
350
}
1025
1026
/***** Set iterator type ***********************************************/
1027
1028
typedef struct {
1029
    PyObject_HEAD
1030
    PySetObject *si_set; /* Set to NULL when iterator is exhausted */
1031
    Py_ssize_t si_used;
1032
    Py_ssize_t si_pos;
1033
    Py_ssize_t len;
1034
} setiterobject;
1035
1036
static void
1037
setiter_dealloc(PyObject *self)
1038
310k
{
1039
310k
    setiterobject *si = (setiterobject*)self;
1040
    /* bpo-31095: UnTrack is needed before calling any callbacks */
1041
310k
    _PyObject_GC_UNTRACK(si);
1042
310k
    Py_XDECREF(si->si_set);
1043
310k
    PyObject_GC_Del(si);
1044
310k
}
1045
1046
static int
1047
setiter_traverse(PyObject *self, visitproc visit, void *arg)
1048
137
{
1049
137
    setiterobject *si = (setiterobject*)self;
1050
137
    Py_VISIT(si->si_set);
1051
137
    return 0;
1052
137
}
1053
1054
static PyObject *
1055
setiter_len(PyObject *op, PyObject *Py_UNUSED(ignored))
1056
10
{
1057
10
    setiterobject *si = (setiterobject*)op;
1058
10
    Py_ssize_t len = 0;
1059
10
    if (si->si_set != NULL && si->si_used == si->si_set->used)
1060
10
        len = si->len;
1061
10
    return PyLong_FromSsize_t(len);
1062
10
}
1063
1064
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
1065
1066
static PyObject *
1067
setiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1068
0
{
1069
0
    setiterobject *si = (setiterobject*)op;
1070
1071
    /* copy the iterator state */
1072
0
    setiterobject tmp = *si;
1073
0
    Py_XINCREF(tmp.si_set);
1074
1075
    /* iterate the temporary into a list */
1076
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1077
0
    Py_XDECREF(tmp.si_set);
1078
0
    if (list == NULL) {
1079
0
        return NULL;
1080
0
    }
1081
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1082
0
}
1083
1084
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
1085
1086
static PyMethodDef setiter_methods[] = {
1087
    {"__length_hint__", setiter_len, METH_NOARGS, length_hint_doc},
1088
    {"__reduce__", setiter_reduce, METH_NOARGS, reduce_doc},
1089
    {NULL,              NULL}           /* sentinel */
1090
};
1091
1092
static PyObject *setiter_iternext(PyObject *self)
1093
1.01M
{
1094
1.01M
    setiterobject *si = (setiterobject*)self;
1095
1.01M
    PyObject *key = NULL;
1096
1.01M
    Py_ssize_t i, mask;
1097
1.01M
    setentry *entry;
1098
1.01M
    PySetObject *so = si->si_set;
1099
1100
1.01M
    if (so == NULL)
1101
0
        return NULL;
1102
1.01M
    assert (PyAnySet_Check(so));
1103
1104
1.01M
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
1105
1.01M
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE_RELAXED(si->si_used);
1106
1.01M
    if (si_used != so_used) {
1107
0
        PyErr_SetString(PyExc_RuntimeError,
1108
0
                        "Set changed size during iteration");
1109
0
        si->si_used = -1; /* Make this state sticky */
1110
0
        return NULL;
1111
0
    }
1112
1113
1.01M
    Py_BEGIN_CRITICAL_SECTION(so);
1114
1.01M
    i = si->si_pos;
1115
1.01M
    assert(i>=0);
1116
1.01M
    entry = so->table;
1117
1.01M
    mask = so->mask;
1118
4.75M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
1119
3.73M
        i++;
1120
3.73M
    }
1121
1.01M
    if (i <= mask) {
1122
704k
        key = Py_NewRef(entry[i].key);
1123
704k
    }
1124
1.01M
    Py_END_CRITICAL_SECTION();
1125
1.01M
    si->si_pos = i+1;
1126
1.01M
    if (key == NULL) {
1127
310k
        si->si_set = NULL;
1128
310k
        Py_DECREF(so);
1129
310k
        return NULL;
1130
310k
    }
1131
704k
    si->len--;
1132
704k
    return key;
1133
1.01M
}
1134
1135
PyTypeObject PySetIter_Type = {
1136
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1137
    "set_iterator",                             /* tp_name */
1138
    sizeof(setiterobject),                      /* tp_basicsize */
1139
    0,                                          /* tp_itemsize */
1140
    /* methods */
1141
    setiter_dealloc,                            /* tp_dealloc */
1142
    0,                                          /* tp_vectorcall_offset */
1143
    0,                                          /* tp_getattr */
1144
    0,                                          /* tp_setattr */
1145
    0,                                          /* tp_as_async */
1146
    0,                                          /* tp_repr */
1147
    0,                                          /* tp_as_number */
1148
    0,                                          /* tp_as_sequence */
1149
    0,                                          /* tp_as_mapping */
1150
    0,                                          /* tp_hash */
1151
    0,                                          /* tp_call */
1152
    0,                                          /* tp_str */
1153
    PyObject_GenericGetAttr,                    /* tp_getattro */
1154
    0,                                          /* tp_setattro */
1155
    0,                                          /* tp_as_buffer */
1156
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
1157
    0,                                          /* tp_doc */
1158
    setiter_traverse,                           /* tp_traverse */
1159
    0,                                          /* tp_clear */
1160
    0,                                          /* tp_richcompare */
1161
    0,                                          /* tp_weaklistoffset */
1162
    PyObject_SelfIter,                          /* tp_iter */
1163
    setiter_iternext,                           /* tp_iternext */
1164
    setiter_methods,                            /* tp_methods */
1165
    0,
1166
};
1167
1168
static PyObject *
1169
set_iter(PyObject *so)
1170
310k
{
1171
310k
    Py_ssize_t size = set_len(so);
1172
310k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
1173
310k
    if (si == NULL)
1174
0
        return NULL;
1175
310k
    si->si_set = (PySetObject*)Py_NewRef(so);
1176
310k
    si->si_used = size;
1177
310k
    si->si_pos = 0;
1178
310k
    si->len = size;
1179
310k
    _PyObject_GC_TRACK(si);
1180
310k
    return (PyObject *)si;
1181
310k
}
1182
1183
static int
1184
set_update_dict_lock_held(PySetObject *so, PyObject *other)
1185
180
{
1186
180
    assert(PyDict_CheckExact(other));
1187
1188
180
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1189
180
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1190
1191
    /* Do one big resize at the start, rather than
1192
    * incrementally resizing as we insert new keys.  Expect
1193
    * that there will be no (or few) overlapping keys.
1194
    */
1195
180
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
1196
180
    if ((so->fill + dictsize)*5 >= so->mask*3) {
1197
4
        if (set_table_resize(so, (so->used + dictsize)*2) != 0) {
1198
0
            return -1;
1199
0
        }
1200
4
    }
1201
1202
180
    Py_ssize_t pos = 0;
1203
180
    PyObject *key;
1204
180
    PyObject *value;
1205
180
    Py_hash_t hash;
1206
344
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1207
164
        if (set_add_entry(so, key, hash)) {
1208
0
            return -1;
1209
0
        }
1210
164
    }
1211
180
    return 0;
1212
180
}
1213
1214
static int
1215
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1216
15.5k
{
1217
15.5k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1218
1219
15.5k
    PyObject *it = PyObject_GetIter(other);
1220
15.5k
    if (it == NULL) {
1221
0
        return -1;
1222
0
    }
1223
1224
15.5k
    PyObject *key;
1225
77.9k
    while ((key = PyIter_Next(it)) != NULL) {
1226
62.3k
        if (set_add_key(so, key)) {
1227
0
            Py_DECREF(it);
1228
0
            Py_DECREF(key);
1229
0
            return -1;
1230
0
        }
1231
62.3k
        Py_DECREF(key);
1232
62.3k
    }
1233
15.5k
    Py_DECREF(it);
1234
15.5k
    if (PyErr_Occurred())
1235
0
        return -1;
1236
15.5k
    return 0;
1237
15.5k
}
1238
1239
static int
1240
set_update_lock_held(PySetObject *so, PyObject *other)
1241
0
{
1242
0
    if (PyAnySet_Check(other)) {
1243
0
        return set_merge_lock_held(so, other);
1244
0
    }
1245
0
    else if (PyDict_CheckExact(other)) {
1246
0
        return set_update_dict_lock_held(so, other);
1247
0
    }
1248
0
    return set_update_iterable_lock_held(so, other);
1249
0
}
1250
1251
// set_update for a `so` that is only visible to the current thread
1252
static int
1253
set_update_local(PySetObject *so, PyObject *other)
1254
72.4k
{
1255
72.4k
    assert(Py_REFCNT(so) == 1);
1256
72.4k
    if (PyAnySet_Check(other)) {
1257
56.6k
        int rv;
1258
56.6k
        Py_BEGIN_CRITICAL_SECTION(other);
1259
56.6k
        rv = set_merge_lock_held(so, other);
1260
56.6k
        Py_END_CRITICAL_SECTION();
1261
56.6k
        return rv;
1262
56.6k
    }
1263
15.7k
    else if (PyDict_CheckExact(other)) {
1264
180
        int rv;
1265
180
        Py_BEGIN_CRITICAL_SECTION(other);
1266
180
        rv = set_update_dict_lock_held(so, other);
1267
180
        Py_END_CRITICAL_SECTION();
1268
180
        return rv;
1269
180
    }
1270
15.5k
    return set_update_iterable_lock_held(so, other);
1271
72.4k
}
1272
1273
static int
1274
set_update_internal(PySetObject *so, PyObject *other)
1275
68.9k
{
1276
68.9k
    if (PyAnySet_Check(other)) {
1277
68.9k
        if (Py_Is((PyObject *)so, other)) {
1278
0
            return 0;
1279
0
        }
1280
68.9k
        int rv;
1281
68.9k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1282
68.9k
        rv = set_merge_lock_held(so, other);
1283
68.9k
        Py_END_CRITICAL_SECTION2();
1284
68.9k
        return rv;
1285
68.9k
    }
1286
0
    else if (PyDict_CheckExact(other)) {
1287
0
        int rv;
1288
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1289
0
        rv = set_update_dict_lock_held(so, other);
1290
0
        Py_END_CRITICAL_SECTION2();
1291
0
        return rv;
1292
0
    }
1293
0
    else {
1294
0
        int rv;
1295
0
        Py_BEGIN_CRITICAL_SECTION(so);
1296
0
        rv = set_update_iterable_lock_held(so, other);
1297
0
        Py_END_CRITICAL_SECTION();
1298
0
        return rv;
1299
0
    }
1300
68.9k
}
1301
1302
/*[clinic input]
1303
set.update
1304
    so: setobject
1305
    *others: array
1306
1307
Update the set, adding elements from all others.
1308
[clinic start generated code]*/
1309
1310
static PyObject *
1311
set_update_impl(PySetObject *so, PyObject * const *others,
1312
                Py_ssize_t others_length)
1313
/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
1314
0
{
1315
0
    Py_ssize_t i;
1316
1317
0
    for (i = 0; i < others_length; i++) {
1318
0
        PyObject *other = others[i];
1319
0
        if (set_update_internal(so, other))
1320
0
            return NULL;
1321
0
    }
1322
0
    Py_RETURN_NONE;
1323
0
}
1324
1325
/* XXX Todo:
1326
   If aligned memory allocations become available, make the
1327
   set object 64 byte aligned so that most of the fields
1328
   can be retrieved or updated in a single cache line.
1329
*/
1330
1331
static PyObject *
1332
make_new_set(PyTypeObject *type, PyObject *iterable)
1333
3.29M
{
1334
3.29M
    assert(PyType_Check(type));
1335
3.29M
    PySetObject *so;
1336
1337
3.29M
    so = (PySetObject *)type->tp_alloc(type, 0);
1338
3.29M
    if (so == NULL)
1339
0
        return NULL;
1340
1341
3.29M
    so->fill = 0;
1342
3.29M
    so->used = 0;
1343
3.29M
    so->mask = PySet_MINSIZE - 1;
1344
3.29M
    so->table = so->smalltable;
1345
3.29M
    so->hash = -1;
1346
3.29M
    so->finger = 0;
1347
3.29M
    so->weakreflist = NULL;
1348
1349
3.29M
    if (iterable != NULL) {
1350
72.3k
        if (set_update_local(so, iterable)) {
1351
0
            Py_DECREF(so);
1352
0
            return NULL;
1353
0
        }
1354
72.3k
    }
1355
1356
3.29M
    return (PyObject *)so;
1357
3.29M
}
1358
1359
static PyObject *
1360
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1361
2.39k
{
1362
2.39k
    if (type != &PySet_Type && type != &PyFrozenSet_Type) {
1363
0
        if (PyType_IsSubtype(type, &PySet_Type))
1364
0
            type = &PySet_Type;
1365
0
        else
1366
0
            type = &PyFrozenSet_Type;
1367
0
    }
1368
2.39k
    return make_new_set(type, iterable);
1369
2.39k
}
1370
1371
static PyObject *
1372
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1373
333
{
1374
333
    if (type != &PyFrozenSet_Type) {
1375
0
        return make_new_set(type, iterable);
1376
0
    }
1377
1378
333
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1379
        /* frozenset(f) is idempotent */
1380
0
        return Py_NewRef(iterable);
1381
0
    }
1382
333
    return make_new_set(type, iterable);
1383
333
}
1384
1385
static PyObject *
1386
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1387
0
{
1388
0
    PyObject *iterable = NULL;
1389
1390
0
    if ((type == &PyFrozenSet_Type ||
1391
0
         type->tp_init == PyFrozenSet_Type.tp_init) &&
1392
0
        !_PyArg_NoKeywords("frozenset", kwds)) {
1393
0
        return NULL;
1394
0
    }
1395
1396
0
    if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) {
1397
0
        return NULL;
1398
0
    }
1399
1400
0
    return make_new_frozenset(type, iterable);
1401
0
}
1402
1403
static PyObject *
1404
frozenset_vectorcall(PyObject *type, PyObject * const*args,
1405
                     size_t nargsf, PyObject *kwnames)
1406
333
{
1407
333
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1408
0
        return NULL;
1409
0
    }
1410
1411
333
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1412
333
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1413
0
        return NULL;
1414
0
    }
1415
1416
333
    PyObject *iterable = (nargs ? args[0] : NULL);
1417
333
    return make_new_frozenset(_PyType_CAST(type), iterable);
1418
333
}
1419
1420
static PyObject *
1421
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1422
0
{
1423
0
    return make_new_set(type, NULL);
1424
0
}
1425
1426
#ifdef Py_GIL_DISABLED
1427
static void
1428
copy_small_table(setentry *dest, setentry *src)
1429
{
1430
    for (Py_ssize_t i = 0; i < PySet_MINSIZE; i++) {
1431
        _Py_atomic_store_ptr_release(&dest[i].key, src[i].key);
1432
        _Py_atomic_store_ssize_relaxed(&dest[i].hash, src[i].hash);
1433
    }
1434
}
1435
#endif
1436
1437
/* set_swap_bodies() switches the contents of any two sets by moving their
1438
   internal data pointers and, if needed, copying the internal smalltables.
1439
   Semantically equivalent to:
1440
1441
     t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
1442
1443
   The function always succeeds and it leaves both objects in a stable state.
1444
   Useful for operations that update in-place (by allowing an intermediate
1445
   result to be swapped into one of the original inputs).
1446
*/
1447
1448
static void
1449
set_swap_bodies(PySetObject *a, PySetObject *b)
1450
{
1451
    Py_ssize_t t;
1452
    setentry *u;
1453
    setentry tab[PySet_MINSIZE];
1454
    Py_hash_t h;
1455
1456
    setentry *a_table = a->table;
1457
    setentry *b_table = b->table;
1458
    FT_ATOMIC_STORE_PTR_RELEASE(a->table, NULL);
1459
    FT_ATOMIC_STORE_PTR_RELEASE(b->table, NULL);
1460
1461
    t = a->fill;     a->fill   = b->fill;        b->fill  = t;
1462
    t = a->used;
1463
    FT_ATOMIC_STORE_SSIZE_RELAXED(a->used, b->used);
1464
    FT_ATOMIC_STORE_SSIZE_RELAXED(b->used, t);
1465
    t = a->mask;
1466
    FT_ATOMIC_STORE_SSIZE_RELEASE(a->mask, b->mask);
1467
    FT_ATOMIC_STORE_SSIZE_RELEASE(b->mask, t);
1468
1469
    u = a_table;
1470
    if (a_table == a->smalltable)
1471
        u = b->smalltable;
1472
    a_table  = b_table;
1473
    if (b_table == b->smalltable)
1474
        a_table = a->smalltable;
1475
    b_table = u;
1476
1477
    if (a_table == a->smalltable || b_table == b->smalltable) {
1478
        memcpy(tab, a->smalltable, sizeof(tab));
1479
#ifndef Py_GIL_DISABLED
1480
        memcpy(a->smalltable, b->smalltable, sizeof(tab));
1481
        memcpy(b->smalltable, tab, sizeof(tab));
1482
#else
1483
        copy_small_table(a->smalltable, b->smalltable);
1484
        copy_small_table(b->smalltable, tab);
1485
#endif
1486
    }
1487
1488
    if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type)  &&
1489
        PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
1490
        h = FT_ATOMIC_LOAD_SSIZE_RELAXED(a->hash);
1491
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, FT_ATOMIC_LOAD_SSIZE_RELAXED(b->hash));
1492
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, h);
1493
    } else {
1494
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, -1);
1495
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, -1);
1496
    }
1497
    if (!SET_IS_SHARED(b) && SET_IS_SHARED(a)) {
1498
        SET_MARK_SHARED(b);
1499
    }
1500
    if (!SET_IS_SHARED(a) && SET_IS_SHARED(b)) {
1501
        SET_MARK_SHARED(a);
1502
    }
1503
    FT_ATOMIC_STORE_PTR_RELEASE(a->table, a_table);
1504
    FT_ATOMIC_STORE_PTR_RELEASE(b->table, b_table);
1505
}
1506
1507
/*[clinic input]
1508
@critical_section
1509
set.copy
1510
    so: setobject
1511
1512
Return a shallow copy of a set.
1513
[clinic start generated code]*/
1514
1515
static PyObject *
1516
set_copy_impl(PySetObject *so)
1517
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
1518
2.21k
{
1519
2.21k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1520
2.21k
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1521
2.21k
    if (copy == NULL) {
1522
0
        return NULL;
1523
0
    }
1524
2.21k
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1525
0
        Py_DECREF(copy);
1526
0
        return NULL;
1527
0
    }
1528
2.21k
    return copy;
1529
2.21k
}
1530
1531
/*[clinic input]
1532
@critical_section
1533
frozenset.copy
1534
    so: setobject
1535
1536
Return a shallow copy of a set.
1537
[clinic start generated code]*/
1538
1539
static PyObject *
1540
frozenset_copy_impl(PySetObject *so)
1541
/*[clinic end generated code: output=b356263526af9e70 input=fbf5bef131268dd7]*/
1542
0
{
1543
0
    if (PyFrozenSet_CheckExact(so)) {
1544
0
        return Py_NewRef(so);
1545
0
    }
1546
0
    return set_copy_impl(so);
1547
0
}
1548
1549
/*[clinic input]
1550
@critical_section
1551
set.clear
1552
    so: setobject
1553
1554
Remove all elements from this set.
1555
[clinic start generated code]*/
1556
1557
static PyObject *
1558
set_clear_impl(PySetObject *so)
1559
/*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/
1560
32.3k
{
1561
32.3k
    set_clear_internal((PyObject*)so);
1562
32.3k
    Py_RETURN_NONE;
1563
32.3k
}
1564
1565
/*[clinic input]
1566
set.union
1567
    so: setobject
1568
    *others: array
1569
1570
Return a new set with elements from the set and all others.
1571
[clinic start generated code]*/
1572
1573
static PyObject *
1574
set_union_impl(PySetObject *so, PyObject * const *others,
1575
               Py_ssize_t others_length)
1576
/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
1577
2
{
1578
2
    PySetObject *result;
1579
2
    PyObject *other;
1580
2
    Py_ssize_t i;
1581
1582
2
    result = (PySetObject *)set_copy((PyObject *)so, NULL);
1583
2
    if (result == NULL)
1584
0
        return NULL;
1585
1586
4
    for (i = 0; i < others_length; i++) {
1587
2
        other = others[i];
1588
2
        if ((PyObject *)so == other)
1589
0
            continue;
1590
2
        if (set_update_local(result, other)) {
1591
0
            Py_DECREF(result);
1592
0
            return NULL;
1593
0
        }
1594
2
    }
1595
2
    return (PyObject *)result;
1596
2
}
1597
1598
static PyObject *
1599
set_or(PyObject *self, PyObject *other)
1600
64
{
1601
64
    PySetObject *result;
1602
1603
64
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1604
0
        Py_RETURN_NOTIMPLEMENTED;
1605
1606
64
    result = (PySetObject *)set_copy(self, NULL);
1607
64
    if (result == NULL) {
1608
0
        return NULL;
1609
0
    }
1610
64
    if (Py_Is(self, other)) {
1611
0
        return (PyObject *)result;
1612
0
    }
1613
64
    if (set_update_local(result, other)) {
1614
0
        Py_DECREF(result);
1615
0
        return NULL;
1616
0
    }
1617
64
    return (PyObject *)result;
1618
64
}
1619
1620
static PyObject *
1621
set_ior(PyObject *self, PyObject *other)
1622
68.8k
{
1623
68.8k
    if (!PyAnySet_Check(other))
1624
0
        Py_RETURN_NOTIMPLEMENTED;
1625
68.8k
    PySetObject *so = _PySet_CAST(self);
1626
1627
68.8k
    if (set_update_internal(so, other)) {
1628
0
        return NULL;
1629
0
    }
1630
68.8k
    return Py_NewRef(so);
1631
68.8k
}
1632
1633
static PyObject *
1634
set_intersection(PySetObject *so, PyObject *other)
1635
180
{
1636
180
    PySetObject *result;
1637
180
    PyObject *key, *it, *tmp;
1638
180
    Py_hash_t hash;
1639
180
    int rv;
1640
1641
180
    if ((PyObject *)so == other)
1642
0
        return set_copy_impl(so);
1643
1644
180
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1645
180
    if (result == NULL)
1646
0
        return NULL;
1647
1648
180
    if (PyAnySet_Check(other)) {
1649
180
        Py_ssize_t pos = 0;
1650
180
        setentry *entry;
1651
1652
180
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1653
144
            tmp = (PyObject *)so;
1654
144
            so = (PySetObject *)other;
1655
144
            other = tmp;
1656
144
        }
1657
1658
252
        while (set_next((PySetObject *)other, &pos, &entry)) {
1659
72
            key = entry->key;
1660
72
            hash = entry->hash;
1661
72
            Py_INCREF(key);
1662
72
            rv = set_contains_entry(so, key, hash);
1663
72
            if (rv < 0) {
1664
0
                Py_DECREF(result);
1665
0
                Py_DECREF(key);
1666
0
                return NULL;
1667
0
            }
1668
72
            if (rv) {
1669
0
                if (set_add_entry(result, key, hash)) {
1670
0
                    Py_DECREF(result);
1671
0
                    Py_DECREF(key);
1672
0
                    return NULL;
1673
0
                }
1674
0
            }
1675
72
            Py_DECREF(key);
1676
72
        }
1677
180
        return (PyObject *)result;
1678
180
    }
1679
1680
0
    it = PyObject_GetIter(other);
1681
0
    if (it == NULL) {
1682
0
        Py_DECREF(result);
1683
0
        return NULL;
1684
0
    }
1685
1686
0
    while ((key = PyIter_Next(it)) != NULL) {
1687
0
        hash = PyObject_Hash(key);
1688
0
        if (hash == -1)
1689
0
            goto error;
1690
0
        rv = set_contains_entry(so, key, hash);
1691
0
        if (rv < 0)
1692
0
            goto error;
1693
0
        if (rv) {
1694
0
            if (set_add_entry(result, key, hash))
1695
0
                goto error;
1696
0
            if (PySet_GET_SIZE(result) >= PySet_GET_SIZE(so)) {
1697
0
                Py_DECREF(key);
1698
0
                break;
1699
0
            }
1700
0
        }
1701
0
        Py_DECREF(key);
1702
0
    }
1703
0
    Py_DECREF(it);
1704
0
    if (PyErr_Occurred()) {
1705
0
        Py_DECREF(result);
1706
0
        return NULL;
1707
0
    }
1708
0
    return (PyObject *)result;
1709
0
  error:
1710
0
    Py_DECREF(it);
1711
0
    Py_DECREF(result);
1712
0
    Py_DECREF(key);
1713
0
    return NULL;
1714
0
}
1715
1716
/*[clinic input]
1717
set.intersection as set_intersection_multi
1718
    so: setobject
1719
    *others: array
1720
1721
Return a new set with elements common to the set and all others.
1722
[clinic start generated code]*/
1723
1724
static PyObject *
1725
set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
1726
                            Py_ssize_t others_length)
1727
/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
1728
0
{
1729
0
    Py_ssize_t i;
1730
1731
0
    if (others_length == 0) {
1732
0
        return set_copy((PyObject *)so, NULL);
1733
0
    }
1734
1735
0
    PyObject *result = Py_NewRef(so);
1736
0
    for (i = 0; i < others_length; i++) {
1737
0
        PyObject *other = others[i];
1738
0
        PyObject *newresult;
1739
0
        Py_BEGIN_CRITICAL_SECTION2(result, other);
1740
0
        newresult = set_intersection((PySetObject *)result, other);
1741
0
        Py_END_CRITICAL_SECTION2();
1742
0
        if (newresult == NULL) {
1743
0
            Py_DECREF(result);
1744
0
            return NULL;
1745
0
        }
1746
0
        Py_SETREF(result, newresult);
1747
0
    }
1748
0
    return result;
1749
0
}
1750
1751
static PyObject *
1752
set_intersection_update(PySetObject *so, PyObject *other)
1753
0
{
1754
0
    PyObject *tmp;
1755
1756
0
    tmp = set_intersection(so, other);
1757
0
    if (tmp == NULL)
1758
0
        return NULL;
1759
0
    set_swap_bodies(so, (PySetObject *)tmp);
1760
0
    Py_DECREF(tmp);
1761
0
    Py_RETURN_NONE;
1762
0
}
1763
1764
/*[clinic input]
1765
set.intersection_update as set_intersection_update_multi
1766
    so: setobject
1767
    *others: array
1768
1769
Update the set, keeping only elements found in it and all others.
1770
[clinic start generated code]*/
1771
1772
static PyObject *
1773
set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
1774
                                   Py_ssize_t others_length)
1775
/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
1776
0
{
1777
0
    PyObject *tmp;
1778
1779
0
    tmp = set_intersection_multi_impl(so, others, others_length);
1780
0
    if (tmp == NULL)
1781
0
        return NULL;
1782
0
    Py_BEGIN_CRITICAL_SECTION(so);
1783
0
    set_swap_bodies(so, (PySetObject *)tmp);
1784
0
    Py_END_CRITICAL_SECTION();
1785
0
    Py_DECREF(tmp);
1786
0
    Py_RETURN_NONE;
1787
0
}
1788
1789
static PyObject *
1790
set_and(PyObject *self, PyObject *other)
1791
180
{
1792
180
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1793
0
        Py_RETURN_NOTIMPLEMENTED;
1794
180
    PySetObject *so = _PySet_CAST(self);
1795
1796
180
    PyObject *rv;
1797
180
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1798
180
    rv = set_intersection(so, other);
1799
180
    Py_END_CRITICAL_SECTION2();
1800
1801
180
    return rv;
1802
180
}
1803
1804
static PyObject *
1805
set_iand(PyObject *self, PyObject *other)
1806
0
{
1807
0
    PyObject *result;
1808
1809
0
    if (!PyAnySet_Check(other))
1810
0
        Py_RETURN_NOTIMPLEMENTED;
1811
0
    PySetObject *so = _PySet_CAST(self);
1812
1813
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1814
0
    result = set_intersection_update(so, other);
1815
0
    Py_END_CRITICAL_SECTION2();
1816
1817
0
    if (result == NULL)
1818
0
        return NULL;
1819
0
    Py_DECREF(result);
1820
0
    return Py_NewRef(so);
1821
0
}
1822
1823
/*[clinic input]
1824
@critical_section so other
1825
set.isdisjoint
1826
    so: setobject
1827
    other: object
1828
    /
1829
1830
Return True if two sets have a null intersection.
1831
[clinic start generated code]*/
1832
1833
static PyObject *
1834
set_isdisjoint_impl(PySetObject *so, PyObject *other)
1835
/*[clinic end generated code: output=273493f2d57c565e input=32f8dcab5e0fc7d6]*/
1836
90.0k
{
1837
90.0k
    PyObject *key, *it, *tmp;
1838
90.0k
    int rv;
1839
1840
90.0k
    if ((PyObject *)so == other) {
1841
0
        if (PySet_GET_SIZE(so) == 0)
1842
0
            Py_RETURN_TRUE;
1843
0
        else
1844
0
            Py_RETURN_FALSE;
1845
0
    }
1846
1847
90.0k
    if (PyAnySet_CheckExact(other)) {
1848
0
        Py_ssize_t pos = 0;
1849
0
        setentry *entry;
1850
1851
0
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1852
0
            tmp = (PyObject *)so;
1853
0
            so = (PySetObject *)other;
1854
0
            other = tmp;
1855
0
        }
1856
0
        while (set_next((PySetObject *)other, &pos, &entry)) {
1857
0
            PyObject *key = entry->key;
1858
0
            Py_INCREF(key);
1859
0
            rv = set_contains_entry(so, key, entry->hash);
1860
0
            Py_DECREF(key);
1861
0
            if (rv < 0) {
1862
0
                return NULL;
1863
0
            }
1864
0
            if (rv) {
1865
0
                Py_RETURN_FALSE;
1866
0
            }
1867
0
        }
1868
0
        Py_RETURN_TRUE;
1869
0
    }
1870
1871
90.0k
    it = PyObject_GetIter(other);
1872
90.0k
    if (it == NULL)
1873
0
        return NULL;
1874
1875
4.27M
    while ((key = PyIter_Next(it)) != NULL) {
1876
4.19M
        rv = set_contains_key(so, key);
1877
4.19M
        Py_DECREF(key);
1878
4.19M
        if (rv < 0) {
1879
0
            Py_DECREF(it);
1880
0
            return NULL;
1881
0
        }
1882
4.19M
        if (rv) {
1883
14.7k
            Py_DECREF(it);
1884
14.7k
            Py_RETURN_FALSE;
1885
14.7k
        }
1886
4.19M
    }
1887
75.3k
    Py_DECREF(it);
1888
75.3k
    if (PyErr_Occurred())
1889
0
        return NULL;
1890
75.3k
    Py_RETURN_TRUE;
1891
75.3k
}
1892
1893
static int
1894
set_difference_update_internal(PySetObject *so, PyObject *other)
1895
10
{
1896
10
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1897
10
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1898
1899
10
    if ((PyObject *)so == other)
1900
0
        return set_clear_internal((PyObject*)so);
1901
1902
10
    if (PyAnySet_Check(other)) {
1903
10
        setentry *entry;
1904
10
        Py_ssize_t pos = 0;
1905
1906
        /* Optimization:  When the other set is more than 8 times
1907
           larger than the base set, replace the other set with
1908
           intersection of the two sets.
1909
        */
1910
10
        if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
1911
0
            other = set_intersection(so, other);
1912
0
            if (other == NULL)
1913
0
                return -1;
1914
10
        } else {
1915
10
            Py_INCREF(other);
1916
10
        }
1917
1918
22
        while (set_next((PySetObject *)other, &pos, &entry)) {
1919
12
            PyObject *key = entry->key;
1920
12
            Py_INCREF(key);
1921
12
            if (set_discard_entry(so, key, entry->hash) < 0) {
1922
0
                Py_DECREF(other);
1923
0
                Py_DECREF(key);
1924
0
                return -1;
1925
0
            }
1926
12
            Py_DECREF(key);
1927
12
        }
1928
1929
10
        Py_DECREF(other);
1930
10
    } else {
1931
0
        PyObject *key, *it;
1932
0
        it = PyObject_GetIter(other);
1933
0
        if (it == NULL)
1934
0
            return -1;
1935
1936
0
        while ((key = PyIter_Next(it)) != NULL) {
1937
0
            if (set_discard_key(so, key) < 0) {
1938
0
                Py_DECREF(it);
1939
0
                Py_DECREF(key);
1940
0
                return -1;
1941
0
            }
1942
0
            Py_DECREF(key);
1943
0
        }
1944
0
        Py_DECREF(it);
1945
0
        if (PyErr_Occurred())
1946
0
            return -1;
1947
0
    }
1948
    /* If more than 1/4th are dummies, then resize them away. */
1949
10
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1950
10
        return 0;
1951
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1952
10
}
1953
1954
/*[clinic input]
1955
set.difference_update
1956
    so: setobject
1957
    *others: array
1958
1959
Update the set, removing elements found in others.
1960
[clinic start generated code]*/
1961
1962
static PyObject *
1963
set_difference_update_impl(PySetObject *so, PyObject * const *others,
1964
                           Py_ssize_t others_length)
1965
/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
1966
0
{
1967
0
    Py_ssize_t i;
1968
1969
0
    for (i = 0; i < others_length; i++) {
1970
0
        PyObject *other = others[i];
1971
0
        int rv;
1972
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1973
0
        rv = set_difference_update_internal(so, other);
1974
0
        Py_END_CRITICAL_SECTION2();
1975
0
        if (rv) {
1976
0
            return NULL;
1977
0
        }
1978
0
    }
1979
0
    Py_RETURN_NONE;
1980
0
}
1981
1982
static PyObject *
1983
set_copy_and_difference(PySetObject *so, PyObject *other)
1984
10
{
1985
10
    PyObject *result;
1986
1987
10
    result = set_copy_impl(so);
1988
10
    if (result == NULL)
1989
0
        return NULL;
1990
10
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1991
10
        return result;
1992
0
    Py_DECREF(result);
1993
0
    return NULL;
1994
10
}
1995
1996
static PyObject *
1997
set_difference(PySetObject *so, PyObject *other)
1998
12
{
1999
12
    PyObject *result;
2000
12
    PyObject *key;
2001
12
    Py_hash_t hash;
2002
12
    setentry *entry;
2003
12
    Py_ssize_t pos = 0, other_size;
2004
12
    int rv;
2005
2006
12
    if (PyAnySet_Check(other)) {
2007
12
        other_size = PySet_GET_SIZE(other);
2008
12
    }
2009
0
    else if (PyDict_CheckExact(other)) {
2010
0
        other_size = PyDict_GET_SIZE(other);
2011
0
    }
2012
0
    else {
2013
0
        return set_copy_and_difference(so, other);
2014
0
    }
2015
2016
    /* If len(so) much more than len(other), it's more efficient to simply copy
2017
     * so and then iterate other looking for common elements. */
2018
12
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
2019
10
        return set_copy_and_difference(so, other);
2020
10
    }
2021
2022
2
    result = make_new_set_basetype(Py_TYPE(so), NULL);
2023
2
    if (result == NULL)
2024
0
        return NULL;
2025
2026
2
    if (PyDict_CheckExact(other)) {
2027
0
        while (set_next(so, &pos, &entry)) {
2028
0
            key = entry->key;
2029
0
            hash = entry->hash;
2030
0
            Py_INCREF(key);
2031
0
            rv = _PyDict_Contains_KnownHash(other, key, hash);
2032
0
            if (rv < 0) {
2033
0
                Py_DECREF(result);
2034
0
                Py_DECREF(key);
2035
0
                return NULL;
2036
0
            }
2037
0
            if (!rv) {
2038
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
2039
0
                    Py_DECREF(result);
2040
0
                    Py_DECREF(key);
2041
0
                    return NULL;
2042
0
                }
2043
0
            }
2044
0
            Py_DECREF(key);
2045
0
        }
2046
0
        return result;
2047
0
    }
2048
2049
    /* Iterate over so, checking for common elements in other. */
2050
28
    while (set_next(so, &pos, &entry)) {
2051
26
        key = entry->key;
2052
26
        hash = entry->hash;
2053
26
        Py_INCREF(key);
2054
26
        rv = set_contains_entry((PySetObject *)other, key, hash);
2055
26
        if (rv < 0) {
2056
0
            Py_DECREF(result);
2057
0
            Py_DECREF(key);
2058
0
            return NULL;
2059
0
        }
2060
26
        if (!rv) {
2061
20
            if (set_add_entry((PySetObject *)result, key, hash)) {
2062
0
                Py_DECREF(result);
2063
0
                Py_DECREF(key);
2064
0
                return NULL;
2065
0
            }
2066
20
        }
2067
26
        Py_DECREF(key);
2068
26
    }
2069
2
    return result;
2070
2
}
2071
2072
/*[clinic input]
2073
set.difference as set_difference_multi
2074
    so: setobject
2075
    *others: array
2076
2077
Return a new set with elements in the set that are not in the others.
2078
[clinic start generated code]*/
2079
2080
static PyObject *
2081
set_difference_multi_impl(PySetObject *so, PyObject * const *others,
2082
                          Py_ssize_t others_length)
2083
/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
2084
0
{
2085
0
    Py_ssize_t i;
2086
0
    PyObject *result, *other;
2087
2088
0
    if (others_length == 0) {
2089
0
        return set_copy((PyObject *)so, NULL);
2090
0
    }
2091
2092
0
    other = others[0];
2093
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2094
0
    result = set_difference(so, other);
2095
0
    Py_END_CRITICAL_SECTION2();
2096
0
    if (result == NULL)
2097
0
        return NULL;
2098
2099
0
    for (i = 1; i < others_length; i++) {
2100
0
        other = others[i];
2101
0
        int rv;
2102
0
        Py_BEGIN_CRITICAL_SECTION(other);
2103
0
        rv = set_difference_update_internal((PySetObject *)result, other);
2104
0
        Py_END_CRITICAL_SECTION();
2105
0
        if (rv) {
2106
0
            Py_DECREF(result);
2107
0
            return NULL;
2108
0
        }
2109
0
    }
2110
0
    return result;
2111
0
}
2112
2113
static PyObject *
2114
set_sub(PyObject *self, PyObject *other)
2115
12
{
2116
12
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2117
0
        Py_RETURN_NOTIMPLEMENTED;
2118
12
    PySetObject *so = _PySet_CAST(self);
2119
2120
12
    PyObject *rv;
2121
12
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2122
12
    rv = set_difference(so, other);
2123
12
    Py_END_CRITICAL_SECTION2();
2124
12
    return rv;
2125
12
}
2126
2127
static PyObject *
2128
set_isub(PyObject *self, PyObject *other)
2129
0
{
2130
0
    if (!PyAnySet_Check(other))
2131
0
        Py_RETURN_NOTIMPLEMENTED;
2132
0
    PySetObject *so = _PySet_CAST(self);
2133
2134
0
    int rv;
2135
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2136
0
    rv = set_difference_update_internal(so, other);
2137
0
    Py_END_CRITICAL_SECTION2();
2138
0
    if (rv < 0) {
2139
0
        return NULL;
2140
0
    }
2141
0
    return Py_NewRef(so);
2142
0
}
2143
2144
static int
2145
set_symmetric_difference_update_dict(PySetObject *so, PyObject *other)
2146
0
{
2147
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
2148
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
2149
2150
0
    Py_ssize_t pos = 0;
2151
0
    PyObject *key, *value;
2152
0
    Py_hash_t hash;
2153
0
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
2154
0
        Py_INCREF(key);
2155
0
        int rv = set_discard_entry(so, key, hash);
2156
0
        if (rv < 0) {
2157
0
            Py_DECREF(key);
2158
0
            return -1;
2159
0
        }
2160
0
        if (rv == DISCARD_NOTFOUND) {
2161
0
            if (set_add_entry(so, key, hash)) {
2162
0
                Py_DECREF(key);
2163
0
                return -1;
2164
0
            }
2165
0
        }
2166
0
        Py_DECREF(key);
2167
0
    }
2168
0
    return 0;
2169
0
}
2170
2171
static int
2172
set_symmetric_difference_update_set(PySetObject *so, PySetObject *other)
2173
0
{
2174
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
2175
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
2176
2177
0
    Py_ssize_t pos = 0;
2178
0
    setentry *entry;
2179
0
    while (set_next(other, &pos, &entry)) {
2180
0
        PyObject *key = Py_NewRef(entry->key);
2181
0
        Py_hash_t hash = entry->hash;
2182
0
        int rv = set_discard_entry(so, key, hash);
2183
0
        if (rv < 0) {
2184
0
            Py_DECREF(key);
2185
0
            return -1;
2186
0
        }
2187
0
        if (rv == DISCARD_NOTFOUND) {
2188
0
            if (set_add_entry(so, key, hash)) {
2189
0
                Py_DECREF(key);
2190
0
                return -1;
2191
0
            }
2192
0
        }
2193
0
        Py_DECREF(key);
2194
0
    }
2195
0
    return 0;
2196
0
}
2197
2198
/*[clinic input]
2199
@permit_long_summary
2200
set.symmetric_difference_update
2201
    so: setobject
2202
    other: object
2203
    /
2204
2205
Update the set, keeping only elements found in either set, but not in both.
2206
[clinic start generated code]*/
2207
2208
static PyObject *
2209
set_symmetric_difference_update_impl(PySetObject *so, PyObject *other)
2210
/*[clinic end generated code: output=79f80b4ee5da66c1 input=86a3dddac9bfb15e]*/
2211
0
{
2212
0
    if (Py_Is((PyObject *)so, other)) {
2213
0
        return set_clear((PyObject *)so, NULL);
2214
0
    }
2215
2216
0
    int rv;
2217
0
    if (PyDict_CheckExact(other)) {
2218
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2219
0
        rv = set_symmetric_difference_update_dict(so, other);
2220
0
        Py_END_CRITICAL_SECTION2();
2221
0
    }
2222
0
    else if (PyAnySet_Check(other)) {
2223
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2224
0
        rv = set_symmetric_difference_update_set(so, (PySetObject *)other);
2225
0
        Py_END_CRITICAL_SECTION2();
2226
0
    }
2227
0
    else {
2228
0
        PySetObject *otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
2229
0
        if (otherset == NULL) {
2230
0
            return NULL;
2231
0
        }
2232
2233
0
        Py_BEGIN_CRITICAL_SECTION(so);
2234
0
        rv = set_symmetric_difference_update_set(so, otherset);
2235
0
        Py_END_CRITICAL_SECTION();
2236
2237
0
        Py_DECREF(otherset);
2238
0
    }
2239
0
    if (rv < 0) {
2240
0
        return NULL;
2241
0
    }
2242
0
    Py_RETURN_NONE;
2243
0
}
2244
2245
/*[clinic input]
2246
@critical_section so other
2247
set.symmetric_difference
2248
    so: setobject
2249
    other: object
2250
    /
2251
2252
Return a new set with elements in either the set or other but not both.
2253
[clinic start generated code]*/
2254
2255
static PyObject *
2256
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
2257
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
2258
0
{
2259
0
    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
2260
0
    if (result == NULL) {
2261
0
        return NULL;
2262
0
    }
2263
0
    if (set_update_lock_held(result, other) < 0) {
2264
0
        Py_DECREF(result);
2265
0
        return NULL;
2266
0
    }
2267
0
    if (set_symmetric_difference_update_set(result, so) < 0) {
2268
0
        Py_DECREF(result);
2269
0
        return NULL;
2270
0
    }
2271
0
    return (PyObject *)result;
2272
0
}
2273
2274
static PyObject *
2275
set_xor(PyObject *self, PyObject *other)
2276
0
{
2277
0
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2278
0
        Py_RETURN_NOTIMPLEMENTED;
2279
0
    PySetObject *so = _PySet_CAST(self);
2280
0
    return set_symmetric_difference((PyObject*)so, other);
2281
0
}
2282
2283
static PyObject *
2284
set_ixor(PyObject *self, PyObject *other)
2285
0
{
2286
0
    PyObject *result;
2287
2288
0
    if (!PyAnySet_Check(other))
2289
0
        Py_RETURN_NOTIMPLEMENTED;
2290
0
    PySetObject *so = _PySet_CAST(self);
2291
2292
0
    result = set_symmetric_difference_update((PyObject*)so, other);
2293
0
    if (result == NULL)
2294
0
        return NULL;
2295
0
    Py_DECREF(result);
2296
0
    return Py_NewRef(so);
2297
0
}
2298
2299
/*[clinic input]
2300
@critical_section so other
2301
set.issubset
2302
    so: setobject
2303
    other: object
2304
    /
2305
2306
Report whether another set contains this set.
2307
[clinic start generated code]*/
2308
2309
static PyObject *
2310
set_issubset_impl(PySetObject *so, PyObject *other)
2311
/*[clinic end generated code: output=b2b59d5f314555ce input=f2a4fd0f2537758b]*/
2312
118
{
2313
118
    setentry *entry;
2314
118
    Py_ssize_t pos = 0;
2315
118
    int rv;
2316
2317
118
    if (!PyAnySet_Check(other)) {
2318
0
        PyObject *tmp = set_intersection(so, other);
2319
0
        if (tmp == NULL) {
2320
0
            return NULL;
2321
0
        }
2322
0
        int result = (PySet_GET_SIZE(tmp) == PySet_GET_SIZE(so));
2323
0
        Py_DECREF(tmp);
2324
0
        return PyBool_FromLong(result);
2325
0
    }
2326
118
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2327
0
        Py_RETURN_FALSE;
2328
2329
532
    while (set_next(so, &pos, &entry)) {
2330
414
        PyObject *key = entry->key;
2331
414
        Py_INCREF(key);
2332
414
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2333
414
        Py_DECREF(key);
2334
414
        if (rv < 0) {
2335
0
            return NULL;
2336
0
        }
2337
414
        if (!rv) {
2338
0
            Py_RETURN_FALSE;
2339
0
        }
2340
414
    }
2341
118
    Py_RETURN_TRUE;
2342
118
}
2343
2344
/*[clinic input]
2345
@critical_section so other
2346
set.issuperset
2347
    so: setobject
2348
    other: object
2349
    /
2350
2351
Report whether this set contains another set.
2352
[clinic start generated code]*/
2353
2354
static PyObject *
2355
set_issuperset_impl(PySetObject *so, PyObject *other)
2356
/*[clinic end generated code: output=ecf00ce552c09461 input=5f2e1f262e6e4ccc]*/
2357
13.7k
{
2358
13.7k
    if (PyAnySet_Check(other)) {
2359
0
        return set_issubset(other, (PyObject *)so);
2360
0
    }
2361
2362
13.7k
    PyObject *key, *it = PyObject_GetIter(other);
2363
13.7k
    if (it == NULL) {
2364
0
        return NULL;
2365
0
    }
2366
102k
    while ((key = PyIter_Next(it)) != NULL) {
2367
88.7k
        int rv = set_contains_key(so, key);
2368
88.7k
        Py_DECREF(key);
2369
88.7k
        if (rv < 0) {
2370
0
            Py_DECREF(it);
2371
0
            return NULL;
2372
0
        }
2373
88.7k
        if (!rv) {
2374
21
            Py_DECREF(it);
2375
21
            Py_RETURN_FALSE;
2376
21
        }
2377
88.7k
    }
2378
13.7k
    Py_DECREF(it);
2379
13.7k
    if (PyErr_Occurred()) {
2380
0
        return NULL;
2381
0
    }
2382
13.7k
    Py_RETURN_TRUE;
2383
13.7k
}
2384
2385
static PyObject *
2386
set_richcompare(PyObject *self, PyObject *w, int op)
2387
118
{
2388
118
    PySetObject *v = _PySet_CAST(self);
2389
118
    PyObject *r1;
2390
118
    int r2;
2391
2392
118
    if(!PyAnySet_Check(w))
2393
0
        Py_RETURN_NOTIMPLEMENTED;
2394
2395
118
    switch (op) {
2396
44
    case Py_EQ:
2397
44
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
2398
0
            Py_RETURN_FALSE;
2399
44
        Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
2400
44
        Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject *)w)->hash);
2401
44
        if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
2402
0
            Py_RETURN_FALSE;
2403
44
        return set_issubset((PyObject*)v, w);
2404
0
    case Py_NE:
2405
0
        r1 = set_richcompare((PyObject*)v, w, Py_EQ);
2406
0
        if (r1 == NULL)
2407
0
            return NULL;
2408
0
        r2 = PyObject_IsTrue(r1);
2409
0
        Py_DECREF(r1);
2410
0
        if (r2 < 0)
2411
0
            return NULL;
2412
0
        return PyBool_FromLong(!r2);
2413
74
    case Py_LE:
2414
74
        return set_issubset((PyObject*)v, w);
2415
0
    case Py_GE:
2416
0
        return set_issuperset((PyObject*)v, w);
2417
0
    case Py_LT:
2418
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
2419
0
            Py_RETURN_FALSE;
2420
0
        return set_issubset((PyObject*)v, w);
2421
0
    case Py_GT:
2422
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
2423
0
            Py_RETURN_FALSE;
2424
0
        return set_issuperset((PyObject*)v, w);
2425
118
    }
2426
118
    Py_RETURN_NOTIMPLEMENTED;
2427
118
}
2428
2429
/*[clinic input]
2430
@critical_section
2431
set.add
2432
    so: setobject
2433
    object as key: object
2434
    /
2435
2436
Add an element to a set.
2437
2438
This has no effect if the element is already present.
2439
[clinic start generated code]*/
2440
2441
static PyObject *
2442
set_add_impl(PySetObject *so, PyObject *key)
2443
/*[clinic end generated code: output=4cc4a937f1425c96 input=03baf62cb0e66514]*/
2444
7.23M
{
2445
7.23M
    if (set_add_key(so, key))
2446
0
        return NULL;
2447
7.23M
    Py_RETURN_NONE;
2448
7.23M
}
2449
2450
int
2451
_PySet_Contains(PySetObject *so, PyObject *key)
2452
236M
{
2453
236M
    assert(so);
2454
2455
236M
    Py_hash_t hash = _PyObject_HashFast(key);
2456
236M
    if (hash == -1) {
2457
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
2458
0
            set_unhashable_type(key);
2459
0
            return -1;
2460
0
        }
2461
0
        PyErr_Clear();
2462
        // Note that 'key' could be a set() or frozenset() object.  Unlike most
2463
        // container types, set allows membership testing with a set key, even
2464
        // though it is not hashable.
2465
0
        Py_BEGIN_CRITICAL_SECTION(key);
2466
0
        hash = frozenset_hash_impl(key);
2467
0
        Py_END_CRITICAL_SECTION();
2468
0
    }
2469
236M
    return set_contains_entry(so, key, hash);
2470
236M
}
2471
2472
static int
2473
set_contains(PyObject *self, PyObject *key)
2474
604
{
2475
604
    PySetObject *so = _PySet_CAST(self);
2476
604
    return _PySet_Contains(so, key);
2477
604
}
2478
2479
/*[clinic input]
2480
@coexist
2481
set.__contains__
2482
    so: setobject
2483
    object as key: object
2484
    /
2485
2486
x.__contains__(y) <==> y in x.
2487
[clinic start generated code]*/
2488
2489
static PyObject *
2490
set___contains___impl(PySetObject *so, PyObject *key)
2491
/*[clinic end generated code: output=b44863d034b3c70e input=cf4c72db704e4cf0]*/
2492
19.5M
{
2493
19.5M
    long result;
2494
2495
19.5M
    result = _PySet_Contains(so, key);
2496
19.5M
    if (result < 0)
2497
0
        return NULL;
2498
19.5M
    return PyBool_FromLong(result);
2499
19.5M
}
2500
2501
/*[clinic input]
2502
@coexist
2503
frozenset.__contains__
2504
    so: setobject
2505
    object as key: object
2506
    /
2507
2508
x.__contains__(y) <==> y in x.
2509
[clinic start generated code]*/
2510
2511
static PyObject *
2512
frozenset___contains___impl(PySetObject *so, PyObject *key)
2513
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
2514
552
{
2515
552
    Py_hash_t hash = _PyObject_HashFast(key);
2516
552
    if (hash == -1) {
2517
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
2518
0
            set_unhashable_type(key);
2519
0
            return NULL;
2520
0
        }
2521
0
        PyErr_Clear();
2522
0
        Py_BEGIN_CRITICAL_SECTION(key);
2523
0
        hash = frozenset_hash_impl(key);
2524
0
        Py_END_CRITICAL_SECTION();
2525
0
    }
2526
552
    setentry *entry; // unused
2527
552
    int status = set_do_lookup(so, so->table, so->mask, key, hash, &entry,
2528
552
                           set_compare_frozenset);
2529
552
    if (status < 0)
2530
0
        return NULL;
2531
552
    return PyBool_FromLong(status);
2532
552
}
2533
2534
/*[clinic input]
2535
@critical_section
2536
set.remove
2537
    so: setobject
2538
    object as key: object
2539
    /
2540
2541
Remove an element from a set; it must be a member.
2542
2543
If the element is not a member, raise a KeyError.
2544
[clinic start generated code]*/
2545
2546
static PyObject *
2547
set_remove_impl(PySetObject *so, PyObject *key)
2548
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2549
0
{
2550
0
    int rv;
2551
2552
0
    rv = set_discard_key(so, key);
2553
0
    if (rv < 0) {
2554
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2555
0
            return NULL;
2556
0
        PyErr_Clear();
2557
0
        Py_hash_t hash;
2558
0
        Py_BEGIN_CRITICAL_SECTION(key);
2559
0
        hash = frozenset_hash_impl(key);
2560
0
        Py_END_CRITICAL_SECTION();
2561
0
        rv = set_discard_entry(so, key, hash);
2562
0
        if (rv < 0)
2563
0
            return NULL;
2564
0
    }
2565
2566
0
    if (rv == DISCARD_NOTFOUND) {
2567
0
        _PyErr_SetKeyError(key);
2568
0
        return NULL;
2569
0
    }
2570
0
    Py_RETURN_NONE;
2571
0
}
2572
2573
/*[clinic input]
2574
@critical_section
2575
set.discard
2576
    so: setobject
2577
    object as key: object
2578
    /
2579
2580
Remove an element from a set if it is a member.
2581
2582
Unlike set.remove(), the discard() method does not raise
2583
an exception when an element is missing from the set.
2584
[clinic start generated code]*/
2585
2586
static PyObject *
2587
set_discard_impl(PySetObject *so, PyObject *key)
2588
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2589
0
{
2590
0
    int rv;
2591
2592
0
    rv = set_discard_key(so, key);
2593
0
    if (rv < 0) {
2594
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2595
0
            return NULL;
2596
0
        PyErr_Clear();
2597
0
        Py_hash_t hash;
2598
0
        Py_BEGIN_CRITICAL_SECTION(key);
2599
0
        hash = frozenset_hash_impl(key);
2600
0
        Py_END_CRITICAL_SECTION();
2601
0
        rv = set_discard_entry(so, key, hash);
2602
0
        if (rv < 0)
2603
0
            return NULL;
2604
0
    }
2605
0
    Py_RETURN_NONE;
2606
0
}
2607
2608
/*[clinic input]
2609
@critical_section
2610
set.__reduce__
2611
    so: setobject
2612
2613
Return state information for pickling.
2614
[clinic start generated code]*/
2615
2616
static PyObject *
2617
set___reduce___impl(PySetObject *so)
2618
/*[clinic end generated code: output=9af7d0e029df87ee input=59405a4249e82f71]*/
2619
0
{
2620
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
2621
2622
0
    keys = PySequence_List((PyObject *)so);
2623
0
    if (keys == NULL)
2624
0
        goto done;
2625
0
    args = PyTuple_Pack(1, keys);
2626
0
    if (args == NULL)
2627
0
        goto done;
2628
0
    state = _PyObject_GetState((PyObject *)so);
2629
0
    if (state == NULL)
2630
0
        goto done;
2631
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, state);
2632
0
done:
2633
0
    Py_XDECREF(args);
2634
0
    Py_XDECREF(keys);
2635
0
    Py_XDECREF(state);
2636
0
    return result;
2637
0
}
2638
2639
/*[clinic input]
2640
@critical_section
2641
set.__sizeof__
2642
    so: setobject
2643
2644
S.__sizeof__() -> size of S in memory, in bytes.
2645
[clinic start generated code]*/
2646
2647
static PyObject *
2648
set___sizeof___impl(PySetObject *so)
2649
/*[clinic end generated code: output=4bfa3df7bd38ed88 input=09e1a09f168eaa23]*/
2650
0
{
2651
0
    size_t res = _PyObject_SIZE(Py_TYPE(so));
2652
0
    if (so->table != so->smalltable) {
2653
0
        res += ((size_t)so->mask + 1) * sizeof(setentry);
2654
0
    }
2655
0
    return PyLong_FromSize_t(res);
2656
0
}
2657
2658
static int
2659
set_init(PyObject *so, PyObject *args, PyObject *kwds)
2660
0
{
2661
0
    PySetObject *self = _PySet_CAST(so);
2662
0
    PyObject *iterable = NULL;
2663
2664
0
    if (!_PyArg_NoKeywords("set", kwds))
2665
0
        return -1;
2666
0
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
2667
0
        return -1;
2668
2669
0
    if (_PyObject_IsUniquelyReferenced((PyObject *)self) && self->fill == 0) {
2670
0
        self->hash = -1;
2671
0
        if (iterable == NULL) {
2672
0
            return 0;
2673
0
        }
2674
0
        return set_update_local(self, iterable);
2675
0
    }
2676
0
    Py_BEGIN_CRITICAL_SECTION(self);
2677
0
    if (self->fill)
2678
0
        set_clear_internal((PyObject*)self);
2679
0
    self->hash = -1;
2680
0
    Py_END_CRITICAL_SECTION();
2681
2682
0
    if (iterable == NULL)
2683
0
        return 0;
2684
0
    return set_update_internal(self, iterable);
2685
0
}
2686
2687
static PyObject*
2688
set_vectorcall(PyObject *type, PyObject * const*args,
2689
               size_t nargsf, PyObject *kwnames)
2690
3.15M
{
2691
3.15M
    assert(PyType_Check(type));
2692
2693
3.15M
    if (!_PyArg_NoKwnames("set", kwnames)) {
2694
0
        return NULL;
2695
0
    }
2696
2697
3.15M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2698
3.15M
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2699
0
        return NULL;
2700
0
    }
2701
2702
3.15M
    if (nargs) {
2703
15.1k
        return make_new_set(_PyType_CAST(type), args[0]);
2704
15.1k
    }
2705
2706
3.14M
    return make_new_set(_PyType_CAST(type), NULL);
2707
3.15M
}
2708
2709
static PySequenceMethods set_as_sequence = {
2710
    set_len,                            /* sq_length */
2711
    0,                                  /* sq_concat */
2712
    0,                                  /* sq_repeat */
2713
    0,                                  /* sq_item */
2714
    0,                                  /* sq_slice */
2715
    0,                                  /* sq_ass_item */
2716
    0,                                  /* sq_ass_slice */
2717
    set_contains,                       /* sq_contains */
2718
};
2719
2720
/* set object ********************************************************/
2721
2722
static PyMethodDef set_methods[] = {
2723
    SET_ADD_METHODDEF
2724
    SET_CLEAR_METHODDEF
2725
    SET___CONTAINS___METHODDEF
2726
    SET_COPY_METHODDEF
2727
    SET_DISCARD_METHODDEF
2728
    SET_DIFFERENCE_MULTI_METHODDEF
2729
    SET_DIFFERENCE_UPDATE_METHODDEF
2730
    SET_INTERSECTION_MULTI_METHODDEF
2731
    SET_INTERSECTION_UPDATE_MULTI_METHODDEF
2732
    SET_ISDISJOINT_METHODDEF
2733
    SET_ISSUBSET_METHODDEF
2734
    SET_ISSUPERSET_METHODDEF
2735
    SET_POP_METHODDEF
2736
    SET___REDUCE___METHODDEF
2737
    SET_REMOVE_METHODDEF
2738
    SET___SIZEOF___METHODDEF
2739
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2740
    SET_SYMMETRIC_DIFFERENCE_UPDATE_METHODDEF
2741
    SET_UNION_METHODDEF
2742
    SET_UPDATE_METHODDEF
2743
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2744
    {NULL,              NULL}   /* sentinel */
2745
};
2746
2747
static PyNumberMethods set_as_number = {
2748
    0,                                  /*nb_add*/
2749
    set_sub,                            /*nb_subtract*/
2750
    0,                                  /*nb_multiply*/
2751
    0,                                  /*nb_remainder*/
2752
    0,                                  /*nb_divmod*/
2753
    0,                                  /*nb_power*/
2754
    0,                                  /*nb_negative*/
2755
    0,                                  /*nb_positive*/
2756
    0,                                  /*nb_absolute*/
2757
    0,                                  /*nb_bool*/
2758
    0,                                  /*nb_invert*/
2759
    0,                                  /*nb_lshift*/
2760
    0,                                  /*nb_rshift*/
2761
    set_and,                            /*nb_and*/
2762
    set_xor,                            /*nb_xor*/
2763
    set_or,                             /*nb_or*/
2764
    0,                                  /*nb_int*/
2765
    0,                                  /*nb_reserved*/
2766
    0,                                  /*nb_float*/
2767
    0,                                  /*nb_inplace_add*/
2768
    set_isub,                           /*nb_inplace_subtract*/
2769
    0,                                  /*nb_inplace_multiply*/
2770
    0,                                  /*nb_inplace_remainder*/
2771
    0,                                  /*nb_inplace_power*/
2772
    0,                                  /*nb_inplace_lshift*/
2773
    0,                                  /*nb_inplace_rshift*/
2774
    set_iand,                           /*nb_inplace_and*/
2775
    set_ixor,                           /*nb_inplace_xor*/
2776
    set_ior,                            /*nb_inplace_or*/
2777
};
2778
2779
PyDoc_STRVAR(set_doc,
2780
"set(iterable=(), /)\n\
2781
--\n\
2782
\n\
2783
Build an unordered collection of unique elements.");
2784
2785
PyTypeObject PySet_Type = {
2786
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2787
    "set",                              /* tp_name */
2788
    sizeof(PySetObject),                /* tp_basicsize */
2789
    0,                                  /* tp_itemsize */
2790
    /* methods */
2791
    set_dealloc,                        /* tp_dealloc */
2792
    0,                                  /* tp_vectorcall_offset */
2793
    0,                                  /* tp_getattr */
2794
    0,                                  /* tp_setattr */
2795
    0,                                  /* tp_as_async */
2796
    set_repr,                           /* tp_repr */
2797
    &set_as_number,                     /* tp_as_number */
2798
    &set_as_sequence,                   /* tp_as_sequence */
2799
    0,                                  /* tp_as_mapping */
2800
    PyObject_HashNotImplemented,        /* tp_hash */
2801
    0,                                  /* tp_call */
2802
    0,                                  /* tp_str */
2803
    PyObject_GenericGetAttr,            /* tp_getattro */
2804
    0,                                  /* tp_setattro */
2805
    0,                                  /* tp_as_buffer */
2806
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2807
        Py_TPFLAGS_BASETYPE |
2808
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2809
    set_doc,                            /* tp_doc */
2810
    set_traverse,                       /* tp_traverse */
2811
    set_clear_internal,                 /* tp_clear */
2812
    set_richcompare,                    /* tp_richcompare */
2813
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2814
    set_iter,                           /* tp_iter */
2815
    0,                                  /* tp_iternext */
2816
    set_methods,                        /* tp_methods */
2817
    0,                                  /* tp_members */
2818
    0,                                  /* tp_getset */
2819
    0,                                  /* tp_base */
2820
    0,                                  /* tp_dict */
2821
    0,                                  /* tp_descr_get */
2822
    0,                                  /* tp_descr_set */
2823
    0,                                  /* tp_dictoffset */
2824
    set_init,                           /* tp_init */
2825
    PyType_GenericAlloc,                /* tp_alloc */
2826
    set_new,                            /* tp_new */
2827
    PyObject_GC_Del,                    /* tp_free */
2828
    .tp_vectorcall = set_vectorcall,
2829
    .tp_version_tag = _Py_TYPE_VERSION_SET,
2830
};
2831
2832
/* frozenset object ********************************************************/
2833
2834
2835
static PyMethodDef frozenset_methods[] = {
2836
    FROZENSET___CONTAINS___METHODDEF
2837
    FROZENSET_COPY_METHODDEF
2838
    SET_DIFFERENCE_MULTI_METHODDEF
2839
    SET_INTERSECTION_MULTI_METHODDEF
2840
    SET_ISDISJOINT_METHODDEF
2841
    SET_ISSUBSET_METHODDEF
2842
    SET_ISSUPERSET_METHODDEF
2843
    SET___REDUCE___METHODDEF
2844
    SET___SIZEOF___METHODDEF
2845
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2846
    SET_UNION_METHODDEF
2847
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2848
    {NULL,              NULL}   /* sentinel */
2849
};
2850
2851
static PyNumberMethods frozenset_as_number = {
2852
    0,                                  /*nb_add*/
2853
    set_sub,                            /*nb_subtract*/
2854
    0,                                  /*nb_multiply*/
2855
    0,                                  /*nb_remainder*/
2856
    0,                                  /*nb_divmod*/
2857
    0,                                  /*nb_power*/
2858
    0,                                  /*nb_negative*/
2859
    0,                                  /*nb_positive*/
2860
    0,                                  /*nb_absolute*/
2861
    0,                                  /*nb_bool*/
2862
    0,                                  /*nb_invert*/
2863
    0,                                  /*nb_lshift*/
2864
    0,                                  /*nb_rshift*/
2865
    set_and,                            /*nb_and*/
2866
    set_xor,                            /*nb_xor*/
2867
    set_or,                             /*nb_or*/
2868
};
2869
2870
PyDoc_STRVAR(frozenset_doc,
2871
"frozenset(iterable=(), /)\n\
2872
--\n\
2873
\n\
2874
Build an immutable unordered collection of unique elements.");
2875
2876
PyTypeObject PyFrozenSet_Type = {
2877
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2878
    "frozenset",                        /* tp_name */
2879
    sizeof(PySetObject),                /* tp_basicsize */
2880
    0,                                  /* tp_itemsize */
2881
    /* methods */
2882
    set_dealloc,                        /* tp_dealloc */
2883
    0,                                  /* tp_vectorcall_offset */
2884
    0,                                  /* tp_getattr */
2885
    0,                                  /* tp_setattr */
2886
    0,                                  /* tp_as_async */
2887
    set_repr,                           /* tp_repr */
2888
    &frozenset_as_number,               /* tp_as_number */
2889
    &set_as_sequence,                   /* tp_as_sequence */
2890
    0,                                  /* tp_as_mapping */
2891
    frozenset_hash,                     /* tp_hash */
2892
    0,                                  /* tp_call */
2893
    0,                                  /* tp_str */
2894
    PyObject_GenericGetAttr,            /* tp_getattro */
2895
    0,                                  /* tp_setattro */
2896
    0,                                  /* tp_as_buffer */
2897
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2898
        Py_TPFLAGS_BASETYPE |
2899
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2900
    frozenset_doc,                      /* tp_doc */
2901
    set_traverse,                       /* tp_traverse */
2902
    set_clear_internal,                 /* tp_clear */
2903
    set_richcompare,                    /* tp_richcompare */
2904
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2905
    set_iter,                           /* tp_iter */
2906
    0,                                  /* tp_iternext */
2907
    frozenset_methods,                  /* tp_methods */
2908
    0,                                  /* tp_members */
2909
    0,                                  /* tp_getset */
2910
    0,                                  /* tp_base */
2911
    0,                                  /* tp_dict */
2912
    0,                                  /* tp_descr_get */
2913
    0,                                  /* tp_descr_set */
2914
    0,                                  /* tp_dictoffset */
2915
    0,                                  /* tp_init */
2916
    PyType_GenericAlloc,                /* tp_alloc */
2917
    frozenset_new,                      /* tp_new */
2918
    PyObject_GC_Del,                    /* tp_free */
2919
    .tp_vectorcall = frozenset_vectorcall,
2920
    .tp_version_tag = _Py_TYPE_VERSION_FROZEN_SET,
2921
};
2922
2923
2924
/***** C API functions *************************************************/
2925
2926
PyObject *
2927
PySet_New(PyObject *iterable)
2928
132k
{
2929
132k
    return make_new_set(&PySet_Type, iterable);
2930
132k
}
2931
2932
PyObject *
2933
PyFrozenSet_New(PyObject *iterable)
2934
2.97k
{
2935
2.97k
    return make_new_set(&PyFrozenSet_Type, iterable);
2936
2.97k
}
2937
2938
Py_ssize_t
2939
PySet_Size(PyObject *anyset)
2940
144
{
2941
144
    if (!PyAnySet_Check(anyset)) {
2942
0
        PyErr_BadInternalCall();
2943
0
        return -1;
2944
0
    }
2945
144
    return set_len(anyset);
2946
144
}
2947
2948
int
2949
PySet_Clear(PyObject *set)
2950
333
{
2951
333
    if (!PySet_Check(set)) {
2952
0
        PyErr_BadInternalCall();
2953
0
        return -1;
2954
0
    }
2955
333
    (void)set_clear(set, NULL);
2956
333
    return 0;
2957
333
}
2958
2959
void
2960
_PySet_ClearInternal(PySetObject *so)
2961
0
{
2962
0
    (void)set_clear_internal((PyObject*)so);
2963
0
}
2964
2965
int
2966
PySet_Contains(PyObject *anyset, PyObject *key)
2967
185k
{
2968
185k
    if (!PyAnySet_Check(anyset)) {
2969
0
        PyErr_BadInternalCall();
2970
0
        return -1;
2971
0
    }
2972
185k
    if (PyFrozenSet_CheckExact(anyset)) {
2973
0
        return set_contains_key((PySetObject *)anyset, key);
2974
0
    }
2975
185k
    int rv;
2976
185k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2977
185k
    rv = set_contains_key((PySetObject *)anyset, key);
2978
185k
    Py_END_CRITICAL_SECTION();
2979
185k
    return rv;
2980
185k
}
2981
2982
int
2983
PySet_Discard(PyObject *set, PyObject *key)
2984
86.7k
{
2985
86.7k
    if (!PySet_Check(set)) {
2986
0
        PyErr_BadInternalCall();
2987
0
        return -1;
2988
0
    }
2989
2990
86.7k
    int rv;
2991
86.7k
    Py_BEGIN_CRITICAL_SECTION(set);
2992
86.7k
    rv = set_discard_key((PySetObject *)set, key);
2993
86.7k
    Py_END_CRITICAL_SECTION();
2994
86.7k
    return rv;
2995
86.7k
}
2996
2997
int
2998
PySet_Add(PyObject *anyset, PyObject *key)
2999
57.5k
{
3000
57.5k
    if (PySet_Check(anyset)) {
3001
54.9k
        int rv;
3002
54.9k
        Py_BEGIN_CRITICAL_SECTION(anyset);
3003
54.9k
        rv = set_add_key((PySetObject *)anyset, key);
3004
54.9k
        Py_END_CRITICAL_SECTION();
3005
54.9k
        return rv;
3006
54.9k
    }
3007
3008
2.55k
    if (PyFrozenSet_Check(anyset) && _PyObject_IsUniquelyReferenced(anyset)) {
3009
        // We can only change frozensets if they are uniquely referenced. The
3010
        // API limits the usage of `PySet_Add` to "fill in the values of brand
3011
        // new frozensets before they are exposed to other code". In this case,
3012
        // this can be done without a lock.
3013
2.55k
        return set_add_key((PySetObject *)anyset, key);
3014
2.55k
    }
3015
3016
0
    PyErr_BadInternalCall();
3017
0
    return -1;
3018
2.55k
}
3019
3020
int
3021
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
3022
1.91k
{
3023
1.91k
    setentry *entry;
3024
3025
1.91k
    if (!PyAnySet_Check(set)) {
3026
0
        PyErr_BadInternalCall();
3027
0
        return -1;
3028
0
    }
3029
1.91k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
3030
477
        return 0;
3031
1.43k
    *key = entry->key;
3032
1.43k
    *hash = entry->hash;
3033
1.43k
    return 1;
3034
1.91k
}
3035
3036
int
3037
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
3038
105k
{
3039
105k
    setentry *entry;
3040
3041
105k
    if (!PyAnySet_Check(set)) {
3042
0
        PyErr_BadInternalCall();
3043
0
        return -1;
3044
0
    }
3045
105k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
3046
105k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
3047
19.0k
        return 0;
3048
86.2k
    *key = Py_NewRef(entry->key);
3049
86.2k
    *hash = entry->hash;
3050
86.2k
    return 1;
3051
105k
}
3052
3053
PyObject *
3054
PySet_Pop(PyObject *set)
3055
23
{
3056
23
    if (!PySet_Check(set)) {
3057
0
        PyErr_BadInternalCall();
3058
0
        return NULL;
3059
0
    }
3060
23
    return set_pop(set, NULL);
3061
23
}
3062
3063
int
3064
_PySet_Update(PyObject *set, PyObject *iterable)
3065
36
{
3066
36
    if (!PySet_Check(set)) {
3067
0
        PyErr_BadInternalCall();
3068
0
        return -1;
3069
0
    }
3070
36
    return set_update_internal((PySetObject *)set, iterable);
3071
36
}
3072
3073
/* Exported for the gdb plugin's benefit. */
3074
PyObject *_PySet_Dummy = dummy;
3075
3076
/***** Dummy Struct  *************************************************/
3077
3078
static PyObject *
3079
dummy_repr(PyObject *op)
3080
0
{
3081
0
    return PyUnicode_FromString("<dummy key>");
3082
0
}
3083
3084
static void _Py_NO_RETURN
3085
dummy_dealloc(PyObject* ignore)
3086
0
{
3087
0
    Py_FatalError("deallocating <dummy key>");
3088
0
}
3089
3090
static PyTypeObject _PySetDummy_Type = {
3091
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3092
    "<dummy key> type",
3093
    0,
3094
    0,
3095
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
3096
    0,                  /*tp_vectorcall_offset*/
3097
    0,                  /*tp_getattr*/
3098
    0,                  /*tp_setattr*/
3099
    0,                  /*tp_as_async*/
3100
    dummy_repr,         /*tp_repr*/
3101
    0,                  /*tp_as_number*/
3102
    0,                  /*tp_as_sequence*/
3103
    0,                  /*tp_as_mapping*/
3104
    0,                  /*tp_hash */
3105
    0,                  /*tp_call */
3106
    0,                  /*tp_str */
3107
    0,                  /*tp_getattro */
3108
    0,                  /*tp_setattro */
3109
    0,                  /*tp_as_buffer */
3110
    Py_TPFLAGS_DEFAULT, /*tp_flags */
3111
};
3112
3113
static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type);