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):
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]))
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
......@@ -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)
......
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