diff -r 2b91121bc3fc Objects/dictobject.c --- a/Objects/dictobject.c Mon Nov 21 02:00:04 2016 -0800 +++ b/Objects/dictobject.c Mon Nov 21 20:29:08 2016 +0900 @@ -101,6 +101,10 @@ where ix == mp->ma_used. Inserting into converting the dict to the combined table. */ +#include "Python.h" +#include "dict-common.h" +#include "stringlib/eq.h" /* to get unicode_eq() */ + /* PyDict_MINSIZE is the starting size for any new dict. * 8 allows dicts with no more than 5 active entries; experiments suggested * this suffices for the majority of dicts (consisting mostly of usually-small @@ -110,9 +114,8 @@ converting the dict to the combined tabl */ #define PyDict_MINSIZE 8 -#include "Python.h" -#include "dict-common.h" -#include "stringlib/eq.h" /* to get unicode_eq() */ +/* PyDict_MAXSIZE is the upper bound of the dict. */ +#define PyDict_MAXSIZE (PY_SSIZE_T_MAX/8+1) /*[clinic input] class dict "PyDictObject *" "&PyDict_Type" @@ -389,7 +392,7 @@ dk_set_index(PyDictKeysObject *keys, Py_ * This can be used to reserve enough size to insert n entries without * resizing. */ -#define ESTIMATE_SIZE(n) (((n)*3) >> 1) +#define ESTIMATE_SIZE(n) (((n)*3+1) >> 1) /* Alternative fraction that is otherwise close enough to 2n/3 to make * little difference. 8 * 2/3 == 8 * 5/8 == 5. 16 * 2/3 == 16 * 5/8 == 10. @@ -1363,10 +1366,23 @@ PyObject * { Py_ssize_t newsize; PyDictKeysObject *new_keys; - for (newsize = PyDict_MINSIZE; - newsize <= minused && newsize > 0; - newsize <<= 1) - ; + + if (minused < USABLE_FRACTION(PyDict_MAXSIZE)) { + Py_ssize_t minsize = ESTIMATE_SIZE(minused); + newsize = PyDict_MINSIZE; + while (newsize < minsize) { + newsize <<= 1; + } + } + else { + /* There are no strict guarantee that returned dict can contain + * minused items without resize. So we create medium size dict + * instead of returning error when too large minused is specified. + */ + newsize = 4096; + } + assert(IS_POWER_OF_2(newsize)); + new_keys = new_keys_object(newsize); if (new_keys == NULL) return NULL;