Commit 77098e74 authored by Stefan Behnel's avatar Stefan Behnel

Avoid generating empty tp_new() functions if we can copy the function pointer...

Avoid generating empty tp_new() functions if we can copy the function pointer from the parent at init time.
See GH-1555.
parent 33707f2e
......@@ -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
......
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