Commit 5a26934a authored by Stefan Behnel's avatar Stefan Behnel

Use a specialised GenericGetAttr implementation for the "tp_getattro" slot...

Use a specialised GenericGetAttr implementation for the "tp_getattro" slot whenever a type uses the generic lookup but has no instance dict.
parent 25c4e3e0
......@@ -60,6 +60,8 @@ Features added
* Name lookups in the module and in classes are faster.
* Python attribute lookups on extension types without instance dict are faster.
* Some missing signals were added to ``libc/signal.pxd``.
Patch by Jeroen Demeyer. (Github issue #1914)
......
......@@ -4840,6 +4840,26 @@ class CClassDefNode(ClassDefNode):
# Don't inherit tp_print from builtin types, restoring the
# behavior of using tp_repr or tp_str instead.
code.putln("%s.tp_print = 0;" % typeobj_cname)
# Use specialised attribute lookup for types with generic lookup but no instance dict.
getattr_slot_func = TypeSlots.get_slot_code_by_name(scope, 'tp_getattro')
dictoffset_slot_func = TypeSlots.get_slot_code_by_name(scope, 'tp_dictoffset')
if getattr_slot_func == '0' and dictoffset_slot_func == '0':
if type.is_final_type:
py_cfunc = "__Pyx_PyObject_GenericGetAttrNoDict" # grepable
utility_func = "PyObject_GenericGetAttrNoDict"
else:
py_cfunc = "__Pyx_PyObject_GenericGetAttr"
utility_func = "PyObject_GenericGetAttr"
code.globalstate.use_utility_code(UtilityCode.load_cached(utility_func, "ObjectHandling.c"))
code.putln("if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) &&"
" likely(!%s.tp_dictoffset && %s.tp_getattro == PyObject_GenericGetAttr)) {" % (
typeobj_cname, typeobj_cname))
code.putln("%s.tp_getattro = %s;" % (
typeobj_cname, py_cfunc))
code.putln("}")
# Fix special method docstrings. This is a bit of a hack, but
# unless we let PyType_Ready create the slot wrappers we have
# a significant performance hit. (See trac #561.)
......
......@@ -612,6 +612,20 @@ def get_slot_function(scope, slot):
return slot_code
return None
def get_slot_by_name(slot_name):
# For now, only search the type struct, no referenced sub-structs.
for slot in slot_table:
if slot.slot_name == slot_name:
return slot
assert False, "Slot not found: %s" % slot_name
def get_slot_code_by_name(scope, slot_name):
slot = get_slot_by_name(slot_name)
return slot.slot_code(scope)
#------------------------------------------------------------------------------------------
#
# Signatures for generic Python functions and methods.
......
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