Commit 4a0ad3fb authored by Robert Bradshaw's avatar Robert Bradshaw

Optimize tp_new and tp_dealloc

parent e159ce51
......@@ -608,6 +608,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.declaration_code("")))
def generate_new_function(self, scope, code):
tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__')
slot_func = scope.mangle_internal("tp_new")
if tp_slot.slot_code(scope) != slot_func:
return # never used
type = scope.parent_type
base_type = type.base_type
py_attrs = []
......@@ -624,9 +628,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"%s;"
% scope.parent_type.declaration_code("p"))
if base_type:
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if scope.parent_scope is base_type.scope.parent_scope and entry.visibility != 'extern':
tp_new = TypeSlots.InternalMethodSlot("tp_new").slot_code(base_type.scope)
else:
tp_new = "%s->tp_new" % base_type.typeptr_cname
code.putln(
"PyObject *o = %s->tp_new(t, a, k);" %
base_type.typeptr_cname)
"PyObject *o = %s(t, a, k);" % tp_new)
else:
code.putln(
"PyObject *o = (*t->tp_alloc)(t, 0);")
......@@ -662,7 +670,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"}")
def generate_dealloc_function(self, scope, code):
tp_slot = TypeSlots.ConstructorSlot("tp_dealloc", '__dealloc__')
slot_func = scope.mangle_internal("tp_dealloc")
base_type = scope.parent_type.base_type
if tp_slot.slot_code(scope) != slot_func:
return # never used
code.putln("")
code.putln(
"static void %s(PyObject *o) {"
......@@ -679,12 +691,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for entry in py_attrs:
code.put_xdecref("p->%s" % entry.cname, entry.type)
if base_type:
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if scope.parent_scope is base_type.scope.parent_scope and entry.visibility != 'extern':
tp_dealloc = TypeSlots.InternalMethodSlot("tp_dealloc").slot_code(base_type.scope)
else:
tp_dealloc = "%s->tp_dealloc" % base_type.typeptr_cname
code.putln(
"%s->tp_dealloc(o);" %
base_type.typeptr_cname)
"%s(o);" % tp_dealloc)
else:
code.putln(
"(*o->ob_type->tp_free)(o);")
"(*o->ob_type->tp_free)(o);")
code.putln(
"}")
......@@ -732,7 +748,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if base_type:
# want to call it explicitly if possible so inlining can be performed
parent_slot = tp_slot.slot_code(base_type.scope)
if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0':
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0' and entry.visibility != 'extern':
code.putln("e = %s(o, v, a); if (e) return e;" % parent_slot)
else:
code.putln("if (%s->tp_traverse) {" % base_type.typeptr_cname)
......@@ -775,7 +792,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if base_type:
# want to call it explicitly if possible so inlining can be performed
parent_slot = tp_slot.slot_code(base_type.scope)
if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0':
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0' and entry.visibility != 'extern':
code.putln("%s(o);" % parent_slot)
else:
code.putln("if (%s->tp_clear) {" % base_type.typeptr_cname)
......
......@@ -228,7 +228,31 @@ class GCDependentSlot(InternalMethodSlot):
# 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:
return self.slot_code(parent_type_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 InternalMethodSlot.slot_code(self, scope)
class ConstructorSlot(InternalMethodSlot):
# Descriptor for tp_new and tp_dealloc.
def __init__(self, slot_name, method):
InternalMethodSlot.__init__(self, slot_name)
self.method = method
def slot_code(self, scope):
if scope.parent_type.base_type \
and not scope.has_pyobject_attrs \
and not scope.lookup_here(self.method):
# 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)
return InternalMethodSlot.slot_code(self, scope)
......@@ -558,7 +582,7 @@ PyBufferProcs = (
#------------------------------------------------------------------------------------------
slot_table = (
InternalMethodSlot("tp_dealloc"),
ConstructorSlot("tp_dealloc", '__dealloc__'),
EmptySlot("tp_print"), #MethodSlot(printfunc, "tp_print", "__print__"),
EmptySlot("tp_getattr"),
EmptySlot("tp_setattr"),
......@@ -606,7 +630,7 @@ slot_table = (
MethodSlot(initproc, "tp_init", "__init__"),
EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"),
InternalMethodSlot("tp_new"),
ConstructorSlot("tp_new", '__new__'),
EmptySlot("tp_free"),
EmptySlot("tp_is_gc"),
......
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