speed up access to module globals
authorStefan Behnel <stefan_ml@behnel.de>
Wed, 6 Mar 2013 23:17:37 +0000 (00:17 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Wed, 6 Mar 2013 23:17:37 +0000 (00:17 +0100)
Cython/Compiler/ExprNodes.py
Cython/Compiler/ModuleNode.py
Cython/Compiler/Nodes.py
Cython/Utility/ObjectHandling.c

index e23e23e..029841a 100755 (executable)
@@ -1615,7 +1615,6 @@ class NameNode(AtomicExprNode):
                 self.is_temp = 0
             else:
                 self.is_temp = 1
-                env.use_utility_code(get_name_interned_utility_code)
 
             self.is_used_as_rvalue = 1
         elif entry.type.is_memoryviewslice:
@@ -1754,32 +1753,41 @@ class NameNode(AtomicExprNode):
                         interned_cname))
                 code.putln('if (unlikely(!%s)) {' % self.result())
                 code.putln('PyErr_Clear();')
+            code.globalstate.use_utility_code(
+                UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
             code.putln(
-                '%s = __Pyx_GetName(%s, %s);' % (
+                '%s = __Pyx_GetModuleGlobalName(%s);' % (
                     self.result(),
-                    Naming.module_cname,
                     interned_cname))
             if not self.cf_is_null:
                 code.putln("}")
             code.putln(code.error_goto_if_null(self.result(), self.pos))
             code.put_gotref(self.py_result())
 
-        elif entry.is_pyglobal or entry.is_builtin:
+        elif entry.is_builtin:
             assert entry.type.is_pyobject, "Python global or builtin not a Python object"
             interned_cname = code.intern_identifier(self.entry.name)
-            if entry.is_builtin:
-                namespace = Naming.builtins_cname
-            else: # entry.is_pyglobal
-                namespace = entry.scope.namespace_cname
             code.globalstate.use_utility_code(get_name_interned_utility_code)
             code.putln(
                 '%s = __Pyx_GetName(%s, %s); %s' % (
                 self.result(),
-                namespace,
+                Naming.builtins_cname,
                 interned_cname,
                 code.error_goto_if_null(self.result(), self.pos)))
             code.put_gotref(self.py_result())
 
+        elif entry.is_pyglobal:
+            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
+            interned_cname = code.intern_identifier(self.entry.name)
+            code.globalstate.use_utility_code(
+                UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
+            code.putln(
+                '%s = __Pyx_GetModuleGlobalName(%s); %s' % (
+                    self.result(),
+                    interned_cname,
+                    code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.py_result())
+
         elif entry.is_local or entry.in_closure or entry.from_closure or entry.type.is_memoryviewslice:
             # Raise UnboundLocalError for objects and memoryviewslices
             raise_unbound = (
index 775da8d..b433e9a 100644 (file)
@@ -571,6 +571,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.put(Nodes.branch_prediction_macros)
         code.putln('')
         code.putln('static PyObject *%s;' % env.module_cname)
+        code.putln('static PyObject *%s;' % env.module_dict_cname)
         code.putln('static PyObject *%s;' % Naming.builtins_cname)
         code.putln('static PyObject *%s;' % Naming.empty_tuple)
         code.putln('static PyObject *%s;' % Naming.empty_bytes)
@@ -2182,6 +2183,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 Naming.pymoduledef_cname))
         code.putln("#endif")
         code.putln(code.error_goto_if_null(env.module_cname, self.pos))
+        code.putln(
+            "%s = PyModule_GetDict(%s); %s" % (
+                env.module_dict_cname, env.module_cname,
+                code.error_goto_if_null(env.module_dict_cname, self.pos)))
+        code.put_incref(env.module_dict_cname, py_object_type, nanny=False)
 
         # CPython may not have put us into sys.modules yet, but relative imports and reimports require it
         fq_module_name = env.qualified_name
index 5727cd9..b6b6bff 100644 (file)
@@ -5734,12 +5734,12 @@ class ForFromStatNode(LoopNode, StatNode):
                 target_node = ExprNodes.PyTempNode(self.target.pos, None)
                 target_node.allocate(code)
                 interned_cname = code.intern_identifier(self.target.entry.name)
-                code.globalstate.use_utility_code(ExprNodes.get_name_interned_utility_code)
-                code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
-                                target_node.result(),
-                                Naming.module_cname,
-                                interned_cname,
-                                code.error_goto_if_null(target_node.result(), self.target.pos)))
+                code.globalstate.use_utility_code(
+                    UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
+                code.putln("%s = __Pyx_GetModuleGlobalName(%s); %s" % (
+                    target_node.result(),
+                    interned_cname,
+                    code.error_goto_if_null(target_node.result(), self.target.pos)))
                 code.put_gotref(target_node.result())
             else:
                 target_node = self.target
index e8f5ab0..a5dc3a3 100644 (file)
@@ -606,6 +606,39 @@ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
     return result;
 }
 
+/////////////// GetModuleGlobalName.proto ///////////////
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name); /*proto*/
+
+/////////////// GetModuleGlobalName ///////////////
+//@requires: PyObjectGetAttrStr
+//@substitute: naming
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
+    PyObject *result;
+#if CYTHON_COMPILING_IN_CPYTHON
+    result = PyDict_GetItem($moddict_cname, name);
+    if (result) {
+        Py_INCREF(result);
+    } else {
+#else
+    result = PyObject_GetItem($moddict_cname, name);
+    if (!result) {
+        PyErr_Clear();
+#endif
+        result = __Pyx_PyObject_GetAttrStr($builtins_cname, name);
+        if (unlikely(!result)) {
+            PyErr_Format(PyExc_NameError,
+#if PY_MAJOR_VERSION >= 3
+                "name '%U' is not defined", name);
+#else
+                "name '%s' is not defined", PyString_AS_STRING(name));
+#endif
+        }
+    }
+    return result;
+}
+
 /////////////// PyObjectGetAttrStr.proto ///////////////
 
 #if CYTHON_COMPILING_IN_CPYTHON