Coverage Report

Created: 2025-08-24 06:48

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