PageRenderTime 70ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/codewriter/codewriter.py

https://bitbucket.org/pypy/pypy/
Python | 115 lines | 78 code | 10 blank | 27 comment | 10 complexity | 4779d0e0a3a47f7b43c4e857224a96e9 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.jit.codewriter import support, heaptracker
  2. from rpython.jit.codewriter.regalloc import perform_register_allocation
  3. from rpython.jit.codewriter.flatten import flatten_graph, KINDS
  4. from rpython.jit.codewriter.assembler import Assembler, JitCode
  5. from rpython.jit.codewriter.jtransform import transform_graph
  6. from rpython.jit.codewriter.format import format_assembler
  7. from rpython.jit.codewriter.liveness import compute_liveness
  8. from rpython.jit.codewriter.call import CallControl
  9. from rpython.jit.codewriter.policy import log
  10. from rpython.flowspace.model import copygraph
  11. from rpython.tool.udir import udir
  12. class CodeWriter(object):
  13. callcontrol = None # for tests
  14. debug = True
  15. def __init__(self, cpu=None, jitdrivers_sd=[]):
  16. self.cpu = cpu
  17. self.assembler = Assembler()
  18. self.callcontrol = CallControl(cpu, jitdrivers_sd)
  19. def transform_func_to_jitcode(self, func, values):
  20. """For testing."""
  21. rtyper = support.annotate(func, values)
  22. graph = rtyper.annotator.translator.graphs[0]
  23. jitcode = JitCode("test")
  24. self.transform_graph_to_jitcode(graph, jitcode, True, 0)
  25. return jitcode
  26. def transform_graph_to_jitcode(self, graph, jitcode, verbose, index):
  27. """Transform a graph into a JitCode containing the same bytecode
  28. in a different format.
  29. """
  30. portal_jd = self.callcontrol.jitdriver_sd_from_portal_graph(graph)
  31. graph = copygraph(graph, shallowvars=True)
  32. #
  33. # step 1: mangle the graph so that it contains the final instructions
  34. # that we want in the JitCode, but still as a control flow graph
  35. transform_graph(graph, self.cpu, self.callcontrol, portal_jd)
  36. #
  37. # step 2: perform register allocation on it
  38. regallocs = {}
  39. for kind in KINDS:
  40. regallocs[kind] = perform_register_allocation(graph, kind)
  41. #
  42. # step 3: flatten the graph to produce human-readable "assembler",
  43. # which means mostly producing a linear list of operations and
  44. # inserting jumps or conditional jumps. This is a list of tuples
  45. # of the shape ("opname", arg1, ..., argN) or (Label(...),).
  46. ssarepr = flatten_graph(graph, regallocs, cpu=self.callcontrol.cpu)
  47. #
  48. # step 3b: compute the liveness around certain operations
  49. compute_liveness(ssarepr)
  50. #
  51. # step 4: "assemble" it into a JitCode, which contains a sequence
  52. # of bytes and lists of constants. It's during this step that
  53. # constants are cast to their normalized type (Signed, GCREF or
  54. # Float).
  55. self.assembler.assemble(ssarepr, jitcode)
  56. jitcode.index = index
  57. #
  58. # print the resulting assembler
  59. if self.debug:
  60. self.print_ssa_repr(ssarepr, portal_jd, verbose)
  61. def make_jitcodes(self, verbose=False):
  62. log.info("making JitCodes...")
  63. self.callcontrol.grab_initial_jitcodes()
  64. count = 0
  65. all_jitcodes = []
  66. for graph, jitcode in self.callcontrol.enum_pending_graphs():
  67. self.transform_graph_to_jitcode(graph, jitcode, verbose, len(all_jitcodes))
  68. all_jitcodes.append(jitcode)
  69. count += 1
  70. if not count % 500:
  71. log.info("Produced %d jitcodes" % count)
  72. self.assembler.finished(self.callcontrol.callinfocollection)
  73. log.info("there are %d JitCode instances." % count)
  74. return all_jitcodes
  75. def setup_vrefinfo(self, vrefinfo):
  76. # must be called at most once
  77. assert self.callcontrol.virtualref_info is None
  78. self.callcontrol.virtualref_info = vrefinfo
  79. def setup_jitdriver(self, jitdriver_sd):
  80. # Must be called once per jitdriver. Usually jitdriver_sd is an
  81. # instance of rpython.jit.metainterp.jitdriver.JitDriverStaticData.
  82. self.callcontrol.jitdrivers_sd.append(jitdriver_sd)
  83. def find_all_graphs(self, policy):
  84. return self.callcontrol.find_all_graphs(policy)
  85. def print_ssa_repr(self, ssarepr, portal_jitdriver, verbose):
  86. if verbose:
  87. print '%s:' % (ssarepr.name,)
  88. print format_assembler(ssarepr)
  89. else:
  90. log.dot()
  91. dir = udir.ensure("jitcodes", dir=1)
  92. if portal_jitdriver:
  93. name = "%02d_portal_runner" % (portal_jitdriver.index,)
  94. elif ssarepr.name and ssarepr.name != '?':
  95. name = ssarepr.name
  96. else:
  97. name = 'unnamed' % id(ssarepr)
  98. i = 1
  99. # escape <lambda> names for windows
  100. name = name.replace('<lambda>', '_(lambda)_')
  101. extra = ''
  102. while dir.join(name+extra).check():
  103. i += 1
  104. extra = '.%d' % i
  105. dir.join(name+extra).write(format_assembler(ssarepr))