Commit b42e181f authored by Robert Bradshaw's avatar Robert Bradshaw

Enable line profiling for Robert Kern's line_profiler.

The profiler filters lines on the function's __code__ attribute, which
must agree with that created in the profile frame.  Unfortunately, this
makes it difficult to profile anything but 'def' functions.
parent 4e6a23c0
...@@ -2092,8 +2092,8 @@ class CCodeWriter(object): ...@@ -2092,8 +2092,8 @@ class CCodeWriter(object):
self.globalstate.use_utility_code( self.globalstate.use_utility_code(
UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c")) UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c"))
def put_trace_declarations(self): def put_trace_declarations(self, codeobj=None):
self.putln('__Pyx_TraceDeclarations') self.putln('__Pyx_TraceDeclarations(%s)' % (codeobj or 'NULL'))
def put_trace_call(self, name, pos): 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])) self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]))
......
...@@ -8020,6 +8020,7 @@ class CodeObjectNode(ExprNode): ...@@ -8020,6 +8020,7 @@ class CodeObjectNode(ExprNode):
subexprs = ['varnames'] subexprs = ['varnames']
is_temp = False is_temp = False
result_code = None
def __init__(self, def_node): def __init__(self, def_node):
ExprNode.__init__(self, def_node.pos, def_node=def_node) ExprNode.__init__(self, def_node.pos, def_node=def_node)
...@@ -8036,10 +8037,13 @@ class CodeObjectNode(ExprNode): ...@@ -8036,10 +8037,13 @@ class CodeObjectNode(ExprNode):
def may_be_none(self): def may_be_none(self):
return False 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 return self.result_code
def generate_result_code(self, code): def generate_result_code(self, code):
if self.result_code is None:
self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2)
code = code.get_cached_constants_writer() code = code.get_cached_constants_writer()
......
...@@ -1592,6 +1592,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1592,6 +1592,7 @@ class FuncDefNode(StatNode, BlockNode):
star_arg = None star_arg = None
starstar_arg = None starstar_arg = None
is_cyfunction = False is_cyfunction = False
code_object = None
def analyse_default_values(self, env): def analyse_default_values(self, env):
default_seen = 0 default_seen = 0
...@@ -1761,7 +1762,8 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1761,7 +1762,8 @@ class FuncDefNode(StatNode, BlockNode):
self.generate_keyword_list(code) self.generate_keyword_list(code)
if profile or linetrace: 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 # ----- Extern library function declarations
lenv.generate_library_function_declarations(code) lenv.generate_library_function_declarations(code)
......
...@@ -1646,6 +1646,7 @@ if VALUE is not None: ...@@ -1646,6 +1646,7 @@ if VALUE is not None:
else: else:
binding = self.current_directives.get('binding') binding = self.current_directives.get('binding')
rhs = ExprNodes.PyCFunctionNode.from_defnode(node, binding) rhs = ExprNodes.PyCFunctionNode.from_defnode(node, binding)
node.code_object = rhs.code_object
if env.is_py_class_scope: if env.is_py_class_scope:
rhs.binding = True rhs.binding = True
......
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
#define CYTHON_FRAME_DEL Py_CLEAR($frame_cname) #define CYTHON_FRAME_DEL Py_CLEAR($frame_cname)
#endif #endif
#define __Pyx_TraceDeclarations \ #define __Pyx_TraceDeclarations(codeobj) \
static PyCodeObject *$frame_code_cname = NULL; \ static PyCodeObject *$frame_code_cname = NULL; if (codeobj) $frame_code_cname = (PyCodeObject*) codeobj; \
CYTHON_FRAME_MODIFIER PyFrameObject *$frame_cname = NULL; \ CYTHON_FRAME_MODIFIER PyFrameObject *$frame_cname = NULL; \
int __Pyx_use_tracing = 0; int __Pyx_use_tracing = 0;
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
#else #else
#define __Pyx_TraceDeclarations #define __Pyx_TraceDeclarations(codeobj)
#define __Pyx_TraceCall(funcname, srcfile, firstlineno) #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
#define __Pyx_TraceException() #define __Pyx_TraceException()
#define __Pyx_TraceReturn(result) #define __Pyx_TraceReturn(result)
......
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