Commit f89efd4c authored by Stefan Behnel's avatar Stefan Behnel

Use dict versioning in Py3.6+ to make the lookup of Python module globals...

Use dict versioning in Py3.6+ to make the lookup of Python module globals almost as fast as C globals.
parent ad1fe32e
...@@ -2148,7 +2148,7 @@ class NameNode(AtomicExprNode): ...@@ -2148,7 +2148,7 @@ class NameNode(AtomicExprNode):
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
code.putln( code.putln(
'%s = __Pyx_GetModuleGlobalName(%s);' % ( '__Pyx_GetModuleGlobalName(%s, %s);' % (
self.result(), self.result(),
interned_cname)) interned_cname))
if not self.cf_is_null: if not self.cf_is_null:
...@@ -2177,7 +2177,7 @@ class NameNode(AtomicExprNode): ...@@ -2177,7 +2177,7 @@ class NameNode(AtomicExprNode):
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
code.putln( code.putln(
'%s = __Pyx_GetModuleGlobalName(%s); %s' % ( '__Pyx_GetModuleGlobalName(%s, %s); %s' % (
self.result(), self.result(),
interned_cname, interned_cname,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
...@@ -2186,7 +2186,7 @@ class NameNode(AtomicExprNode): ...@@ -2186,7 +2186,7 @@ class NameNode(AtomicExprNode):
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c")) UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"))
code.putln( code.putln(
'%s = __Pyx_GetNameInClass(%s, %s); %s' % ( '__Pyx_GetNameInClass(%s, %s, %s); %s' % (
self.result(), self.result(),
entry.scope.namespace_cname, entry.scope.namespace_cname,
interned_cname, interned_cname,
......
...@@ -6845,15 +6845,15 @@ class ForFromStatNode(LoopNode, StatNode): ...@@ -6845,15 +6845,15 @@ class ForFromStatNode(LoopNode, StatNode):
if self.target.entry.scope.is_module_scope: if self.target.entry.scope.is_module_scope:
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
lookup_func = '__Pyx_GetModuleGlobalName(%s)' lookup_func = '__Pyx_GetModuleGlobalName(%s, %s); %s'
else: else:
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c")) UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"))
lookup_func = '__Pyx_GetNameInClass(%s, %%s)' % ( lookup_func = '__Pyx_GetNameInClass(%s, {}, %s); %s'.format(
self.target.entry.scope.namespace_cname) self.target.entry.scope.namespace_cname)
code.putln("%s = %s; %s" % ( code.putln(lookup_func % (
target_node.result(), target_node.result(),
lookup_func % interned_cname, interned_cname,
code.error_goto_if_null(target_node.result(), self.target.pos))) code.error_goto_if_null(target_node.result(), self.target.pos)))
code.put_gotref(target_node.result()) code.put_gotref(target_node.result())
else: else:
......
...@@ -416,6 +416,9 @@ class __Pyx_FakeReference { ...@@ -416,6 +416,9 @@ class __Pyx_FakeReference {
#if CYTHON_USE_DICT_VERSIONS #if CYTHON_USE_DICT_VERSIONS
#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) \
(version_var) = __PYX_GET_DICT_VERSION(dict); \
(cache_var) = (value);
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) { \ #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) { \
static PY_UINT64_T __pyx_dict_version = 0; \ static PY_UINT64_T __pyx_dict_version = 0; \
static PyObject *__pyx_dict_cached_value = NULL; \ static PyObject *__pyx_dict_cached_value = NULL; \
...@@ -428,6 +431,7 @@ class __Pyx_FakeReference { ...@@ -428,6 +431,7 @@ class __Pyx_FakeReference {
} }
#else #else
#define __PYX_GET_DICT_VERSION(dict) (0) #define __PYX_GET_DICT_VERSION(dict) (0)
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
#endif #endif
......
...@@ -1111,7 +1111,8 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { ...@@ -1111,7 +1111,8 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
/////////////// GetNameInClass.proto /////////////// /////////////// GetNameInClass.proto ///////////////
static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/ #define __Pyx_GetNameInClass(var, nmspace, name) (var) = __Pyx__GetNameInClass(nmspace, name)
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/
/////////////// GetNameInClass /////////////// /////////////// GetNameInClass ///////////////
//@requires: PyObjectGetAttrStr //@requires: PyObjectGetAttrStr
...@@ -1126,10 +1127,10 @@ static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) { ...@@ -1126,10 +1127,10 @@ static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) {
if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
return NULL; return NULL;
__Pyx_PyErr_Clear(); __Pyx_PyErr_Clear();
return __Pyx_GetModuleGlobalName(name); return __Pyx__GetModuleGlobalName(name);
} }
static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name) { static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
PyObject *result; PyObject *result;
result = __Pyx_PyObject_GetAttrStr(nmspace, name); result = __Pyx_PyObject_GetAttrStr(nmspace, name);
if (!result) { if (!result) {
...@@ -1154,19 +1155,39 @@ static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name) { ...@@ -1154,19 +1155,39 @@ static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name) {
/////////////// GetModuleGlobalName.proto /////////////// /////////////// GetModuleGlobalName.proto ///////////////
//@substitute: naming
#if CYTHON_USE_DICT_VERSIONS
#define __Pyx_GetModuleGlobalName(var, name) { \
static PY_UINT64_T __pyx_dict_version = 0; \
static PyObject *__pyx_dict_cached_value = NULL; \
(var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION($moddict_cname))) ? \
(likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) : \
__Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value); \
}
static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); /*proto*/
#else
#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name)
static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); /*proto*/
#endif
static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name); /*proto*/
/////////////// GetModuleGlobalName /////////////// /////////////// GetModuleGlobalName ///////////////
//@requires: GetBuiltinName //@requires: GetBuiltinName
//@substitute: naming //@substitute: naming
static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) { #if CYTHON_USE_DICT_VERSIONS
static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value)
#else
static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
#endif
{
PyObject *result; PyObject *result;
#if !CYTHON_AVOID_BORROWED_REFS #if !CYTHON_AVOID_BORROWED_REFS
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1
// Identifier names are always interned and have a pre-calculated hash value. // Identifier names are always interned and have a pre-calculated hash value.
result = _PyDict_GetItem_KnownHash($moddict_cname, name, ((PyASCIIObject *) name)->hash); result = _PyDict_GetItem_KnownHash($moddict_cname, name, ((PyASCIIObject *) name)->hash);
__PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version)
if (likely(result)) { if (likely(result)) {
Py_INCREF(result); Py_INCREF(result);
} else if (unlikely(PyErr_Occurred())) { } else if (unlikely(PyErr_Occurred())) {
...@@ -1174,12 +1195,14 @@ static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) { ...@@ -1174,12 +1195,14 @@ static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
} else { } else {
#else #else
result = PyDict_GetItem($moddict_cname, name); result = PyDict_GetItem($moddict_cname, name);
__PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version)
if (likely(result)) { if (likely(result)) {
Py_INCREF(result); Py_INCREF(result);
} else { } else {
#endif #endif
#else #else
result = PyObject_GetItem($moddict_cname, name); result = PyObject_GetItem($moddict_cname, name);
__PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version)
if (!result) { if (!result) {
PyErr_Clear(); PyErr_Clear();
#endif #endif
......
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