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

/pypy/jit/backend/x86/runner.py

https://bitbucket.org/jterrace/pypy
Python | 217 lines | 202 code | 12 blank | 3 comment | 8 complexity | 9ea291f10b93d1af1e1b62390e5405da MD5 | raw file
  1. import py
  2. from pypy.rpython.lltypesystem import lltype, llmemory, rffi
  3. from pypy.rpython.lltypesystem.lloperation import llop
  4. from pypy.rpython.llinterp import LLInterpreter
  5. from pypy.rlib.objectmodel import we_are_translated
  6. from pypy.jit.metainterp import history, compile
  7. from pypy.jit.backend.x86.assembler import Assembler386
  8. from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS
  9. from pypy.jit.backend.x86.profagent import ProfileAgent
  10. from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
  11. from pypy.jit.backend.x86 import regloc
  12. import sys
  13. from pypy.tool.ansi_print import ansi_log
  14. log = py.log.Producer('jitbackend')
  15. py.log.setconsumer('jitbackend', ansi_log)
  16. class AbstractX86CPU(AbstractLLCPU):
  17. debug = True
  18. supports_floats = True
  19. supports_singlefloats = True
  20. BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed)
  21. dont_keepalive_stuff = False # for tests
  22. with_threads = False
  23. def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
  24. gcdescr=None):
  25. if gcdescr is not None:
  26. gcdescr.force_index_ofs = FORCE_INDEX_OFS
  27. AbstractLLCPU.__init__(self, rtyper, stats, opts,
  28. translate_support_code, gcdescr)
  29. profile_agent = ProfileAgent()
  30. if rtyper is not None:
  31. config = rtyper.annotator.translator.config
  32. if config.translation.jit_profiler == "oprofile":
  33. from pypy.jit.backend.x86 import oprofile
  34. if not oprofile.OPROFILE_AVAILABLE:
  35. log.WARNING('oprofile support was explicitly enabled, but oprofile headers seem not to be available')
  36. profile_agent = oprofile.OProfileAgent()
  37. self.with_threads = config.translation.thread
  38. self.profile_agent = profile_agent
  39. def setup(self):
  40. if self.opts is not None:
  41. failargs_limit = self.opts.failargs_limit
  42. else:
  43. failargs_limit = 1000
  44. self.assembler = Assembler386(self, self.translate_support_code,
  45. failargs_limit)
  46. def get_on_leave_jitted_hook(self):
  47. return self.assembler.leave_jitted_hook
  48. def setup_once(self):
  49. self.profile_agent.startup()
  50. self.assembler.setup_once()
  51. def finish_once(self):
  52. self.assembler.finish_once()
  53. self.profile_agent.shutdown()
  54. def dump_loop_token(self, looptoken):
  55. """
  56. NOT_RPYTHON
  57. """
  58. from pypy.jit.backend.x86.tool.viewcode import machine_code_dump
  59. data = []
  60. label_list = [(offset, name) for name, offset in
  61. looptoken._x86_ops_offset.iteritems()]
  62. label_list.sort()
  63. addr = looptoken._x86_rawstart
  64. src = rffi.cast(rffi.CCHARP, addr)
  65. for p in range(looptoken._x86_fullsize):
  66. data.append(src[p])
  67. data = ''.join(data)
  68. lines = machine_code_dump(data, addr, self.backend_name, label_list)
  69. print ''.join(lines)
  70. def compile_loop(self, inputargs, operations, looptoken, log=True, name=''):
  71. return self.assembler.assemble_loop(name, inputargs, operations,
  72. looptoken, log=log)
  73. def compile_bridge(self, faildescr, inputargs, operations,
  74. original_loop_token, log=True):
  75. clt = original_loop_token.compiled_loop_token
  76. clt.compiling_a_bridge()
  77. return self.assembler.assemble_bridge(faildescr, inputargs, operations,
  78. original_loop_token, log=log)
  79. def set_future_value_int(self, index, intvalue):
  80. self.assembler.fail_boxes_int.setitem(index, intvalue)
  81. def set_future_value_float(self, index, floatvalue):
  82. self.assembler.fail_boxes_float.setitem(index, floatvalue)
  83. def set_future_value_ref(self, index, ptrvalue):
  84. self.assembler.fail_boxes_ptr.setitem(index, ptrvalue)
  85. def get_latest_value_int(self, index):
  86. return self.assembler.fail_boxes_int.getitem(index)
  87. def get_latest_value_float(self, index):
  88. return self.assembler.fail_boxes_float.getitem(index)
  89. def get_latest_value_ref(self, index):
  90. return self.assembler.fail_boxes_ptr.getitem(index)
  91. def get_latest_value_count(self):
  92. return self.assembler.fail_boxes_count
  93. def clear_latest_values(self, count):
  94. setitem = self.assembler.fail_boxes_ptr.setitem
  95. null = lltype.nullptr(llmemory.GCREF.TO)
  96. for index in range(count):
  97. setitem(index, null)
  98. def get_latest_force_token(self):
  99. # the FORCE_TOKEN operation and this helper both return 'ebp'.
  100. return self.assembler.fail_ebp
  101. def execute_token(self, executable_token):
  102. addr = executable_token._x86_bootstrap_code
  103. #llop.debug_print(lltype.Void, ">>>> Entering", addr)
  104. func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr)
  105. fail_index = self._execute_call(func)
  106. #llop.debug_print(lltype.Void, "<<<< Back")
  107. return self.get_fail_descr_from_number(fail_index)
  108. def _execute_call(self, func):
  109. # help flow objspace
  110. prev_interpreter = None
  111. if not self.translate_support_code:
  112. prev_interpreter = LLInterpreter.current_interpreter
  113. LLInterpreter.current_interpreter = self.debug_ll_interpreter
  114. res = 0
  115. try:
  116. res = func()
  117. finally:
  118. if not self.translate_support_code:
  119. LLInterpreter.current_interpreter = prev_interpreter
  120. return res
  121. def cast_ptr_to_int(x):
  122. adr = llmemory.cast_ptr_to_adr(x)
  123. return CPU386.cast_adr_to_int(adr)
  124. cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)'
  125. cast_ptr_to_int = staticmethod(cast_ptr_to_int)
  126. all_null_registers = lltype.malloc(rffi.LONGP.TO, 24,
  127. flavor='raw', zero=True,
  128. immortal=True)
  129. def force(self, addr_of_force_token):
  130. TP = rffi.CArrayPtr(lltype.Signed)
  131. addr_of_force_index = addr_of_force_token + FORCE_INDEX_OFS
  132. fail_index = rffi.cast(TP, addr_of_force_index)[0]
  133. assert fail_index >= 0, "already forced!"
  134. faildescr = self.get_fail_descr_from_number(fail_index)
  135. rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
  136. frb = self.assembler._find_failure_recovery_bytecode(faildescr)
  137. bytecode = rffi.cast(rffi.UCHARP, frb)
  138. # start of "no gc operation!" block
  139. fail_index_2 = self.assembler.grab_frame_values(
  140. bytecode,
  141. addr_of_force_token,
  142. self.all_null_registers)
  143. self.assembler.leave_jitted_hook()
  144. # end of "no gc operation!" block
  145. assert fail_index == fail_index_2
  146. return faildescr
  147. def redirect_call_assembler(self, oldlooptoken, newlooptoken):
  148. self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
  149. def invalidate_loop(self, looptoken):
  150. from pypy.jit.backend.x86 import codebuf
  151. for addr, tgt in looptoken.compiled_loop_token.invalidate_positions:
  152. mc = codebuf.MachineCodeBlockWrapper()
  153. mc.JMP_l(tgt)
  154. assert mc.get_relative_pos() == 5 # [JMP] [tgt 4 bytes]
  155. mc.copy_to_raw_memory(addr - 1)
  156. # positions invalidated
  157. looptoken.compiled_loop_token.invalidate_positions = []
  158. class CPU386(AbstractX86CPU):
  159. backend_name = 'x86'
  160. WORD = 4
  161. NUM_REGS = 8
  162. CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.esi, regloc.edi]
  163. supports_longlong = True
  164. def __init__(self, *args, **kwargs):
  165. assert sys.maxint == (2**31 - 1)
  166. super(CPU386, self).__init__(*args, **kwargs)
  167. class CPU386_NO_SSE2(CPU386):
  168. supports_floats = False
  169. supports_longlong = False
  170. class CPU_X86_64(AbstractX86CPU):
  171. backend_name = 'x86_64'
  172. WORD = 8
  173. NUM_REGS = 16
  174. CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15]
  175. def __init__(self, *args, **kwargs):
  176. assert sys.maxint == (2**63 - 1)
  177. super(CPU_X86_64, self).__init__(*args, **kwargs)
  178. CPU = CPU386