#!/usr/bin/env python import zz import sys import bisect class Dump(object): def __init__(self, filename=None): self.operations = [] self.argindex = {} self.boxcache = {} if filename is not None: self.load(filename) def load(self, filename): start = len(self.operations) f = open(filename) for line in f: self.operations.append(line.strip()) f.close() argindex = self.argindex for rev in range(start, len(self.operations)): opname, step, args = self.getop(rev) for arg in args: try: argindex[arg].append(rev) except KeyError: argindex[arg] = [rev] def getop(self, rev): line = self.operations[rev] fields = line.split(' ', 2) opname = fields[0] step = fields[1] if len(fields) == 2: args = [] else: args = fields[2].split('\t') return opname, step, args def getopcount(self): return len(self.operations) class RevBox(zz.Box): def __init__(self, dump, rev): opname, step, args = dump.getop(rev) zz.Box.__init__(self, '%d %s %s' % (rev, step, opname), bgcolor=(255,255,255)) self.key = dump, rev self.dump = dump self.rev = rev self.argboxes = {} box = self for i, arg in enumerate(args): box1 = ArgBox(dump, arg, rev, i) self.argboxes[arg] = box1 box.set_right(box1) box = box1 def up(self): if self.rev > 0: return RevBox(self.dump, self.rev - 1) else: return None def down(self): if self.rev < self.dump.getopcount() - 1: return RevBox(self.dump, self.rev + 1) else: return None def __hash__(self): return hash(self.key) def __cmp__(self, other): return cmp(self.key, other.key) class ArgBox(zz.Box): def __init__(self, dump, arg, rev, n): zz.Box.__init__(self, arg, bgcolor=(160,255,160)) self.key = dump, rev, n def __hash__(self): return hash(self.key) def __cmp__(self, other): return cmp(self.key, other.key) def findvlist(self): arg = self.text dump, rev, _ = self.key vlist = dump.argindex[arg] n = bisect.bisect_left(vlist, rev) return vlist, n def siblingbox(self, rev): arg = self.text dump = self.key[0] box = RevBox(dump, rev) return box.argboxes[arg] def up(self): vlist, n = self.findvlist() if n > 0: return self.siblingbox(vlist[n-1]) else: return None def down(self): vlist, n = self.findvlist() if n < len(vlist) - 1: return self.siblingbox(vlist[n+1]) else: return None class DumpGraph(zz.Graph): Width = 1000 Height = 720 StepX = 180 Cx = Width // 2 - StepX def show(dump): g = DumpGraph(RevBox(dump, dump.getopcount() - 1)) g.main() if __name__ == '__main__': if len(sys.argv) > 1: filename = sys.argv[1] else: filename = 'pypy-space-dump' show(Dump(filename))