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):
code.globalstate.use_utility_code(
UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
code.putln(
'%s = __Pyx_GetModuleGlobalName(%s);' % (
'__Pyx_GetModuleGlobalName(%s, %s);' % (
self.result(),
interned_cname))
if not self.cf_is_null:
......@@ -2177,7 +2177,7 @@ class NameNode(AtomicExprNode):
code.globalstate.use_utility_code(
UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
code.putln(
'%s = __Pyx_GetModuleGlobalName(%s); %s' % (
'__Pyx_GetModuleGlobalName(%s, %s); %s' % (
self.result(),
interned_cname,
code.error_goto_if_null(self.result(), self.pos)))
......@@ -2186,7 +2186,7 @@ class NameNode(AtomicExprNode):
code.globalstate.use_utility_code(
UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"))
code.putln(
'%s = __Pyx_GetNameInClass(%s, %s); %s' % (
'__Pyx_GetNameInClass(%s, %s, %s); %s' % (
self.result(),
entry.scope.namespace_cname,
interned_cname,
......
......@@ -6845,15 +6845,15 @@ class ForFromStatNode(LoopNode, StatNode):
if self.target.entry.scope.is_module_scope:
code.globalstate.use_utility_code(
UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
lookup_func = '__Pyx_GetModuleGlobalName(%s)'
lookup_func = '__Pyx_GetModuleGlobalName(%s, %s); %s'
else:
code.globalstate.use_utility_code(
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)
code.putln("%s = %s; %s" % (
code.putln(lookup_func % (
target_node.result(),
lookup_func % interned_cname,
interned_cname,
code.error_goto_if_null(target_node.result(), self.target.pos)))
code.put_gotref(target_node.result())
else:
......
......@@ -416,6 +416,9 @@ class __Pyx_FakeReference {
#if CYTHON_USE_DICT_VERSIONS
#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) { \
static PY_UINT64_T __pyx_dict_version = 0; \
static PyObject *__pyx_dict_cached_value = NULL; \
......@@ -428,6 +431,7 @@ class __Pyx_FakeReference {
}
#else
#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);
#endif
......
......@@ -1111,7 +1111,8 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
/////////////// 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 ///////////////
//@requires: PyObjectGetAttrStr
......@@ -1126,10 +1127,10 @@ static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) {
if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
return NULL;
__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;
result = __Pyx_PyObject_GetAttrStr(nmspace, name);
if (!result) {
......@@ -1154,19 +1155,39 @@ static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name) {
/////////////// 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 ///////////////
//@requires: GetBuiltinName
//@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;
#if !CYTHON_AVOID_BORROWED_REFS
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1
// Identifier names are always interned and have a pre-calculated hash value.
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)) {
Py_INCREF(result);
} else if (unlikely(PyErr_Occurred())) {
......@@ -1174,12 +1195,14 @@ static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
} else {
#else
result = PyDict_GetItem($moddict_cname, name);
__PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version)
if (likely(result)) {
Py_INCREF(result);
} else {
#endif
#else
result = PyObject_GetItem($moddict_cname, name);
__PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version)
if (!result) {
PyErr_Clear();
#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