From 61ab9c73d85ec6dcc5f5db50f0d75dce96126934 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sat, 16 Feb 2013 20:38:39 +0100 Subject: [PATCH] reduce attribute lookup overhead a bit --- Cython/Compiler/ExprNodes.py | 4 +++- Cython/Compiler/Nodes.py | 14 ++++++++++---- Cython/Utility/ObjectHandling.c | 20 +++++++++++++++++++- Cython/Utility/Optimize.c | 3 ++- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 1a7b7b3..2333d03 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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), diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 897f32f..e22d390 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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)) diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c index 992711d..4fea755 100644 --- a/Cython/Utility/ObjectHandling.c +++ b/Cython/Utility/ObjectHandling.c @@ -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); diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index 706894e..0c7831e 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -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; -- 2.7.4