From 66221af567be4e16e8ace6030c82ee2b65328ef9 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou <antoine@python.org> Date: Sun, 17 Dec 2017 21:57:40 +0100 Subject: [PATCH] Optimize `x in set` using PySet_Contains() --- Cython/Compiler/ExprNodes.py | 5 +++++ Cython/Utility/ObjectHandling.c | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index e2a6ce5ab..903947549 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -12197,6 +12197,11 @@ class CmpNode(object): self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyDictContains", "ObjectHandling.c") self.special_bool_cmp_function = "__Pyx_PyDict_ContainsTF" return True + elif self.operand2.type is Builtin.set_type: + self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") + self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySetContains", "ObjectHandling.c") + self.special_bool_cmp_function = "__Pyx_PySet_ContainsTF" + return True elif self.operand2.type is Builtin.unicode_type: self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyUnicodeContains", "StringTools.c") diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c index 080b9b9b5..c49970381 100644 --- a/Cython/Utility/ObjectHandling.c +++ b/Cython/Utility/ObjectHandling.c @@ -1035,6 +1035,32 @@ static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); } +/////////////// PySetContains.proto /////////////// + +static int __Pyx_PySet_ContainsUnhashable(PyObject *set, PyObject *key) { + int result = -1; + if (PySet_Check(key) && PyErr_ExceptionMatches(PyExc_TypeError)) { + /* Convert key to frozenset */ + PyObject *tmpkey; + PyErr_Clear(); + tmpkey = PyFrozenSet_New(key); + if (tmpkey != NULL) { + result = PySet_Contains(set, tmpkey); + Py_DECREF(tmpkey); + } + } + return result; +} + +static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq) { + int result = PySet_Contains(set, key); + + if (unlikely(result < 0)) { + result = __Pyx_PySet_ContainsUnhashable(set, key); + } + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + /////////////// PySequenceContains.proto /////////////// static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { -- 2.30.9