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;
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);
}