PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/jit/metainterp/test/support.py

https://bitbucket.org/pypy/pypy/
Python | 299 lines | 236 code | 48 blank | 15 comment | 26 complexity | 5ffd7df6cf4f3bbf36c59bad177517a4 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py, sys
  2. from pypy.rpython.lltypesystem import lltype, llmemory
  3. from pypy.rpython.ootypesystem import ootype
  4. from pypy.jit.backend.llgraph import runner
  5. from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
  6. from pypy.jit.metainterp.warmstate import unspecialize_value
  7. from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
  8. from pypy.jit.metainterp import pyjitpl, history
  9. from pypy.jit.codewriter.policy import JitPolicy
  10. from pypy.jit.codewriter import codewriter, longlong
  11. from pypy.rlib.rfloat import isnan
  12. def _get_jitcodes(testself, CPUClass, func, values, type_system,
  13. supports_longlong=False, translationoptions={}, **kwds):
  14. from pypy.jit.codewriter import support
  15. class FakeJitCell(object):
  16. __product_token = None
  17. def get_procedure_token(self):
  18. return self.__product_token
  19. def set_procedure_token(self, token):
  20. self.__product_token = token
  21. class FakeWarmRunnerState(object):
  22. def attach_procedure_to_interp(self, greenkey, procedure_token):
  23. cell = self.jit_cell_at_key(greenkey)
  24. cell.set_procedure_token(procedure_token)
  25. def helper_func(self, FUNCPTR, func):
  26. from pypy.rpython.annlowlevel import llhelper
  27. return llhelper(FUNCPTR, func)
  28. def get_location_str(self, args):
  29. return 'location'
  30. def jit_cell_at_key(self, greenkey):
  31. assert greenkey == []
  32. return self._cell
  33. _cell = FakeJitCell()
  34. trace_limit = sys.maxint
  35. enable_opts = ALL_OPTS_DICT
  36. func._jit_unroll_safe_ = True
  37. rtyper = support.annotate(func, values, type_system=type_system,
  38. translationoptions=translationoptions)
  39. graphs = rtyper.annotator.translator.graphs
  40. testself.all_graphs = graphs
  41. result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
  42. class FakeJitDriverSD:
  43. num_green_args = 0
  44. portal_graph = graphs[0]
  45. virtualizable_info = None
  46. greenfield_info = None
  47. result_type = result_kind
  48. portal_runner_ptr = "???"
  49. stats = history.Stats()
  50. cpu = CPUClass(rtyper, stats, None, False)
  51. cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
  52. cw.debug = True
  53. testself.cw = cw
  54. policy = JitPolicy()
  55. policy.set_supports_floats(True)
  56. policy.set_supports_longlong(supports_longlong)
  57. cw.find_all_graphs(policy)
  58. #
  59. testself.warmrunnerstate = FakeWarmRunnerState()
  60. testself.warmrunnerstate.cpu = cpu
  61. FakeJitDriverSD.warmstate = testself.warmrunnerstate
  62. if hasattr(testself, 'finish_setup_for_interp_operations'):
  63. testself.finish_setup_for_interp_operations()
  64. #
  65. cw.make_jitcodes(verbose=True)
  66. def _run_with_blackhole(testself, args):
  67. from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
  68. cw = testself.cw
  69. blackholeinterpbuilder = BlackholeInterpBuilder(cw)
  70. blackholeinterp = blackholeinterpbuilder.acquire_interp()
  71. count_i = count_r = count_f = 0
  72. for value in args:
  73. T = lltype.typeOf(value)
  74. if T == lltype.Signed:
  75. blackholeinterp.setarg_i(count_i, value)
  76. count_i += 1
  77. elif T == llmemory.GCREF:
  78. blackholeinterp.setarg_r(count_r, value)
  79. count_r += 1
  80. elif T == lltype.Float:
  81. value = longlong.getfloatstorage(value)
  82. blackholeinterp.setarg_f(count_f, value)
  83. count_f += 1
  84. else:
  85. raise TypeError(T)
  86. [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
  87. blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
  88. blackholeinterp.run()
  89. return blackholeinterp._final_result_anytype()
  90. def _run_with_pyjitpl(testself, args):
  91. class DoneWithThisFrame(Exception):
  92. pass
  93. class DoneWithThisFrameRef(DoneWithThisFrame):
  94. def __init__(self, cpu, *args):
  95. DoneWithThisFrame.__init__(self, *args)
  96. cw = testself.cw
  97. opt = history.Options(listops=True)
  98. metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
  99. metainterp_sd.finish_setup(cw)
  100. [jitdriver_sd] = metainterp_sd.jitdrivers_sd
  101. metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
  102. metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
  103. metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
  104. metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
  105. testself.metainterp = metainterp
  106. try:
  107. metainterp.compile_and_run_once(jitdriver_sd, *args)
  108. except DoneWithThisFrame, e:
  109. #if conftest.option.view:
  110. # metainterp.stats.view()
  111. return e.args[0]
  112. else:
  113. raise Exception("FAILED")
  114. def _run_with_machine_code(testself, args):
  115. metainterp = testself.metainterp
  116. num_green_args = metainterp.jitdriver_sd.num_green_args
  117. procedure_token = metainterp.get_procedure_token(args[:num_green_args])
  118. # a loop was successfully created by _run_with_pyjitpl(); call it
  119. cpu = metainterp.cpu
  120. args1 = []
  121. for i in range(len(args) - num_green_args):
  122. x = args[num_green_args + i]
  123. args1.append(unspecialize_value(x))
  124. faildescr = cpu.execute_token(procedure_token, *args1)
  125. assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
  126. if metainterp.jitdriver_sd.result_type == history.INT:
  127. return cpu.get_latest_value_int(0)
  128. elif metainterp.jitdriver_sd.result_type == history.REF:
  129. return cpu.get_latest_value_ref(0)
  130. elif metainterp.jitdriver_sd.result_type == history.FLOAT:
  131. return cpu.get_latest_value_float(0)
  132. else:
  133. return None
  134. class JitMixin:
  135. basic = True
  136. def check_resops(self, expected=None, **check):
  137. get_stats().check_resops(expected=expected, **check)
  138. def check_simple_loop(self, expected=None, **check):
  139. get_stats().check_simple_loop(expected=expected, **check)
  140. def check_trace_count(self, count): # was check_loop_count
  141. # The number of traces compiled
  142. assert get_stats().compiled_count == count
  143. def check_trace_count_at_most(self, count):
  144. assert get_stats().compiled_count <= count
  145. def check_jitcell_token_count(self, count): # was check_tree_loop_count
  146. assert len(get_stats().jitcell_token_wrefs) == count
  147. def check_target_token_count(self, count):
  148. tokens = get_stats().get_all_jitcell_tokens()
  149. n = sum ([len(t.target_tokens) for t in tokens])
  150. assert n == count
  151. def check_enter_count(self, count):
  152. assert get_stats().enter_count == count
  153. def check_enter_count_at_most(self, count):
  154. assert get_stats().enter_count <= count
  155. def check_jumps(self, maxcount):
  156. return # FIXME
  157. assert get_stats().exec_jumps <= maxcount
  158. def check_aborted_count(self, count):
  159. assert get_stats().aborted_count == count
  160. def check_aborted_count_at_least(self, count):
  161. assert get_stats().aborted_count >= count
  162. def meta_interp(self, *args, **kwds):
  163. kwds['CPUClass'] = self.CPUClass
  164. kwds['type_system'] = self.type_system
  165. if "backendopt" not in kwds:
  166. kwds["backendopt"] = False
  167. old = codewriter.CodeWriter.debug
  168. try:
  169. codewriter.CodeWriter.debug = True
  170. return ll_meta_interp(*args, **kwds)
  171. finally:
  172. codewriter.CodeWriter.debug = old
  173. def interp_operations(self, f, args, **kwds):
  174. # get the JitCodes for the function f
  175. _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
  176. # try to run it with blackhole.py
  177. result1 = _run_with_blackhole(self, args)
  178. # try to run it with pyjitpl.py
  179. result2 = _run_with_pyjitpl(self, args)
  180. assert result1 == result2 or isnan(result1) and isnan(result2)
  181. # try to run it by running the code compiled just before
  182. result3 = _run_with_machine_code(self, args)
  183. assert result1 == result3 or result3 == NotImplemented or isnan(result1) and isnan(result3)
  184. #
  185. if (longlong.supports_longlong and
  186. isinstance(result1, longlong.r_float_storage)):
  187. result1 = longlong.getrealfloat(result1)
  188. return result1
  189. def check_history(self, expected=None, **isns):
  190. # this can be used after calling meta_interp
  191. get_stats().check_history(expected, **isns)
  192. def check_operations_history(self, expected=None, **isns):
  193. # this can be used after interp_operations
  194. if expected is not None:
  195. expected = dict(expected)
  196. expected['finish'] = 1
  197. self.metainterp.staticdata.stats.check_history(expected, **isns)
  198. class LLJitMixin(JitMixin):
  199. type_system = 'lltype'
  200. CPUClass = runner.LLtypeCPU
  201. @staticmethod
  202. def Ptr(T):
  203. return lltype.Ptr(T)
  204. @staticmethod
  205. def GcStruct(name, *fields, **kwds):
  206. S = lltype.GcStruct(name, *fields, **kwds)
  207. return S
  208. malloc = staticmethod(lltype.malloc)
  209. nullptr = staticmethod(lltype.nullptr)
  210. @staticmethod
  211. def malloc_immortal(T):
  212. return lltype.malloc(T, immortal=True)
  213. def _get_NODE(self):
  214. NODE = lltype.GcForwardReference()
  215. NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
  216. ('next', lltype.Ptr(NODE))))
  217. return NODE
  218. class OOJitMixin(JitMixin):
  219. type_system = 'ootype'
  220. #CPUClass = runner.OOtypeCPU
  221. def setup_class(cls):
  222. py.test.skip("ootype tests skipped for now")
  223. @staticmethod
  224. def Ptr(T):
  225. return T
  226. @staticmethod
  227. def GcStruct(name, *fields, **kwds):
  228. if 'hints' in kwds:
  229. kwds['_hints'] = kwds['hints']
  230. del kwds['hints']
  231. I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
  232. return I
  233. malloc = staticmethod(ootype.new)
  234. nullptr = staticmethod(ootype.null)
  235. @staticmethod
  236. def malloc_immortal(T):
  237. return ootype.new(T)
  238. def _get_NODE(self):
  239. NODE = ootype.Instance('NODE', ootype.ROOT, {})
  240. NODE._add_fields({'value': ootype.Signed,
  241. 'next': NODE})
  242. return NODE
  243. # ____________________________________________________________
  244. class _Foo:
  245. pass
  246. def noConst(x):
  247. """Helper function for tests, returning 'x' as a BoxInt/BoxPtr
  248. even if it is a ConstInt/ConstPtr."""
  249. f1 = _Foo(); f2 = _Foo()
  250. f1.x = x; f2.x = 0
  251. return f1.x