summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-09-14 00:25:33 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-09-14 00:25:33 (GMT)
commit0ab085c4cba79c1743288a300425b3c9050250ba (patch)
treeaa0436b634cc45a83f710bdf94289deefd540d9b /Objects
parent742dfd6f178c3880248c32d64322e2cff8cea23f (diff)
downloadcpython-0ab085c4cba79c1743288a300425b3c9050250ba.zip
cpython-0ab085c4cba79c1743288a300425b3c9050250ba.tar.gz
cpython-0ab085c4cba79c1743288a300425b3c9050250ba.tar.bz2
Changed the dict implementation to take "string shortcuts" only when
keys are true strings -- no subclasses need apply. This may be debatable. The problem is that a str subclass may very well want to override __eq__ and/or __hash__ (see the new example of case-insensitive strings in test_descr), but go-fast shortcuts for strings are ubiquitous in our dicts (and subclass overrides aren't even looked for then). Another go-fast reason for the change is that PyCheck_StringExact() is a quicker test than PyCheck_String(), and we make such a test on virtually every access to every dict. OTOH, a str subclass may also be perfectly happy using the base str eq and hash, and this change slows them a lot. But those cases are still hypothetical, while Python's own reliance on true-string dicts is not.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/dictobject.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index b98cccf..f68a964 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -298,8 +298,8 @@ Done:
* means we don't need to go through PyObject_Compare(); we can always use
* _PyString_Eq directly.
*
- * This really only becomes meaningful if proper error handling in lookdict()
- * is too expensive.
+ * This is valuable because the general-case error handling in lookdict() is
+ * expensive, and dicts with pure-string keys are very common.
*/
static dictentry *
lookdict_string(dictobject *mp, PyObject *key, register long hash)
@@ -311,8 +311,11 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
dictentry *ep0 = mp->ma_table;
register dictentry *ep;
- /* make sure this function doesn't have to handle non-string keys */
- if (!PyString_Check(key)) {
+ /* Make sure this function doesn't have to handle non-string 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 (!PyString_CheckExact(key)) {
#ifdef SHOW_CONVERSION_COUNTS
++converted;
#endif
@@ -478,7 +481,7 @@ PyDict_GetItem(PyObject *op, PyObject *key)
return NULL;
}
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{
@@ -510,7 +513,7 @@ PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
}
mp = (dictobject *)op;
#ifdef CACHE_HASH
- if (PyString_Check(key)) {
+ if (PyString_CheckExact(key)) {
#ifdef INTERN_STRINGS
if (((PyStringObject *)key)->ob_sinterned != NULL) {
key = ((PyStringObject *)key)->ob_sinterned;
@@ -562,7 +565,7 @@ PyDict_DelItem(PyObject *op, PyObject *key)
return -1;
}
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{
@@ -820,7 +823,7 @@ dict_repr(dictobject *mp)
if (s == NULL)
goto Done;
result = _PyString_Join(s, pieces);
- Py_DECREF(s);
+ Py_DECREF(s);
Done:
Py_XDECREF(pieces);
@@ -842,7 +845,7 @@ dict_subscript(dictobject *mp, register PyObject *key)
long hash;
assert(mp->ma_table != NULL);
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{
@@ -1358,7 +1361,7 @@ dict_has_key(register dictobject *mp, PyObject *key)
long hash;
register long ok;
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{
@@ -1382,7 +1385,7 @@ dict_get(register dictobject *mp, PyObject *args)
return NULL;
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{
@@ -1411,7 +1414,7 @@ dict_setdefault(register dictobject *mp, PyObject *args)
return NULL;
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{
@@ -1647,7 +1650,7 @@ dict_contains(dictobject *mp, PyObject *key)
long hash;
#ifdef CACHE_HASH
- if (!PyString_Check(key) ||
+ if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
{