PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/pypy/pypy/
Python | 211 lines | 196 code | 12 blank | 3 comment | 8 complexity | 474d30d5de43b2015d4dfea435e8fd1e MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  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.codewriter import longlong
  7. from pypy.jit.metainterp import history, compile
  8. from pypy.jit.backend.x86.assembler import Assembler386
  9. from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS, IS_X86_32
  10. from pypy.jit.backend.x86.profagent import ProfileAgent
  11. from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
  12. from pypy.jit.backend.x86 import regloc
  13. import sys
  14. from pypy.tool.ansi_print import ansi_log
  15. log = py.log.Producer('jitbackend')
  16. py.log.setconsumer('jitbackend', ansi_log)
  17. class AbstractX86CPU(AbstractLLCPU):
  18. debug = True
  19. supports_floats = True
  20. supports_singlefloats = True
  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 get_latest_value_int(self, index):
  80. return self.assembler.fail_boxes_int.getitem(index)
  81. def get_latest_value_float(self, index):
  82. return self.assembler.fail_boxes_float.getitem(index)
  83. def get_latest_value_ref(self, index):
  84. return self.assembler.fail_boxes_ptr.getitem(index)
  85. def get_latest_value_count(self):
  86. return self.assembler.fail_boxes_count
  87. def clear_latest_values(self, count):
  88. setitem = self.assembler.fail_boxes_ptr.setitem
  89. null = lltype.nullptr(llmemory.GCREF.TO)
  90. for index in range(count):
  91. setitem(index, null)
  92. def get_latest_force_token(self):
  93. # the FORCE_TOKEN operation and this helper both return 'ebp'.
  94. return self.assembler.fail_ebp
  95. def make_execute_token(self, *ARGS):
  96. FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, lltype.Signed))
  97. #
  98. def execute_token(executable_token, *args):
  99. clt = executable_token.compiled_loop_token
  100. assert len(args) == clt._debug_nbargs
  101. #
  102. addr = executable_token._x86_function_addr
  103. func = rffi.cast(FUNCPTR, addr)
  104. #llop.debug_print(lltype.Void, ">>>> Entering", addr)
  105. prev_interpreter = None # help flow space
  106. if not self.translate_support_code:
  107. prev_interpreter = LLInterpreter.current_interpreter
  108. LLInterpreter.current_interpreter = self.debug_ll_interpreter
  109. try:
  110. fail_index = func(*args)
  111. finally:
  112. if not self.translate_support_code:
  113. LLInterpreter.current_interpreter = prev_interpreter
  114. #llop.debug_print(lltype.Void, "<<<< Back")
  115. return self.get_fail_descr_from_number(fail_index)
  116. return execute_token
  117. def cast_ptr_to_int(x):
  118. adr = llmemory.cast_ptr_to_adr(x)
  119. return CPU386.cast_adr_to_int(adr)
  120. cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)'
  121. cast_ptr_to_int = staticmethod(cast_ptr_to_int)
  122. all_null_registers = lltype.malloc(rffi.LONGP.TO,
  123. IS_X86_32 and (16+8) # 16 + 8 regs
  124. or (16+16), # 16 + 16 regs
  125. flavor='raw', zero=True,
  126. immortal=True)
  127. def force(self, addr_of_force_token):
  128. TP = rffi.CArrayPtr(lltype.Signed)
  129. addr_of_force_index = addr_of_force_token + FORCE_INDEX_OFS
  130. fail_index = rffi.cast(TP, addr_of_force_index)[0]
  131. assert fail_index >= 0, "already forced!"
  132. faildescr = self.get_fail_descr_from_number(fail_index)
  133. rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
  134. frb = self.assembler._find_failure_recovery_bytecode(faildescr)
  135. bytecode = rffi.cast(rffi.UCHARP, frb)
  136. # start of "no gc operation!" block
  137. fail_index_2 = self.assembler.grab_frame_values(
  138. bytecode,
  139. addr_of_force_token,
  140. self.all_null_registers)
  141. self.assembler.leave_jitted_hook()
  142. # end of "no gc operation!" block
  143. assert fail_index == fail_index_2
  144. return faildescr
  145. def redirect_call_assembler(self, oldlooptoken, newlooptoken):
  146. self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
  147. def invalidate_loop(self, looptoken):
  148. from pypy.jit.backend.x86 import codebuf
  149. for addr, tgt in looptoken.compiled_loop_token.invalidate_positions:
  150. mc = codebuf.MachineCodeBlockWrapper()
  151. mc.JMP_l(tgt)
  152. assert mc.get_relative_pos() == 5 # [JMP] [tgt 4 bytes]
  153. mc.copy_to_raw_memory(addr - 1)
  154. # positions invalidated
  155. looptoken.compiled_loop_token.invalidate_positions = []
  156. class CPU386(AbstractX86CPU):
  157. backend_name = 'x86'
  158. WORD = 4
  159. NUM_REGS = 8
  160. CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.esi, regloc.edi]
  161. supports_longlong = True
  162. def __init__(self, *args, **kwargs):
  163. assert sys.maxint == (2**31 - 1)
  164. super(CPU386, self).__init__(*args, **kwargs)
  165. class CPU386_NO_SSE2(CPU386):
  166. supports_floats = False
  167. supports_longlong = False
  168. class CPU_X86_64(AbstractX86CPU):
  169. backend_name = 'x86_64'
  170. WORD = 8
  171. NUM_REGS = 16
  172. CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15]
  173. def __init__(self, *args, **kwargs):
  174. assert sys.maxint == (2**63 - 1)
  175. super(CPU_X86_64, self).__init__(*args, **kwargs)
  176. CPU = CPU386