Commits

Antonio Cuni committed 2aaa9b2

kill Function and slice_debug_merge_points, replace them by the versions found in the jitlogparser

Comments (0)

Files changed (3)

_jitviewer/parser.py

         else:
             return self.bytecode_name
 
-class Function(object):
-    filename = None
-    name = None
-    startlineno = 0
-    _linerange = None
-    _lineset = None
-    is_bytecode = False
-    inline_level = None
+class FunctionHtml(parser.Function):
+    TraceForOpcode = TraceForOpcodeHtml
     
-    def __init__(self, chunks, path, storage):
-        self.path = path
-        self.chunks = chunks
-        for chunk in self.chunks:
-            if chunk.filename is not None:
-                self.startlineno = chunk.startlineno
-                self.filename = chunk.filename
-                self.name = chunk.name
-                self.inline_level = chunk.inline_level
-                break
-        self.storage = storage
-
-    def getlinerange(self):
-        if self._linerange is None:
-            self._compute_linerange()
-        return self._linerange
-    linerange = property(getlinerange)
-
-    def getlineset(self):
-        if self._lineset is None:
-            self._compute_linerange()
-        return self._lineset
-    lineset = property(getlineset)
-
-    def _compute_linerange(self):
-        self._lineset = set()
-        minline = sys.maxint
-        maxline = -1
-        for chunk in self.chunks:
-            if chunk.is_bytecode and chunk.filename is not None:
-                lineno = chunk.lineno
-                minline = min(minline, lineno)
-                maxline = max(maxline, lineno)
-                if chunk.line_starts_here or len(chunk.operations) > 1:
-                    self._lineset.add(lineno)
-        if minline == sys.maxint:
-            minline = 0
-            maxline = 0
-        self._linerange = minline, maxline
-
     def html_repr(self):
         return "inlined call to %s in %s" % (self.name, self.filename)
 
-    def repr(self):
-        if self.filename is None:
-            return "Unknown"
-        return "%s, file '%s', line %d" % (self.name, self.filename,
-                                           self.startlineno)
-        
-    def __repr__(self):
-        return "[%s]" % ", ".join([repr(chunk) for chunk in self.chunks])
-
-    def pretty_print(self, out):
-        print >>out, "Loop starting at %s in %s at %d" % (self.name,
-                                        self.filename, self.startlineno)
-        lineno = -1
-        for chunk in self.chunks:
-            if chunk.filename is not None and chunk.lineno != lineno:
-                lineno = chunk.lineno
-                source = chunk.getcode().source[chunk.lineno -
-                                                chunk.startlineno]
-                print >>out, "  ", source
-            chunk.pretty_print(out)
 
 def parse_log_counts(input, loops):
     if not input:
     return ParserWithHtmlRepr(input, None, {}, 'lltype', None,
                               nonstrict=True).parse()
 
-def slice_debug_merge_points(operations, storage, limit=None):
-    """ Slice given operation list into a chain of Bytecode chunks.
-    Also detect inlined functions and make them Function
-    """
-    stack = []
-
-    def getpath(stack):
-        return ",".join([str(len(v)) for v in stack])
-
-    def append_to_res(bc):
-        if not stack:
-            stack.append([])
-        else:
-            if bc.inline_level is not None and bc.inline_level + 1 != len(stack):
-                if bc.inline_level < len(stack):
-                    last = stack.pop()
-                    stack[-1].append(Function(last, getpath(stack), storage))
-                else:
-                    stack.append([])
-        stack[-1].append(bc)
-
-    so_far = []
-    stack = []
-    for op in operations:
-        if op.name == 'debug_merge_point':
-            if so_far:
-                append_to_res(TraceForOpcodeHtml(so_far, storage))
-                if limit:
-                    break
-                so_far = []
-        so_far.append(op)
-    if so_far:
-        append_to_res(TraceForOpcodeHtml(so_far, storage))
-    # wrap stack back up
-    if not stack:
-        # no ops whatsoever
-        return Function([], getpath(stack), storage)
-    while True:
-        next = stack.pop()
-        if not stack:
-            return Function(next, getpath(stack), storage)
-        stack[-1].append(Function(next, getpath(stack), storage))
-
 def adjust_bridges(loop, bridges):
     """ Slice given loop according to given bridges to follow. Returns a plain
     list of operations.

_jitviewer/test/test_parser.py

 from pypy.tool.jitlogparser.storage import LoopStorage
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.history import ConstInt, Const
-from _jitviewer.parser import parse, TraceForOpcodeHtml, Function,\
-     slice_debug_merge_points,\
+from _jitviewer.parser import parse, TraceForOpcodeHtml, FunctionHtml,\
      adjust_bridges, parse_log_counts, cssclass
 import py
 
     []
     debug_merge_point("SomeRandomStuff", 0)
     ''')
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert len(res.chunks) == 1
     assert res.chunks[0].html_repr()
 
     debug_merge_point("<code object stuff, file '/I/dont/exist.py', line 200> #11 SUB", 0)
     i2 = int_add(i1, 1)
     ''')
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert len(res.chunks) == 3
     assert len(res.chunks[0].operations) == 1
     assert len(res.chunks[1].operations) == 2
     debug_merge_point('<code object inner, file 'source.py', line 9> #7 RETURN_VALUE', 1)
     debug_merge_point('<code object inlined_call, file 'source.py', line 12> #31 STORE_FAST', 0)
     """)
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert len(res.chunks) == 3 # two chunks + inlined call
     assert isinstance(res.chunks[0], TraceForOpcodeHtml)
-    assert isinstance(res.chunks[1], Function)
+    assert isinstance(res.chunks[1], FunctionHtml)
     assert isinstance(res.chunks[2], TraceForOpcodeHtml)
     assert res.chunks[1].path == "1"
     assert len(res.chunks[1].chunks) == 3
     debug_merge_point("<code object stuff, file '/I/dont/exist.py', line 202> #11 SUB", 0)
     i2 = int_add(i1, 1)
     ''')
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert res.repr() == res.chunks[0].repr()
     assert res.repr() == "stuff, file '/I/dont/exist.py', line 200"
     assert res.startlineno == 200
     debug_merge_point("<code object stuff, file '/I/dont/exist.py', line 202> #11 SUB", 0)
     i2 = int_add(i1, 1)
     ''')
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert res.repr() == res.chunks[1].repr()
 
 def test_lineno():
     debug_merge_point("<code object f, file '%(fname)s', line 2> #6 BINARY_ADD", 0)
     debug_merge_point("<code object f, file '%(fname)s', line 2> #7 RETURN_VALUE", 0)
     ''' % locals())
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert res.chunks[1].lineno == 3
 
 def test_linerange():
     debug_merge_point("<code object f, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
     debug_merge_point("<code object f, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
     ''' % locals())
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert res.linerange == (7, 9)
     assert res.lineset == set([7, 8, 9])
 
     guard_class(p6, 144264192, descr=<Guard2>)
     p12 = getfield_gc(p6, descr=<GcPtrFieldDescr pypy.objspace.std.iterobject.W_AbstractSeqIterObject.inst_w_seq 12>)
     """ % locals())
-    res = slice_debug_merge_points(ops.operations, LoopStorage())
+    res = FunctionHtml.from_operations(ops.operations, LoopStorage())
     assert res.lineset
 
 def test_reassign_loops():
     loop = parse("""
     debug_merge_point('StrLiteralSearch at 11/51 [17, 8, 3, 1, 1, 1, 1, 51, 0, 19, 51, 1]', 0)
     """)
-    ops = slice_debug_merge_points(loop.operations, LoopStorage())
+    ops = FunctionHtml.from_operations(loop.operations, LoopStorage())
     chunk = ops.chunks[0]
     assert chunk.bytecode_name == 'StrLiteralSearch'
 
 import flask
 import inspect
 from pypy.tool.logparser import parse_log_file, extract_category
-from _jitviewer.parser import (parse, slice_debug_merge_points, adjust_bridges,
+from _jitviewer.parser import (parse, FunctionHtml, adjust_bridges,
                    parse_log_counts)
 from _jitviewer.display import CodeRepr, CodeReprNoFile
 import _jitviewer
                 is_entry = True
             else:
                 is_entry = False
-            func = slice_debug_merge_points(loop.operations, self.storage,
-                                            limit=1)
+            func = FunctionHtml.from_operations(loop.operations, self.storage,
+                                                limit=1)
             func.count = getattr(loop, 'count', '?')
             loops.append((is_entry, index, func))
         loops.sort(lambda a, b: cmp(b[2].count, a[2].count))
         no = int(flask.request.args.get('no', '0'))
         orig_loop = self.storage.loops[no]
         ops = adjust_bridges(orig_loop, flask.request.args)
-        loop = slice_debug_merge_points(ops, self.storage)
+        loop = FunctionHtml.from_operations(ops, self.storage)
         path = flask.request.args.get('path', '').split(',')
         if path:
             up = '"' + ','.join(path[:-1]) + '"'