From 2a299874cdfec5d04ebb0a0fac01ac92d7b48bc3 Mon Sep 17 00:00:00 2001 From: Stefan Behnel <stefan_ml@behnel.de> Date: Thu, 9 Apr 2015 20:24:57 +0200 Subject: [PATCH] streamline obj.pop() code --- Cython/Compiler/Optimize.py | 16 +++++++-- Cython/Utility/Optimize.c | 65 +++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 04f4deead..fd0562ef6 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -2667,7 +2667,8 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin, PyObject_PopIndex_func_type = PyrexTypes.CFuncType( PyrexTypes.py_object_type, [ PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), - PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None), + PyrexTypes.CFuncTypeArg("py_index", PyrexTypes.py_object_type, None), + PyrexTypes.CFuncTypeArg("c_index", PyrexTypes.c_py_ssize_t_type, None), PyrexTypes.CFuncTypeArg("is_signed", PyrexTypes.c_int_type, None), ], has_varargs=True) # to fake the additional macro args that lack a proper C type @@ -2702,14 +2703,23 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin, ) elif len(args) == 2: index = unwrap_coerced_node(args[1]) + py_index = ExprNodes.NoneNode(index.pos) orig_index_type = index.type if not index.type.is_int: - if is_list or isinstance(index, ExprNodes.IntNode): + if isinstance(index, ExprNodes.IntNode): + py_index = index.coerce_to_pyobject(self.current_env()) + index = index.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) + elif is_list: + if index.type.is_pyobject: + py_index = index.coerce_to_simple(self.current_env()) + index = ExprNodes.CloneNode(py_index) index = index.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) else: return node elif not PyrexTypes.numeric_type_fits(index.type, PyrexTypes.c_py_ssize_t_type): return node + elif isinstance(index, ExprNodes.IntNode): + py_index = index.coerce_to_pyobject(self.current_env()) # real type might still be larger at runtime if not orig_index_type.is_int: orig_index_type = index.type @@ -2721,7 +2731,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin, return ExprNodes.PythonCapiCallNode( node.pos, "__Pyx_Py%s_PopIndex" % type_name, self.PyObject_PopIndex_func_type, - args=[obj, index, + args=[obj, py_index, index, ExprNodes.IntNode(index.pos, value=str(orig_index_type.signed and 1 or 0), constant_result=orig_index_type.signed and 1 or 0, type=PyrexTypes.c_int_type), diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index 2f2aad627..ca0c65eb4 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -78,11 +78,17 @@ static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) { /////////////// pop.proto /////////////// -#define __Pyx_PyObject_Pop(L) (PyList_CheckExact(L) ? \ - __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L)) +static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/ +#if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); /*proto*/ -static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/ +#define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ? \ + __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L)) + +#else +#define __Pyx_PyList_Pop(L) __Pyx__PyObject_Pop(L) +#define __Pyx_PyObject_Pop(L) __Pyx__PyObject_Pop(L) +#endif /////////////// pop /////////////// //@requires: ObjectHandling.c::PyObjectCallMethod0 @@ -96,44 +102,65 @@ static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) { return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop")); } -static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { /* Check that both the size is positive and no reallocation shrinking needs to be done. */ if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) { Py_SIZE(L) -= 1; return PyList_GET_ITEM(L, PyList_GET_SIZE(L)); } -#endif return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop")); } +#endif /////////////// pop_index.proto /////////////// -#define __Pyx_PyObject_PopIndex(L, ix, is_signed, type, to_py_func) ( \ - (PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed)) ? \ - __Pyx__PyList_PopIndex(L, ix) : __Pyx__PyObject_PopIndex(L, to_py_func(ix))) +static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix); /*proto*/ +static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/ + +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix); /*proto*/ -#define __Pyx_PyList_PopIndex(L, ix, is_signed, type, to_py_func) ( \ +#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \ + (likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ? \ + __Pyx__PyList_PopIndex(L, py_ix, ix) : ( \ + (unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \ + __Pyx__PyObject_PopIndex(L, py_ix))) + +#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \ __Pyx_fits_Py_ssize_t(ix, type, is_signed) ? \ - __Pyx__PyList_PopIndex(L, ix) : __Pyx__PyObject_PopIndex(L, to_py_func(ix))) + __Pyx__PyList_PopIndex(L, py_ix, ix) : ( \ + (unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \ + __Pyx__PyObject_PopIndex(L, py_ix))) -static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix); /*proto*/ -static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/ +#else + +#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) \ + __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) + +#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \ + (unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \ + __Pyx__PyObject_PopIndex(L, py_ix)) +#endif /////////////// pop_index /////////////// //@requires: ObjectHandling.c::PyObjectCallMethod1 -static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) { +static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) { PyObject *r; if (unlikely(!py_ix)) return NULL; - r = __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix); + r = __Pyx__PyObject_PopIndex(L, py_ix); Py_DECREF(py_ix); return r; } -static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix) { +static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) { + return __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix); +} + #if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) { Py_ssize_t size = PyList_GET_SIZE(L); if (likely(size > (((PyListObject*)L)->allocated >> 1))) { Py_ssize_t cix = ix; @@ -148,9 +175,13 @@ static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix) { return v; } } -#endif - return __Pyx__PyObject_PopIndex(L, PyInt_FromSsize_t(ix)); + if (py_ix == Py_None) { + return __Pyx__PyObject_PopNewIndex(L, PyInt_FromSsize_t(ix)); + } else { + return __Pyx__PyObject_PopIndex(L, py_ix); + } } +#endif /////////////// dict_getitem_default.proto /////////////// -- 2.30.9