diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2019-03-30 22:12:53 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2019-03-30 22:13:15 +0100 |
commit | 77098e74eb98f98704c4e4e661d4917ee42626bc (patch) | |
tree | b54cc601fdb9804886c48af9bb971668102d281d | |
parent | 33707f2ee8f669a8d1e185707d900357525759ae (diff) | |
download | cython-less_tp_new.tar.gz |
Avoid generating empty tp_new() functions if we can copy the function pointer from the parent at init time.less_tp_new
See GH-1555.
-rw-r--r-- | Cython/Compiler/TypeSlots.py | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index aeb773465..f7ea0e1e9 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -366,24 +366,53 @@ class ConstructorSlot(InternalMethodSlot): InternalMethodSlot.__init__(self, slot_name, **kargs) self.method = method - def slot_code(self, scope): - entry = scope.lookup_here(self.method) if self.method else None + def _needs_own(self, scope): if (scope.parent_type.base_type and not scope.has_pyobject_attrs and not scope.has_memoryview_attrs and not scope.has_cpp_class_attrs - and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname) - and not (entry and entry.is_special)): + and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname)): + entry = scope.lookup_here(self.method) if self.method else None + if not (entry and entry.is_special): + return False + # Unless we can safely delegate to the parent, all types need a tp_new(). + return True + + def _parent_slot_function(self, scope): + parent_type_scope = scope.parent_type.base_type.scope + if scope.parent_scope is parent_type_scope.parent_scope: + entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) + if entry.visibility != 'extern': + return self.slot_code(parent_type_scope) + return None + + def slot_code(self, scope): + if not self._needs_own(scope): # if the type does not have object attributes, it can # delegate GC methods to its parent - iff the parent # functions are defined in the same module - parent_type_scope = scope.parent_type.base_type.scope - if scope.parent_scope is parent_type_scope.parent_scope: - entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) - if entry.visibility != 'extern': - return self.slot_code(parent_type_scope) + slot_code = self._parent_slot_function(scope) + return slot_code or '0' return InternalMethodSlot.slot_code(self, scope) + def generate_dynamic_init_code(self, scope, code): + if self.slot_code(scope) != '0': + return + # If we don't have our own slot function and don't know the + # parent function statically, copy it dynamically. + base_type = scope.parent_type.base_type + if base_type.is_extension_type and base_type.typeobj_cname: + src = '%s.%s' % (base_type.typeobj_cname, self.slot_name) + elif base_type.typeptr_cname: + src = '%s->%s' % (base_type.typeptr_cname, self.slot_name) + else: + return + + code.putln("%s.%s = %s;" % ( + scope.parent_type.typeobj_cname, + self.slot_name, + src)) + class SyntheticSlot(InternalMethodSlot): # Type slot descriptor for a synthesized method which |