diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 1e964c692c9aad14a313d4a007d56be501c3a438..9d3c22c74710b4ff7da8cb4d0172502310278d2d 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -2092,8 +2092,8 @@ class CCodeWriter(object): self.globalstate.use_utility_code( UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c")) - def put_trace_declarations(self): - self.putln('__Pyx_TraceDeclarations') + def put_trace_declarations(self, codeobj=None): + self.putln('__Pyx_TraceDeclarations(%s)' % (codeobj or 'NULL')) def put_trace_call(self, name, pos): self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1])) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index d5361547fc9a654a4c3d2760f7e709b4f92033d2..e2b2f2952b61246a077ef5e8f1011a70352eeb5a 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -8020,6 +8020,7 @@ class CodeObjectNode(ExprNode): subexprs = ['varnames'] is_temp = False + result_code = None def __init__(self, def_node): ExprNode.__init__(self, def_node.pos, def_node=def_node) @@ -8036,11 +8037,14 @@ class CodeObjectNode(ExprNode): def may_be_none(self): return False - def calculate_result_code(self): + def calculate_result_code(self, code=None): + if self.result_code is None: + self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) return self.result_code def generate_result_code(self, code): - self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) + if self.result_code is None: + self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) code = code.get_cached_constants_writer() code.mark_pos(self.pos) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 31f77c0a5f9733ad11a73950735a2aa40bef3da6..6ab35c50b85dd00bf7a2c30cb53cd2f88cfb2ac9 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1592,6 +1592,7 @@ class FuncDefNode(StatNode, BlockNode): star_arg = None starstar_arg = None is_cyfunction = False + code_object = None def analyse_default_values(self, env): default_seen = 0 @@ -1761,7 +1762,8 @@ class FuncDefNode(StatNode, BlockNode): self.generate_keyword_list(code) if profile or linetrace: - code.put_trace_declarations() + code_object = self.code_object.calculate_result_code(code) if self.code_object else None + code.put_trace_declarations(code_object) # ----- Extern library function declarations lenv.generate_library_function_declarations(code) diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 76e38e678a7f37aa03b3c6679254e312532cdc32..a4403101a9d0bb492bba8df3ca933fe12136ec74 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -1646,6 +1646,7 @@ if VALUE is not None: else: binding = self.current_directives.get('binding') rhs = ExprNodes.PyCFunctionNode.from_defnode(node, binding) + node.code_object = rhs.code_object if env.is_py_class_scope: rhs.binding = True diff --git a/Cython/Utility/Profile.c b/Cython/Utility/Profile.c index cf219b3c2c8602ef7f2432843b005203cceb845f..67d7340efaad1e54d08b65333c3f0431580dba5a 100644 --- a/Cython/Utility/Profile.c +++ b/Cython/Utility/Profile.c @@ -34,8 +34,8 @@ #define CYTHON_FRAME_DEL Py_CLEAR($frame_cname) #endif - #define __Pyx_TraceDeclarations \ - static PyCodeObject *$frame_code_cname = NULL; \ + #define __Pyx_TraceDeclarations(codeobj) \ + static PyCodeObject *$frame_code_cname = NULL; if (codeobj) $frame_code_cname = (PyCodeObject*) codeobj; \ CYTHON_FRAME_MODIFIER PyFrameObject *$frame_cname = NULL; \ int __Pyx_use_tracing = 0; @@ -81,7 +81,7 @@ #else - #define __Pyx_TraceDeclarations + #define __Pyx_TraceDeclarations(codeobj) #define __Pyx_TraceCall(funcname, srcfile, firstlineno) #define __Pyx_TraceException() #define __Pyx_TraceReturn(result)