PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/jit/metainterp/graphpage.py

https://bitbucket.org/pypy/pypy/
Python | 213 lines | 188 code | 22 blank | 3 comment | 42 complexity | dfd6d496e7561c595e039806fbbecea8 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from pypy.translator.tool.graphpage import GraphPage
  2. from pypy.translator.tool.make_dot import DotGen
  3. from pypy.jit.metainterp.history import Box
  4. from pypy.jit.metainterp.resoperation import rop
  5. class SubGraph:
  6. def __init__(self, suboperations):
  7. self.suboperations = suboperations
  8. def get_operations(self):
  9. return self.suboperations
  10. def get_display_text(self):
  11. return None
  12. def display_procedures(procedures, errmsg=None, highlight_procedures={}, metainterp_sd=None):
  13. graphs = [(procedure, highlight_procedures.get(procedure, 0))
  14. for procedure in procedures]
  15. for graph, highlight in graphs:
  16. for op in graph.get_operations():
  17. if is_interesting_guard(op):
  18. graphs.append((SubGraph(op.getdescr()._debug_suboperations),
  19. highlight))
  20. graphpage = ResOpGraphPage(graphs, errmsg, metainterp_sd)
  21. graphpage.display()
  22. def is_interesting_guard(op):
  23. return hasattr(op.getdescr(), '_debug_suboperations')
  24. def getdescr(op):
  25. if op._descr is not None:
  26. return op._descr
  27. if hasattr(op, '_descr_wref'):
  28. return op._descr_wref()
  29. return None
  30. class ResOpGraphPage(GraphPage):
  31. def compute(self, graphs, errmsg=None, metainterp_sd=None):
  32. resopgen = ResOpGen(metainterp_sd)
  33. for graph, highlight in graphs:
  34. resopgen.add_graph(graph, highlight)
  35. if errmsg:
  36. resopgen.set_errmsg(errmsg)
  37. self.source = resopgen.getsource()
  38. self.links = resopgen.getlinks()
  39. class ResOpGen(object):
  40. CLUSTERING = True
  41. BOX_COLOR = (128, 0, 96)
  42. def __init__(self, metainterp_sd=None):
  43. self.graphs = []
  44. self.highlight_graphs = {}
  45. self.block_starters = {} # {graphindex: {set-of-operation-indices}}
  46. self.all_operations = {}
  47. self.errmsg = None
  48. self.target_tokens = {}
  49. self.metainterp_sd = metainterp_sd
  50. def op_name(self, graphindex, opindex):
  51. return 'g%dop%d' % (graphindex, opindex)
  52. def mark_starter(self, graphindex, opindex):
  53. self.block_starters[graphindex][opindex] = True
  54. def add_graph(self, graph, highlight=False):
  55. graphindex = len(self.graphs)
  56. self.graphs.append(graph)
  57. self.highlight_graphs[graph] = highlight
  58. for i, op in enumerate(graph.get_operations()):
  59. self.all_operations[op] = graphindex, i
  60. def find_starters(self):
  61. for graphindex in range(len(self.graphs)):
  62. self.block_starters[graphindex] = {0: True}
  63. for graphindex, graph in enumerate(self.graphs):
  64. mergepointblock = None
  65. for i, op in enumerate(graph.get_operations()):
  66. if is_interesting_guard(op):
  67. self.mark_starter(graphindex, i+1)
  68. if op.getopnum() == rop.DEBUG_MERGE_POINT:
  69. if mergepointblock is None:
  70. mergepointblock = i
  71. elif op.getopnum() == rop.LABEL:
  72. self.mark_starter(graphindex, i)
  73. self.target_tokens[getdescr(op)] = (graphindex, i)
  74. mergepointblock = i
  75. else:
  76. if mergepointblock is not None:
  77. self.mark_starter(graphindex, mergepointblock)
  78. mergepointblock = None
  79. def set_errmsg(self, errmsg):
  80. self.errmsg = errmsg
  81. def getsource(self):
  82. self.find_starters()
  83. self.pendingedges = []
  84. self.dotgen = DotGen('resop')
  85. self.dotgen.emit('clusterrank="local"')
  86. self.generrmsg()
  87. _prev = Box._extended_display
  88. try:
  89. Box._extended_display = False
  90. for i, graph in enumerate(self.graphs):
  91. self.gengraph(graph, i)
  92. finally:
  93. Box._extended_display = _prev
  94. # we generate the edges at the end of the file; otherwise, and edge
  95. # could mention a node before it's declared, and this can cause the
  96. # node declaration to occur too early -- in the wrong subgraph.
  97. for frm, to, kwds in self.pendingedges:
  98. self.dotgen.emit_edge(frm, to, **kwds)
  99. return self.dotgen.generate(target=None)
  100. def generrmsg(self):
  101. if self.errmsg:
  102. self.dotgen.emit_node('errmsg', label=self.errmsg,
  103. shape="box", fillcolor="red")
  104. if self.graphs and self.block_starters[0]:
  105. opindex = max(self.block_starters[0])
  106. blockname = self.op_name(0, opindex)
  107. self.pendingedges.append((blockname, 'errmsg', {}))
  108. def getgraphname(self, graphindex):
  109. return 'graph%d' % graphindex
  110. def gengraph(self, graph, graphindex):
  111. graphname = self.getgraphname(graphindex)
  112. if self.CLUSTERING:
  113. self.dotgen.emit('subgraph cluster%d {' % graphindex)
  114. label = graph.get_display_text()
  115. if label is not None:
  116. colorindex = self.highlight_graphs.get(graph, 0)
  117. if colorindex == 1:
  118. fillcolor = '#f084c2' # highlighted graph
  119. elif colorindex == 2:
  120. fillcolor = '#808080' # invalidated graph
  121. else:
  122. fillcolor = '#84f0c2' # normal color
  123. self.dotgen.emit_node(graphname, shape="octagon",
  124. label=label, fillcolor=fillcolor)
  125. self.pendingedges.append((graphname,
  126. self.op_name(graphindex, 0),
  127. {}))
  128. operations = graph.get_operations()
  129. for opindex in self.block_starters[graphindex]:
  130. self.genblock(operations, graphindex, opindex)
  131. if self.CLUSTERING:
  132. self.dotgen.emit('}') # closes the subgraph
  133. def genedge(self, frm, to, **kwds):
  134. self.pendingedges.append((self.op_name(*frm),
  135. self.op_name(*to),
  136. kwds))
  137. def genblock(self, operations, graphindex, opstartindex):
  138. if opstartindex >= len(operations):
  139. return
  140. blockname = self.op_name(graphindex, opstartindex)
  141. block_starters = self.block_starters[graphindex]
  142. lines = []
  143. opindex = opstartindex
  144. while True:
  145. op = operations[opindex]
  146. op_repr = op.repr(graytext=True)
  147. if op.getopnum() == rop.DEBUG_MERGE_POINT:
  148. jd_sd = self.metainterp_sd.jitdrivers_sd[op.getarg(0).getint()]
  149. if jd_sd._get_printable_location_ptr:
  150. s = jd_sd.warmstate.get_location_str(op.getarglist()[2:])
  151. s = s.replace(',', '.') # we use comma for argument splitting
  152. op_repr = "debug_merge_point(%d, '%s')" % (op.getarg(1).getint(), s)
  153. lines.append(op_repr)
  154. if is_interesting_guard(op):
  155. tgt = op.getdescr()._debug_suboperations[0]
  156. tgt_g, tgt_i = self.all_operations[tgt]
  157. self.genedge((graphindex, opstartindex),
  158. (tgt_g, tgt_i),
  159. color='red')
  160. opindex += 1
  161. if opindex >= len(operations):
  162. break
  163. if opindex in block_starters:
  164. self.genedge((graphindex, opstartindex),
  165. (graphindex, opindex))
  166. break
  167. if op.getopnum() == rop.JUMP:
  168. tgt_descr = getdescr(op)
  169. if tgt_descr is not None and tgt_descr in self.target_tokens:
  170. self.genedge((graphindex, opstartindex),
  171. self.target_tokens[tgt_descr],
  172. weight="0")
  173. lines.append("")
  174. label = "\\l".join(lines)
  175. kwds = {}
  176. #if op in self.highlightops:
  177. # kwds['color'] = 'red'
  178. # kwds['fillcolor'] = '#ffe8e8'
  179. self.dotgen.emit_node(blockname, shape="box", label=label, **kwds)
  180. def getlinks(self):
  181. boxes = {}
  182. for op in self.all_operations:
  183. args = op.getarglist() + [op.result]
  184. for box in args:
  185. if getattr(box, 'is_box', False):
  186. boxes[box] = True
  187. links = {}
  188. for box in boxes:
  189. links[str(box)] = repr(box), self.BOX_COLOR
  190. return links