Commit d4bd468a authored by Stefan Behnel's avatar Stefan Behnel

Add some guards and branch hints to the dict lookup optimisation code.

parent 5ea22893
...@@ -4354,7 +4354,7 @@ class OverrideCheckNode(StatNode): ...@@ -4354,7 +4354,7 @@ class OverrideCheckNode(StatNode):
" || (Py_TYPE(%s)->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {" % ( " || (Py_TYPE(%s)->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {" % (
self_arg, self_arg)) self_arg, self_arg))
code.putln("#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP") code.putln("#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS")
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("PyDictVersioning", "ObjectHandling.c")) UtilityCode.load_cached("PyDictVersioning", "ObjectHandling.c"))
# TODO: remove the object dict version check by 'inlining' the getattr implementation for methods. # TODO: remove the object dict version check by 'inlining' the getattr implementation for methods.
...@@ -4389,7 +4389,7 @@ class OverrideCheckNode(StatNode): ...@@ -4389,7 +4389,7 @@ class OverrideCheckNode(StatNode):
# NOTE: it's not 100% sure that we catch the exact versions here that were used for the lookup, # NOTE: it's not 100% sure that we catch the exact versions here that were used for the lookup,
# but it is very unlikely that the versions change during lookup, and the type dict safe guard # but it is very unlikely that the versions change during lookup, and the type dict safe guard
# should increase the chance of detecting such a case. # should increase the chance of detecting such a case.
code.putln("#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP") code.putln("#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS")
code.putln("%s = __Pyx_get_tp_dict_version(%s);" % ( code.putln("%s = __Pyx_get_tp_dict_version(%s);" % (
Naming.tp_dict_version_temp, self_arg)) Naming.tp_dict_version_temp, self_arg))
code.putln("%s = __Pyx_get_object_dict_version(%s);" % ( code.putln("%s = __Pyx_get_object_dict_version(%s);" % (
...@@ -4409,7 +4409,7 @@ class OverrideCheckNode(StatNode): ...@@ -4409,7 +4409,7 @@ class OverrideCheckNode(StatNode):
code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type) code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
code.funcstate.release_temp(func_node_temp) code.funcstate.release_temp(func_node_temp)
code.putln("#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP") code.putln("#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS")
code.putln("}") code.putln("}")
code.putln("#endif") code.putln("#endif")
......
...@@ -2402,7 +2402,7 @@ static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y) ...@@ -2402,7 +2402,7 @@ static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y)
/////////////// PyDictVersioning.proto /////////////// /////////////// PyDictVersioning.proto ///////////////
#if CYTHON_USE_DICT_VERSIONS #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) #define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1)
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) #define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) \ #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) \
...@@ -2432,24 +2432,28 @@ static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UIN ...@@ -2432,24 +2432,28 @@ static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UIN
/////////////// PyDictVersioning /////////////// /////////////// PyDictVersioning ///////////////
#if CYTHON_USE_DICT_VERSIONS #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) {
PyObject *dict = Py_TYPE(obj)->tp_dict; PyObject *dict = Py_TYPE(obj)->tp_dict;
return dict ? __PYX_GET_DICT_VERSION(dict) : 0; return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0;
} }
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) {
PyObject **dictptr = NULL; PyObject **dictptr = NULL;
Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset;
if (offset) { if (offset) {
dictptr = (offset > 0) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); #if CYTHON_COMPILING_IN_CPYTHON
dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj);
#else
dictptr = _PyObject_GetDictPtr(obj);
#endif
} }
return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0;
} }
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) {
PyObject *dict = Py_TYPE(obj)->tp_dict; PyObject *dict = Py_TYPE(obj)->tp_dict;
if (!dict || tp_dict_version != __PYX_GET_DICT_VERSION(dict)) if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict)))
return 0; return 0;
return obj_dict_version == __Pyx_get_object_dict_version(obj); return obj_dict_version == __Pyx_get_object_dict_version(obj);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment