reduce attribute lookup overhead a bit
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 16 Feb 2013 19:38:39 +0000 (20:38 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 16 Feb 2013 19:38:39 +0000 (20:38 +0100)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py
Cython/Utility/ObjectHandling.c
Cython/Utility/Optimize.c

index 1a7b7b3..2333d03 100755 (executable)
@@ -4958,8 +4958,10 @@ class AttributeNode(ExprNode):
 
     def generate_result_code(self, code):
         if self.is_py_attr:
+            code.globalstate.use_utility_code(
+                UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
             code.putln(
-                '%s = PyObject_GetAttr(%s, %s); %s' % (
+                '%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s' % (
                     self.result(),
                     self.obj.py_result(),
                     code.intern_identifier(self.attribute),
index 897f32f..e22d390 100644 (file)
@@ -3856,8 +3856,10 @@ class OverrideCheckNode(StatNode):
         func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
         self.func_node.set_cname(func_node_temp)
         # need to get attribute manually--scope would return cdef method
+        code.globalstate.use_utility_code(
+            UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
         err = code.error_goto_if_null(func_node_temp, self.pos)
-        code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
+        code.putln("%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s" % (
             func_node_temp, self_arg, interned_attr_cname, err))
         code.put_gotref(func_node_temp)
         is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
@@ -5849,10 +5851,12 @@ class WithStatNode(StatNode):
         code.putln("/*with:*/ {")
         self.manager.generate_evaluation_code(code)
         self.exit_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
-        code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
+        code.globalstate.use_utility_code(
+            UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
+        code.putln("%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s" % (
             self.exit_var,
             self.manager.py_result(),
-            code.get_py_string_const(EncodedString('__exit__'), identifier=True),
+            code.intern_identifier(EncodedString('__exit__')),
             code.error_goto_if_null(self.exit_var, self.pos),
             ))
         code.put_gotref(self.exit_var)
@@ -6710,10 +6714,12 @@ class FromImportStatNode(StatNode):
                     code.error_goto(self.pos)))
         item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
         self.item.set_cname(item_temp)
+        code.globalstate.use_utility_code(
+            UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
         for name, target, coerced_item in self.interned_items:
             cname = code.intern_identifier(name)
             code.putln(
-                '%s = PyObject_GetAttr(%s, %s);' % (
+                '%s = __Pyx_PyObject_GetAttrStr(%s, %s);' % (
                     item_temp,
                     self.module.py_result(),
                     cname))
index 992711d..4fea755 100644 (file)
@@ -586,13 +586,31 @@ static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
     return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
 }
 
+/////////////// PyObjectGetAttrStr.proto ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) {
+    PyTypeObject* tp = Py_TYPE(obj);
+    if (likely(tp->tp_getattro))
+        return tp->tp_getattro(obj, attr_name);
+#if PY_MAJOR_VERSION < 3
+    if (likely(tp->tp_getattr))
+        return tp->tp_getattr(obj, PyString_AS_STRING(attr_name));
+#endif
+    return PyObject_GetAttr(obj, attr_name);
+}
+#else
+#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n)
+#endif
+
 /////////////// PyObjectCallMethod.proto ///////////////
+//@requires: PyObjectGetAttrStr
 //@substitute: naming
 
 static PyObject* __Pyx_PyObject_CallMethodTuple(PyObject* obj, PyObject* method_name, PyObject* args) {
     PyObject *method, *result = NULL;
     if (unlikely(!args)) return NULL;
-    method = PyObject_GetAttr(obj, method_name);
+    method = __Pyx_PyObject_GetAttrStr(obj, method_name);
     if (unlikely(!method)) goto bad;
     result = PyObject_Call(method, args, NULL);
     Py_DECREF(method);
index 706894e..0c7831e 100644 (file)
@@ -82,6 +82,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
 static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix); /*proto*/
 
 /////////////// pop_index ///////////////
+//@requires: ObjectHandling.c::PyObjectGetAttrStr
 
 static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
     PyObject *r, *m, *t, *py_ix;
@@ -103,7 +104,7 @@ static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
     }
 #endif
     py_ix = t = NULL;
-    m = PyObject_GetAttr(L, PYIDENT("pop"));
+    m = __Pyx_PyObject_GetAttrStr(L, PYIDENT("pop"));
     if (!m) goto bad;
     py_ix = PyInt_FromSsize_t(ix);
     if (!py_ix) goto bad;