Index: ExprNodes.py =================================================================== RCS file: /usr/local/cvsroot/third_party/pyrex/Pyrex/Compiler/ExprNodes.py,v retrieving revision 1.8 diff -u -r1.8 ExprNodes.py --- ExprNodes.py 6 Feb 2007 23:46:28 -0000 1.8 +++ ExprNodes.py 24 Mar 2007 01:15:27 -0000 @@ -1209,6 +1209,25 @@ code.error_goto(self.pos))) +class AllocExtTypeNode (AtomicExprNode): + + type_name = None + + def analyse_types (self, env): + entry = env.lookup (self.type_name.name) + self.type = entry.type + self.is_temp = 1 + + def generate_result_code (self, code): + code.putln ( + '%s = __Pyx_FastExtensionConstructor(%s); if (!%s) %s' % ( + self.result_code, + self.type.typeptr_cname, + self.result_code, + code.error_goto(self.pos) + ) + ) + class SimpleCallNode(ExprNode): # Function call without keyword, * or ** args. # @@ -1224,8 +1243,36 @@ coerced_self = None arg_tuple = None + def constructor_check (self, function, env): + # check for __fast_init__ + if function.is_name: + entry = env.lookup (function.name) + if entry and isinstance (entry.type, PyrexTypes.PyExtensionType): + ext_type = entry.type + if ext_type.base_type is None: + # probe for __fast_init__ + entry = ext_type.scope.lookup ('__fast_init__') + if entry and isinstance (entry.type, PyrexTypes.CFuncType): + # phew, enough qualifying! + return ext_type + return None + def analyse_types(self, env): function = self.function + # probe for fast constructor + probe = self.constructor_check (function, env) + if probe: + # replace and thus: + # (arg0, arg1, ...) + # => + # type.__fast_init__ (AllocExtNode (type), arg0, arg1, ...) + env.use_utility_code(fast_extension_constructor_utility_code) + self.function = AttributeNode (self.pos, obj=function, attribute='__fast_init__') + arg0 = AllocExtTypeNode (self.pos, type_name=function) + self.args.insert (0, arg0) + # recurse with our automagically-replaced function and args + return self.analyse_types (env) + function.is_called = 1 self.function.analyse_types(env) if function.is_attribute and function.entry and function.entry.is_cmethod: @@ -3137,7 +3184,8 @@ Py_XDECREF(tb); return result; } -"""] +""" +] #------------------------------------------------------------------------------------ @@ -3213,6 +3261,24 @@ bad: Py_XDECREF(py_modname); return result; +} +"""] + +#------------------------------------------------------------------------------------ + +fast_extension_constructor_utility_code = [ +"""static PyObject *__Pyx_FastExtensionConstructor(PyTypeObject * tp); /*proto*/ +""",""" +static PyObject *__Pyx_FastExtensionConstructor(PyTypeObject * tp) +{ + PyObject * op; + op = (PyObject *) _PyObject_GC_New(tp); + if (!op) { + return op; + } else { + _PyObject_GC_TRACK(op); + } + return op; } """] Index: Nodes.py =================================================================== RCS file: /usr/local/cvsroot/third_party/pyrex/Pyrex/Compiler/Nodes.py,v retrieving revision 1.16 diff -u -r1.16 Nodes.py --- Nodes.py 6 Feb 2007 23:46:28 -0000 1.16 +++ Nodes.py 24 Mar 2007 01:15:27 -0000 @@ -614,6 +614,13 @@ "Suite attached to non-function declaration") name = name_declarator.name cname = name_declarator.cname + if name == '__fast_init__': + # quietly add a 'return self' statement to the end of __fast_init__ methods + if self.body is not None: + import ExprNodes + self.body.stats.append ( + ReturnStatNode ( + self.pos, value=ExprNodes.NameNode (self.pos, name='self'))) self.entry = env.declare_cfunction( name, type, self.pos, cname = cname, visibility = self.visibility,