]> granicus.if.org Git - python/commitdiff
Issue #25557: Refactor _PyDict_LoadGlobal()
authorVictor Stinner <victor.stinner@gmail.com>
Fri, 20 Nov 2015 08:24:02 +0000 (09:24 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Fri, 20 Nov 2015 08:24:02 +0000 (09:24 +0100)
Don't fallback to PyDict_GetItemWithError() if the hash is unknown: compute the
hash instead. Add also comments to explain the optimization a little bit.

Objects/dictobject.c
Python/ceval.c

index 624ae9b88858adcb5139427dbe78c1f3c677a169..4a72c9af078d8473621e66bdab9d2691fc9500ab 100644 (file)
@@ -1165,39 +1165,42 @@ _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key)
     return PyDict_GetItemWithError(dp, kv);
 }
 
-/* Fast version of global value lookup.
+/* Fast version of global value lookup (LOAD_GLOBAL).
  * Lookup in globals, then builtins.
+ *
+ * Raise an exception and return NULL if an error occurred (ex: computing the
+ * key hash failed, key comparison failed, ...). Return NULL if the key doesn't
+ * exist. Return the value if the key exists.
  */
 PyObject *
 _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
 {
-    PyObject *x;
-    if (PyUnicode_CheckExact(key)) {
-        PyObject **value_addr;
-        Py_hash_t hash = ((PyASCIIObject *)key)->hash;
-        if (hash != -1) {
-            PyDictKeyEntry *e;
-            e = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr);
-            if (e == NULL) {
-                return NULL;
-            }
-            x = *value_addr;
-            if (x != NULL)
-                return x;
-            e = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
-            if (e == NULL) {
-                return NULL;
-            }
-            x = *value_addr;
-            return x;
-        }
+    Py_hash_t hash;
+    PyDictKeyEntry *entry;
+    PyObject **value_addr;
+    PyObject *value;
+
+    if (!PyUnicode_CheckExact(key) ||
+        (hash = ((PyASCIIObject *) key)->hash) == -1)
+    {
+        hash = PyObject_Hash(key);
+        if (hash == -1)
+            return NULL;
     }
-    x = PyDict_GetItemWithError((PyObject *)globals, key);
-    if (x != NULL)
-        return x;
-    if (PyErr_Occurred())
+
+    /* namespace 1: globals */
+    entry = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr);
+    if (entry == NULL)
         return NULL;
-    return PyDict_GetItemWithError((PyObject *)builtins, key);
+    value = *value_addr;
+    if (value != NULL)
+        return value;
+
+    /* namespace 2: builtins */
+    entry = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
+    if (entry == NULL)
+        return NULL;
+    return *value_addr;
 }
 
 /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
index 7f9ef6fc5bba78170a34d852d8618fc720675dfd..1d656495f548d3521ceb0ee3599ce78e56b48a53 100644 (file)
@@ -2347,26 +2347,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
             PyObject *name = GETITEM(names, oparg);
             PyObject *v;
             if (PyDict_CheckExact(f->f_globals)
-                && PyDict_CheckExact(f->f_builtins)) {
+                && PyDict_CheckExact(f->f_builtins))
+            {
                 v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,
                                        (PyDictObject *)f->f_builtins,
                                        name);
                 if (v == NULL) {
-                    if (!_PyErr_OCCURRED())
+                    if (!_PyErr_OCCURRED()) {
+                        /* _PyDict_LoadGlobal() returns NULL without raising
+                         * an exception if the key doesn't exist */
                         format_exc_check_arg(PyExc_NameError,
                                              NAME_ERROR_MSG, name);
+                    }
                     goto error;
                 }
                 Py_INCREF(v);
             }
             else {
                 /* Slow-path if globals or builtins is not a dict */
+
+                /* namespace 1: globals */
                 v = PyObject_GetItem(f->f_globals, name);
                 if (v == NULL) {
                     if (!PyErr_ExceptionMatches(PyExc_KeyError))
                         goto error;
                     PyErr_Clear();
 
+                    /* namespace 2: builtins */
                     v = PyObject_GetItem(f->f_builtins, name);
                     if (v == NULL) {
                         if (PyErr_ExceptionMatches(PyExc_KeyError))