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