diff -r a8563ef0eb8a Objects/dictobject.c --- a/Objects/dictobject.c Tue Jan 17 10:07:25 2017 +0200 +++ b/Objects/dictobject.c Tue Jan 17 17:10:54 2017 +0900 @@ -3296,11 +3296,71 @@ PyObject * /* For backward compatibility with old dictionary interface */ +/* PyDict_GetItemString specialized for key is ascii string. + * + * Implementation is same to lookdict_unicode, except comparing only ascii + * C string. + */ +static PyObject * +dict_getitemascii(PyDictObject *mp, const char *key, Py_ssize_t len) +{ + assert(mp->ma_keys->dk_lookup != lookdict); + + Py_hash_t hash = _Py_HashBytes(key, len); + size_t mask = DK_MASK(mp->ma_keys); + size_t perturb = hash; + size_t i = hash & mask; + PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys); + + for (;;) { + Py_ssize_t ix = dk_get_index(mp->ma_keys, i); + if (ix == DKIX_EMPTY) { + return NULL; + } + if (ix >= 0) { + PyDictKeyEntry *ep = &ep0[ix]; + PyObject *ekey = ep->me_key; + assert(PyUnicode_IS_READY(ekey)); + + if (ep->me_hash == hash && PyUnicode_IS_ASCII(ekey) && + PyUnicode_GET_LENGTH(ekey) == len && + memcmp(PyUnicode_DATA(ekey), key, len) == 0) { + if (_PyDict_HasSplitTable(mp)) { + return mp->ma_values[ix]; + } + else { + return ep->me_value; + } + } + } + + perturb >>= PERTURB_SHIFT; + i = mask & ((i << 2) + i + perturb + 1); + } + assert(0); + return NULL; +} + PyObject * PyDict_GetItemString(PyObject *v, const char *key) { + if (!PyDict_Check(v)) + return NULL; + + Py_ssize_t len; + int ascii = 1; + for (len = 0; key[len]; len++) { + if (key[len] < 0) { + ascii = 0; + } + } + + if (ascii && ((PyDictObject*)v)->ma_keys->dk_lookup != lookdict) { + return dict_getitemascii((PyDictObject*)v, key, len); + } + PyObject *kv, *rv; - kv = PyUnicode_FromString(key); + kv = PyUnicode_FromStringAndSize(key, len); if (kv == NULL) { PyErr_Clear(); return NULL;