From: Victor Stinner <victor.stinner@gmail.com>
Date: Thu, 15 Dec 2016 16:23:24 +0000 (+0100)
Subject: Merge 3.6
X-Git-Tag: v3.7.0a1~1744
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5cc70c9935ca07d4ac08cddaeee90a87ec1e5a4a;p=python

Merge 3.6
---

5cc70c9935ca07d4ac08cddaeee90a87ec1e5a4a
diff --cc Objects/dictobject.c
index e7c0db1882,5fff34b119..6a7e831944
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@@ -1214,12 -1245,12 +1214,12 @@@ After resizing a table is always combin
  but can be resplit by make_keys_shared().
  */
  static int
- dictresize(PyDictObject *mp, Py_ssize_t minused)
+ dictresize(PyDictObject *mp, Py_ssize_t minsize)
  {
 -    Py_ssize_t i, newsize;
 +    Py_ssize_t newsize, numentries;
      PyDictKeysObject *oldkeys;
      PyObject **oldvalues;
 -    PyDictKeyEntry *ep0;
 +    PyDictKeyEntry *oldentries, *newentries;
  
      /* Find the smallest table size > minused. */
      for (newsize = PyDict_MINSIZE;
@@@ -1244,30 -1269,37 +1244,32 @@@
          mp->ma_keys = oldkeys;
          return -1;
      }
+     // New table must be large enough.
+     assert(mp->ma_keys->dk_usable >= mp->ma_used);
      if (oldkeys->dk_lookup == lookdict)
          mp->ma_keys->dk_lookup = lookdict;
 -    mp->ma_values = NULL;
 -    ep0 = DK_ENTRIES(oldkeys);
 -    /* Main loop below assumes we can transfer refcount to new keys
 -     * and that value is stored in me_value.
 -     * Increment ref-counts and copy values here to compensate
 -     * This (resizing a split table) should be relatively rare */
 +
 +    numentries = mp->ma_used;
 +    oldentries = DK_ENTRIES(oldkeys);
 +    newentries = DK_ENTRIES(mp->ma_keys);
 +    oldvalues = mp->ma_values;
      if (oldvalues != NULL) {
 -        for (i = 0; i < oldkeys->dk_nentries; i++) {
 -            if (oldvalues[i] != NULL) {
 -                Py_INCREF(ep0[i].me_key);
 -                ep0[i].me_value = oldvalues[i];
 -            }
 -        }
 -    }
 -    /* Main loop */
 -    for (i = 0; i < oldkeys->dk_nentries; i++) {
 -        PyDictKeyEntry *ep = &ep0[i];
 -        if (ep->me_value != NULL) {
 -            insertdict_clean(mp, ep->me_key, ep->me_hash, ep->me_value);
 +        /* Convert split table into new combined table.
 +         * We must incref keys; we can transfer values.
 +         * Note that values of split table is always dense.
 +         */
 +        for (Py_ssize_t i = 0; i < numentries; i++) {
 +            assert(oldvalues[i] != NULL);
 +            PyDictKeyEntry *ep = &oldentries[i];
 +            PyObject *key = ep->me_key;
 +            Py_INCREF(key);
 +            newentries[i].me_key = key;
 +            newentries[i].me_hash = ep->me_hash;
 +            newentries[i].me_value = oldvalues[i];
          }
 -    }
 -    mp->ma_keys->dk_usable -= mp->ma_used;
 -    if (oldvalues != NULL) {
 -        /* NULL out me_value slot in oldkeys, in case it was shared */
 -        for (i = 0; i < oldkeys->dk_nentries; i++)
 -            ep0[i].me_value = NULL;
 +
          DK_DECREF(oldkeys);
 +        mp->ma_values = NULL;
          if (oldvalues != empty_values) {
              free_values(oldvalues);
          }