Coverage Report

Created: 2025-12-14 07:06

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