diff options
Diffstat (limited to 'Objects/setobject.c')
| -rw-r--r-- | Objects/setobject.c | 447 | 
1 files changed, 199 insertions, 248 deletions
| diff --git a/Objects/setobject.c b/Objects/setobject.c index 61f1d94e46..4ef692db33 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -20,7 +20,7 @@     All arithmetic on hash should ignore overflow. -   Unlike the dictionary implementation, the lookkey functions can return +   Unlike the dictionary implementation, the lookkey function can return     NULL if the rich comparison returns an error.  */ @@ -53,120 +53,73 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)      setentry *entry;      size_t perturb = hash;      size_t mask = so->mask; -    size_t i = (size_t)hash; /* Unsigned for defined overflow behavior. */ +    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */      size_t j;      int cmp; -    entry = &table[i & mask]; +    entry = &table[i];      if (entry->key == NULL)          return entry;      while (1) { -        if (entry->key == key) -            return entry; -        if (entry->hash == hash && entry->key != dummy) { +        if (entry->hash == hash) {              PyObject *startkey = entry->key; +            /* startkey cannot be a dummy because the dummy hash field is -1 */ +            assert(startkey != dummy); +            if (startkey == key) +                return entry; +            if (PyUnicode_CheckExact(startkey) +                && PyUnicode_CheckExact(key) +                && unicode_eq(startkey, key)) +                return entry;              Py_INCREF(startkey);              cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);              Py_DECREF(startkey); -            if (cmp < 0) +            if (cmp < 0)                                          /* unlikely */                  return NULL; -            if (table != so->table || entry->key != startkey) +            if (table != so->table || entry->key != startkey)     /* unlikely */                  return set_lookkey(so, key, hash); -            if (cmp > 0) +            if (cmp > 0)                                          /* likely */                  return entry; +            mask = so->mask;                 /* help avoid a register spill */          } -        if (entry->key == dummy && freeslot == NULL) +        if (entry->hash == -1 && freeslot == NULL)              freeslot = entry; -        for (j = 1 ; j <= LINEAR_PROBES ; j++) { -            entry = &table[(i + j) & mask]; -            if (entry->key == NULL) -                goto found_null; -            if (entry->key == key) -                return entry; -            if (entry->hash == hash && entry->key != dummy) { -                PyObject *startkey = entry->key; -                Py_INCREF(startkey); -                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); -                Py_DECREF(startkey); -                if (cmp < 0) -                    return NULL; -                if (table != so->table || entry->key != startkey) -                    return set_lookkey(so, key, hash); -                if (cmp > 0) -                    return entry; +        if (i + LINEAR_PROBES <= mask) { +            for (j = 0 ; j < LINEAR_PROBES ; j++) { +                entry++; +                if (entry->key == NULL) +                    goto found_null; +                if (entry->hash == hash) { +                    PyObject *startkey = entry->key; +                    assert(startkey != dummy); +                    if (startkey == key) +                        return entry; +                    if (PyUnicode_CheckExact(startkey) +                        && PyUnicode_CheckExact(key) +                        && unicode_eq(startkey, key)) +                        return entry; +                    Py_INCREF(startkey); +                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); +                    Py_DECREF(startkey); +                    if (cmp < 0) +                        return NULL; +                    if (table != so->table || entry->key != startkey) +                        return set_lookkey(so, key, hash); +                    if (cmp > 0) +                        return entry; +                    mask = so->mask; +                } +                if (entry->hash == -1 && freeslot == NULL) +                    freeslot = entry;              } -            if (entry->key == dummy && freeslot == NULL) -                freeslot = entry;          }          perturb >>= PERTURB_SHIFT; -        i = i * 5 + 1 + perturb; +        i = (i * 5 + 1 + perturb) & mask; -        entry = &table[i & mask]; -        if (entry->key == NULL) -            goto found_null; -    } -  found_null: -    return freeslot == NULL ? entry : freeslot; -} - -/* - * Hacked up version of set_lookkey which can assume keys are always unicode; - * This means we can always use unicode_eq directly and not have to check to - * see if the comparison altered the table. - */ -static setentry * -set_lookkey_unicode(PySetObject *so, PyObject *key, Py_hash_t hash) -{ -    setentry *table = so->table; -    setentry *freeslot = NULL; -    setentry *entry; -    size_t perturb = hash; -    size_t mask = so->mask; -    size_t i = (size_t)hash; -    size_t j; - -    /* Make sure this function doesn't have to handle non-unicode keys, -       including subclasses of str; e.g., one reason to subclass -       strings is to override __eq__, and for speed we don't cater to -       that here. */ -    if (!PyUnicode_CheckExact(key)) { -        so->lookup = set_lookkey; -        return set_lookkey(so, key, hash); -    } - -    entry = &table[i & mask]; -    if (entry->key == NULL) -        return entry; - -    while (1) { -        if (entry->key == key -            || (entry->hash == hash -                && entry->key != dummy -                && unicode_eq(entry->key, key))) -            return entry; -        if (entry->key == dummy && freeslot == NULL) -            freeslot = entry; - -        for (j = 1 ; j <= LINEAR_PROBES ; j++) { -            entry = &table[(i + j) & mask]; -            if (entry->key == NULL) -                goto found_null; -            if (entry->key == key -                || (entry->hash == hash -                    && entry->key != dummy -                    && unicode_eq(entry->key, key))) -                return entry; -            if (entry->key == dummy && freeslot == NULL) -                freeslot = entry; -        } - -        perturb >>= PERTURB_SHIFT; -        i = i * 5 + 1 + perturb; - -        entry = &table[i & mask]; +        entry = &table[i];          if (entry->key == NULL)              goto found_null;      } @@ -189,20 +142,22 @@ set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)      setentry *entry;      size_t perturb = hash;      size_t mask = (size_t)so->mask; -    size_t i = (size_t)hash; +    size_t i = (size_t)hash & mask;      size_t j;      while (1) { -        entry = &table[i & mask]; +        entry = &table[i];          if (entry->key == NULL)              goto found_null; -        for (j = 1 ; j <= LINEAR_PROBES ; j++) { -            entry = &table[(i + j) & mask]; -            if (entry->key == NULL) -                goto found_null; +        if (i + LINEAR_PROBES <= mask) { +            for (j = 0; j < LINEAR_PROBES; j++) { +                entry++; +                if (entry->key == NULL) +                    goto found_null; +            }          }          perturb >>= PERTURB_SHIFT; -        i = i * 5 + 1 + perturb; +        i = (i * 5 + 1 + perturb) & mask;      }    found_null:      entry->key = key; @@ -225,15 +180,14 @@ set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash)  {      setentry *entry; -    assert(so->lookup != NULL); -    entry = so->lookup(so, key, hash); +    entry = set_lookkey(so, key, hash);      if (entry == NULL)          return -1;      if (entry->key == NULL) {          /* UNUSED */ -        so->fill++;          entry->key = key;          entry->hash = hash; +        so->fill++;          so->used++;      } else if (entry->key == dummy) {          /* DUMMY */ @@ -257,13 +211,15 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)  {      Py_ssize_t newsize;      setentry *oldtable, *newtable, *entry; -    Py_ssize_t i; +    Py_ssize_t oldfill = so->fill; +    Py_ssize_t oldused = so->used;      int is_oldtable_malloced;      setentry small_copy[PySet_MINSIZE];      assert(minused >= 0);      /* Find the smallest table size > minused. */ +    /* XXX speed-up with intrinsics */      for (newsize = PySet_MINSIZE;           newsize <= minused && newsize > 0;           newsize <<= 1) @@ -307,19 +263,27 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)      /* Make the set empty, using the new table. */      assert(newtable != oldtable); -    so->table = newtable; -    so->mask = newsize - 1;      memset(newtable, 0, sizeof(setentry) * newsize); -    i = so->used; -    so->used = 0;      so->fill = 0; +    so->used = 0; +    so->mask = newsize - 1; +    so->table = newtable;      /* Copy the data over; this is refcount-neutral for active entries;         dummy entries aren't copied over, of course */ -    for (entry = oldtable; i > 0; entry++) { -        if (entry->key != NULL && entry->key != dummy) { -            --i; -            set_insert_clean(so, entry->key, entry->hash); +    if (oldfill == oldused) { +        for (entry = oldtable; oldused > 0; entry++) { +            if (entry->key != NULL) { +                oldused--; +                set_insert_clean(so, entry->key, entry->hash); +            } +        } +    } else { +        for (entry = oldtable; oldused > 0; entry++) { +            if (entry->key != NULL && entry->key != dummy) { +                oldused--; +                set_insert_clean(so, entry->key, entry->hash); +            }          }      } @@ -340,7 +304,7 @@ set_add_entry(PySetObject *so, setentry *entry)      assert(so->fill <= so->mask);  /* at least one empty slot */      n_used = so->used;      Py_INCREF(key); -    if (set_insert_key(so, key, hash) == -1) { +    if (set_insert_key(so, key, hash)) {          Py_DECREF(key);          return -1;      } @@ -352,8 +316,8 @@ set_add_entry(PySetObject *so, setentry *entry)  static int  set_add_key(PySetObject *so, PyObject *key)  { +    setentry entry;      Py_hash_t hash; -    Py_ssize_t n_used;      if (!PyUnicode_CheckExact(key) ||          (hash = ((PyASCIIObject *) key)->hash) == -1) { @@ -361,16 +325,9 @@ set_add_key(PySetObject *so, PyObject *key)          if (hash == -1)              return -1;      } -    assert(so->fill <= so->mask);  /* at least one empty slot */ -    n_used = so->used; -    Py_INCREF(key); -    if (set_insert_key(so, key, hash) == -1) { -        Py_DECREF(key); -        return -1; -    } -    if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) -        return 0; -    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); +    entry.key = key; +    entry.hash = hash; +    return set_add_entry(so, &entry);  }  #define DISCARD_NOTFOUND 0 @@ -378,16 +335,18 @@ set_add_key(PySetObject *so, PyObject *key)  static int  set_discard_entry(PySetObject *so, setentry *oldentry) -{       setentry *entry; +{ +    setentry *entry;      PyObject *old_key; -    entry = (so->lookup)(so, oldentry->key, oldentry->hash); +    entry = set_lookkey(so, oldentry->key, oldentry->hash);      if (entry == NULL)          return -1;      if (entry->key == NULL  ||  entry->key == dummy)          return DISCARD_NOTFOUND;      old_key = entry->key;      entry->key = dummy; +    entry->hash = -1;      so->used--;      Py_DECREF(old_key);      return DISCARD_FOUND; @@ -396,9 +355,8 @@ set_discard_entry(PySetObject *so, setentry *oldentry)  static int  set_discard_key(PySetObject *so, PyObject *key)  { +    setentry entry;      Py_hash_t hash; -    setentry *entry; -    PyObject *old_key;      assert (PyAnySet_Check(so)); @@ -408,16 +366,9 @@ set_discard_key(PySetObject *so, PyObject *key)          if (hash == -1)              return -1;      } -    entry = (so->lookup)(so, key, hash); -    if (entry == NULL) -        return -1; -    if (entry->key == NULL  ||  entry->key == dummy) -        return DISCARD_NOTFOUND; -    old_key = entry->key; -    entry->key = dummy; -    so->used--; -    Py_DECREF(old_key); -    return DISCARD_FOUND; +    entry.key = key; +    entry.hash = hash; +    return set_discard_entry(so, &entry);  }  static void @@ -434,20 +385,15 @@ set_empty_to_minsize(PySetObject *so)  static int  set_clear_internal(PySetObject *so)  { -    setentry *entry, *table; -    int table_is_malloced; -    Py_ssize_t fill; +    setentry *entry; +    setentry *table = so->table; +    Py_ssize_t fill = so->fill; +    Py_ssize_t used = so->used; +    int table_is_malloced = table != so->smalltable;      setentry small_copy[PySet_MINSIZE]; -#ifdef Py_DEBUG -    Py_ssize_t i = 0; -    Py_ssize_t n = so->mask + 1; -#endif -      assert (PyAnySet_Check(so)); -    table = so->table;      assert(table != NULL); -    table_is_malloced = table != so->smalltable;      /* This is delicate.  During the process of clearing the set,       * decrefs can cause the set to mutate.  To avoid fatal confusion @@ -455,7 +401,6 @@ set_clear_internal(PySetObject *so)       * clearing the slots, and never refer to anything via so->ref while       * clearing.       */ -    fill = so->fill;      if (table_is_malloced)          set_empty_to_minsize(so); @@ -474,20 +419,11 @@ set_clear_internal(PySetObject *so)       * assert that the refcount on table is 1 now, i.e. that this function       * has unique access to it, so decref side-effects can't alter it.       */ -    for (entry = table; fill > 0; ++entry) { -#ifdef Py_DEBUG -        assert(i < n); -        ++i; -#endif -        if (entry->key) { -            --fill; -            if (entry->key != dummy) -                Py_DECREF(entry->key); +    for (entry = table; used > 0; entry++) { +        if (entry->key && entry->key != dummy) { +            used--; +            Py_DECREF(entry->key);          } -#ifdef Py_DEBUG -        else -            assert(entry->key == NULL); -#endif      }      if (table_is_malloced) @@ -534,16 +470,16 @@ static void  set_dealloc(PySetObject *so)  {      setentry *entry; -    Py_ssize_t fill = so->fill; +    Py_ssize_t used = so->used; +      PyObject_GC_UnTrack(so);      Py_TRASHCAN_SAFE_BEGIN(so)      if (so->weakreflist != NULL)          PyObject_ClearWeakRefs((PyObject *) so); -    for (entry = so->table; fill > 0; entry++) { -        if (entry->key) { -            --fill; -            if (entry->key != dummy) +    for (entry = so->table; used > 0; entry++) { +        if (entry->key && entry->key != dummy) { +                used--;                  Py_DECREF(entry->key);          }      } @@ -609,16 +545,16 @@ set_merge(PySetObject *so, PyObject *otherset)  {      PySetObject *other;      PyObject *key; -    Py_hash_t hash;      Py_ssize_t i; -    setentry *entry; +    setentry *so_entry; +    setentry *other_entry;      assert (PyAnySet_Check(so));      assert (PyAnySet_Check(otherset));      other = (PySetObject*)otherset;      if (other == so || other->used == 0) -        /* a.update(a) or a.update({}); nothing to do */ +        /* a.update(a) or a.update(set()); nothing to do */          return 0;      /* Do one big resize at the start, rather than       * incrementally resizing as we insert new keys.  Expect @@ -628,14 +564,45 @@ set_merge(PySetObject *so, PyObject *otherset)         if (set_table_resize(so, (so->used + other->used)*2) != 0)             return -1;      } +    so_entry = so->table; +    other_entry = other->table; + +    /* If our table is empty, and both tables have the same size, and +       there are no dummies to eliminate, then just copy the pointers. */ +    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) { +        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) { +            key = other_entry->key; +            if (key != NULL) { +                assert(so_entry->key == NULL); +                Py_INCREF(key); +                so_entry->key = key; +                so_entry->hash = other_entry->hash; +            } +        } +        so->fill = other->fill; +        so->used = other->used; +        return 0; +    } + +    /* If our table is empty, we can use set_insert_clean() */ +    if (so->fill == 0) { +        for (i = 0; i <= other->mask; i++, other_entry++) { +            key = other_entry->key; +            if (key != NULL && key != dummy) { +                Py_INCREF(key); +                set_insert_clean(so, key, other_entry->hash); +            } +        } +        return 0; +    } + +    /* We can't assure there are no duplicates, so do normal insertions */      for (i = 0; i <= other->mask; i++) { -        entry = &other->table[i]; -        key = entry->key; -        hash = entry->hash; -        if (key != NULL && -            key != dummy) { +        other_entry = &other->table[i]; +        key = other_entry->key; +        if (key != NULL && key != dummy) {              Py_INCREF(key); -            if (set_insert_key(so, key, hash) == -1) { +            if (set_insert_key(so, key, other_entry->hash)) {                  Py_DECREF(key);                  return -1;              } @@ -645,10 +612,23 @@ set_merge(PySetObject *so, PyObject *otherset)  }  static int +set_contains_entry(PySetObject *so, setentry *entry) +{ +    PyObject *key; +    setentry *lu_entry; + +    lu_entry = set_lookkey(so, entry->key, entry->hash); +    if (lu_entry == NULL) +        return -1; +    key = lu_entry->key; +    return key != NULL && key != dummy; +} + +static int  set_contains_key(PySetObject *so, PyObject *key)  { +    setentry entry;      Py_hash_t hash; -    setentry *entry;      if (!PyUnicode_CheckExact(key) ||          (hash = ((PyASCIIObject *) key)->hash) == -1) { @@ -656,30 +636,16 @@ set_contains_key(PySetObject *so, PyObject *key)          if (hash == -1)              return -1;      } -    entry = (so->lookup)(so, key, hash); -    if (entry == NULL) -        return -1; -    key = entry->key; -    return key != NULL && key != dummy; -} - -static int -set_contains_entry(PySetObject *so, setentry *entry) -{ -    PyObject *key; -    setentry *lu_entry; - -    lu_entry = (so->lookup)(so, entry->key, entry->hash); -    if (lu_entry == NULL) -        return -1; -    key = lu_entry->key; -    return key != NULL && key != dummy; +    entry.key = key; +    entry.hash = hash; +    return set_contains_entry(so, &entry);  }  static PyObject *  set_pop(PySetObject *so)  { -    Py_ssize_t i = 0; +    /* Make sure the search finger is in bounds */ +    Py_ssize_t i = so->finger & so->mask;      setentry *entry;      PyObject *key; @@ -689,32 +655,16 @@ set_pop(PySetObject *so)          return NULL;      } -    /* Set entry to "the first" unused or dummy set entry.  We abuse -     * the hash field of slot 0 to hold a search finger: -     * If slot 0 has a value, use slot 0. -     * Else slot 0 is being used to hold a search finger, -     * and we use its hash value as the first index to look. -     */ -    entry = &so->table[0]; -    if (entry->key == NULL || entry->key == dummy) { -        i = entry->hash; -        /* The hash field may be a real hash value, or it may be a -         * legit search finger, or it may be a once-legit search -         * finger that's out of bounds now because it wrapped around -         * or the table shrunk -- simply make sure it's in bounds now. -         */ -        if (i > so->mask || i < 1) -            i = 1;              /* skip slot 0 */ -        while ((entry = &so->table[i])->key == NULL || entry->key==dummy) { -            i++; -            if (i > so->mask) -                i = 1; -        } +    while ((entry = &so->table[i])->key == NULL || entry->key==dummy) { +        i++; +        if (i > so->mask) +            i = 0;      }      key = entry->key;      entry->key = dummy; +    entry->hash = -1;      so->used--; -    so->table[0].hash = i + 1;  /* next place to start */ +    so->finger = i + 1;         /* next place to start */      return key;  } @@ -757,7 +707,7 @@ frozenset_hash(PyObject *self)      hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1;      while (set_next(so, &pos, &entry)) {          /* Work to increase the bit dispersion for closely spaced hash -           values.  The is important because some use cases have many +           values.  This is important because some use cases have many             combinations of a small number of elements with nearby             hashes so that many distinct combinations collapse to only             a handful of distinct hash values. */ @@ -767,7 +717,7 @@ frozenset_hash(PyObject *self)      /* Make the final result spread-out in a different pattern         than the algorithm for tuples or other python objects. */      hash = hash * 69069U + 907133923UL; -    if (hash == -1) +    if (hash == (Py_uhash_t)-1)          hash = 590923713UL;      so->hash = hash;      return hash; @@ -889,8 +839,8 @@ static PyObject *setiter_iternext(setiterobject *si)      return key;  fail: -    Py_DECREF(so);      si->si_set = NULL; +    Py_DECREF(so);      return NULL;  } @@ -971,7 +921,7 @@ set_update_internal(PySetObject *so, PyObject *other)              an_entry.hash = hash;              an_entry.key = key; -            if (set_add_entry(so, &an_entry) == -1) +            if (set_add_entry(so, &an_entry))                  return -1;          }          return 0; @@ -982,7 +932,7 @@ set_update_internal(PySetObject *so, PyObject *other)          return -1;      while ((key = PyIter_Next(it)) != NULL) { -        if (set_add_key(so, key) == -1) { +        if (set_add_key(so, key)) {              Py_DECREF(it);              Py_DECREF(key);              return -1; @@ -1002,7 +952,7 @@ set_update(PySetObject *so, PyObject *args)      for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {          PyObject *other = PyTuple_GET_ITEM(args, i); -        if (set_update_internal(so, other) == -1) +        if (set_update_internal(so, other))              return NULL;      }      Py_RETURN_NONE; @@ -1011,6 +961,12 @@ set_update(PySetObject *so, PyObject *args)  PyDoc_STRVAR(update_doc,  "Update a set with the union of itself and others."); +/* XXX Todo: +   If aligned memory allocations become available, make the +   set object 64 byte aligned so that most of the fields +   can be retrieved or updated in a single cache line. +*/ +  static PyObject *  make_new_set(PyTypeObject *type, PyObject *iterable)  { @@ -1025,12 +981,12 @@ make_new_set(PyTypeObject *type, PyObject *iterable)      so->used = 0;      so->mask = PySet_MINSIZE - 1;      so->table = so->smalltable; -    so->lookup = set_lookkey_unicode;      so->hash = -1; +    so->finger = 0;      so->weakreflist = NULL;      if (iterable != NULL) { -        if (set_update_internal(so, iterable) == -1) { +        if (set_update_internal(so, iterable)) {              Py_DECREF(so);              return NULL;          } @@ -1114,10 +1070,8 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)       t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t     The function always succeeds and it leaves both objects in a stable state. -   Useful for creating temporary frozensets from sets for membership testing -   in __contains__(), discard(), and remove().  Also useful for operations -   that update in-place (by allowing an intermediate result to be swapped -   into one of the original inputs). +   Useful for operations that update in-place (by allowing an intermediate +   result to be swapped into one of the original inputs).  */  static void @@ -1125,7 +1079,6 @@ set_swap_bodies(PySetObject *a, PySetObject *b)  {      Py_ssize_t t;      setentry *u; -    setentry *(*f)(PySetObject *so, PyObject *key, Py_ssize_t hash);      setentry tab[PySet_MINSIZE];      Py_hash_t h; @@ -1141,8 +1094,6 @@ set_swap_bodies(PySetObject *a, PySetObject *b)          a->table = a->smalltable;      b->table = u; -    f = a->lookup;   a->lookup = b->lookup;      b->lookup = f; -      if (a->table == a->smalltable || b->table == b->smalltable) {          memcpy(tab, a->smalltable, sizeof(tab));          memcpy(a->smalltable, b->smalltable, sizeof(tab)); @@ -1200,7 +1151,7 @@ set_union(PySetObject *so, PyObject *args)          other = PyTuple_GET_ITEM(args, i);          if ((PyObject *)so == other)              continue; -        if (set_update_internal(result, other) == -1) { +        if (set_update_internal(result, other)) {              Py_DECREF(result);              return NULL;          } @@ -1226,7 +1177,7 @@ set_or(PySetObject *so, PyObject *other)          return NULL;      if ((PyObject *)so == other)          return (PyObject *)result; -    if (set_update_internal(result, other) == -1) { +    if (set_update_internal(result, other)) {          Py_DECREF(result);          return NULL;      } @@ -1239,7 +1190,7 @@ set_ior(PySetObject *so, PyObject *other)      if (!PyAnySet_Check(other))          Py_RETURN_NOTIMPLEMENTED; -    if (set_update_internal(so, other) == -1) +    if (set_update_internal(so, other))          return NULL;      Py_INCREF(so);      return (PyObject *)so; @@ -1275,7 +1226,7 @@ set_intersection(PySetObject *so, PyObject *other)                  return NULL;              }              if (rv) { -                if (set_add_entry(result, entry) == -1) { +                if (set_add_entry(result, entry)) {                      Py_DECREF(result);                      return NULL;                  } @@ -1311,7 +1262,7 @@ set_intersection(PySetObject *so, PyObject *other)              return NULL;          }          if (rv) { -            if (set_add_entry(result, &entry) == -1) { +            if (set_add_entry(result, &entry)) {                  Py_DECREF(it);                  Py_DECREF(result);                  Py_DECREF(key); @@ -1519,7 +1470,7 @@ set_difference_update(PySetObject *so, PyObject *args)      for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {          PyObject *other = PyTuple_GET_ITEM(args, i); -        if (set_difference_update_internal(so, other) == -1) +        if (set_difference_update_internal(so, other))              return NULL;      }      Py_RETURN_NONE; @@ -1575,7 +1526,7 @@ set_difference(PySetObject *so, PyObject *other)                  return NULL;              }              if (!rv) { -                if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { +                if (set_add_entry((PySetObject *)result, &entrycopy)) {                      Py_DECREF(result);                      return NULL;                  } @@ -1592,7 +1543,7 @@ set_difference(PySetObject *so, PyObject *other)              return NULL;          }          if (!rv) { -            if (set_add_entry((PySetObject *)result, entry) == -1) { +            if (set_add_entry((PySetObject *)result, entry)) {                  Py_DECREF(result);                  return NULL;              } @@ -1617,7 +1568,7 @@ set_difference_multi(PySetObject *so, PyObject *args)      for (i=1 ; i<PyTuple_GET_SIZE(args) ; i++) {          other = PyTuple_GET_ITEM(args, i); -        if (set_difference_update_internal((PySetObject *)result, other) == -1) { +        if (set_difference_update_internal((PySetObject *)result, other)) {              Py_DECREF(result);              return NULL;          } @@ -1642,7 +1593,7 @@ set_isub(PySetObject *so, PyObject *other)  {      if (!PyAnySet_Check(other))          Py_RETURN_NOTIMPLEMENTED; -    if (set_difference_update_internal(so, other) == -1) +    if (set_difference_update_internal(so, other))          return NULL;      Py_INCREF(so);      return (PyObject *)so; @@ -1676,7 +1627,7 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other)                  return NULL;              }              if (rv == DISCARD_NOTFOUND) { -                if (set_add_entry(so, &an_entry) == -1) { +                if (set_add_entry(so, &an_entry)) {                      Py_DECREF(key);                      return NULL;                  } @@ -1702,7 +1653,7 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other)              return NULL;          }          if (rv == DISCARD_NOTFOUND) { -            if (set_add_entry(so, entry) == -1) { +            if (set_add_entry(so, entry)) {                  Py_DECREF(otherset);                  return NULL;              } @@ -1853,7 +1804,7 @@ set_richcompare(PySetObject *v, PyObject *w, int op)  static PyObject *  set_add(PySetObject *so, PyObject *key)  { -    if (set_add_key(so, key) == -1) +    if (set_add_key(so, key))          return NULL;      Py_RETURN_NONE;  } @@ -1986,7 +1937,7 @@ set_sizeof(PySetObject *so)  {      Py_ssize_t res; -    res = sizeof(PySetObject); +    res = _PyObject_SIZE(Py_TYPE(so));      if (so->table != so->smalltable)          res = res + (so->mask + 1) * sizeof(setentry);      return PyLong_FromSsize_t(res); @@ -2397,7 +2348,7 @@ test_c_api(PySetObject *so)      if (str == NULL)          return NULL;      set_clear_internal(so); -    if (set_update_internal(so, str) == -1) { +    if (set_update_internal(so, str)) {          Py_DECREF(str);          return NULL;      } | 
