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

/rpython/rlib/test/test_jit.py

https://bitbucket.org/pypy/pypy/
Python | 311 lines | 267 code | 37 blank | 7 comment | 18 complexity | 24cda03193686ad81f068bf28d3ff579 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py, pytest
  2. from rpython.conftest import option
  3. from rpython.annotator.model import UnionError
  4. from rpython.rlib.jit import (hint, we_are_jitted, JitDriver, elidable_promote,
  5. JitHintError, oopspec, isconstant, conditional_call,
  6. elidable, unroll_safe, dont_look_inside,
  7. enter_portal_frame, leave_portal_frame)
  8. from rpython.rlib.rarithmetic import r_uint
  9. from rpython.rtyper.test.tool import BaseRtypingTest
  10. from rpython.rtyper.lltypesystem import lltype
  11. from rpython.translator.translator import TranslationContext
  12. from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
  13. from rpython.annotator import model as annmodel
  14. def test_oopspec():
  15. @oopspec('foobar')
  16. def fn():
  17. pass
  18. assert fn.oopspec == 'foobar'
  19. def test_jitdriver_autoreds():
  20. driver = JitDriver(greens=['foo'], reds='auto')
  21. assert driver.autoreds
  22. assert driver.reds == []
  23. assert driver.numreds is None
  24. py.test.raises(TypeError, "driver.can_enter_jit(foo='something')")
  25. py.test.raises(AssertionError, "JitDriver(greens=['foo'], reds='auto', confirm_enter_jit='something')")
  26. def test_jitdriver_numreds():
  27. driver = JitDriver(greens=['foo'], reds=['a', 'b'])
  28. assert driver.reds == ['a', 'b']
  29. assert driver.numreds == 2
  30. #
  31. class MyJitDriver(JitDriver):
  32. greens = ['foo']
  33. reds = ['a', 'b']
  34. driver = MyJitDriver()
  35. assert driver.reds == ['a', 'b']
  36. assert driver.numreds == 2
  37. def test_jitdriver_inline():
  38. py.test.skip("@inline off: see skipped failures in test_warmspot.")
  39. driver = JitDriver(greens=[], reds='auto')
  40. calls = []
  41. def foo(a, b):
  42. calls.append(('foo', a, b))
  43. @driver.inline(foo)
  44. def bar(a, b):
  45. calls.append(('bar', a, b))
  46. return a+b
  47. assert bar._inline_jit_merge_point_ is foo
  48. assert driver.inline_jit_merge_point
  49. assert bar(40, 2) == 42
  50. assert calls == [
  51. ('foo', 40, 2),
  52. ('bar', 40, 2),
  53. ]
  54. def test_jitdriver_clone():
  55. py.test.skip("@inline off: see skipped failures in test_warmspot.")
  56. def bar(): pass
  57. def foo(): pass
  58. driver = JitDriver(greens=[], reds=[])
  59. py.test.raises(AssertionError, "driver.inline(bar)(foo)")
  60. #
  61. driver = JitDriver(greens=[], reds='auto')
  62. py.test.raises(AssertionError, "driver.clone()")
  63. foo = driver.inline(bar)(foo)
  64. assert foo._inline_jit_merge_point_ == bar
  65. #
  66. driver.foo = 'bar'
  67. driver2 = driver.clone()
  68. assert driver is not driver2
  69. assert driver2.foo == 'bar'
  70. driver.foo = 'xxx'
  71. assert driver2.foo == 'bar'
  72. def test_merge_enter_different():
  73. myjitdriver = JitDriver(greens=[], reds=['n'])
  74. def fn(n):
  75. while n > 0:
  76. myjitdriver.jit_merge_point(n=n)
  77. myjitdriver.can_enter_jit(n=n)
  78. n -= 1
  79. return n
  80. py.test.raises(JitHintError, fn, 100)
  81. myjitdriver = JitDriver(greens=['n'], reds=[])
  82. py.test.raises(JitHintError, fn, 100)
  83. def test_invalid_hint_combinations_error():
  84. with pytest.raises(TypeError):
  85. @unroll_safe
  86. @elidable
  87. def f():
  88. pass
  89. with pytest.raises(TypeError):
  90. @unroll_safe
  91. @elidable
  92. def f():
  93. pass
  94. with pytest.raises(TypeError):
  95. @unroll_safe
  96. @dont_look_inside
  97. def f():
  98. pass
  99. with pytest.raises(TypeError):
  100. @unroll_safe
  101. @dont_look_inside
  102. def f():
  103. pass
  104. class TestJIT(BaseRtypingTest):
  105. def test_hint(self):
  106. def f():
  107. x = hint(5, hello="world")
  108. return x
  109. res = self.interpret(f, [])
  110. assert res == 5
  111. def test_we_are_jitted(self):
  112. def f(x):
  113. try:
  114. if we_are_jitted():
  115. return x
  116. return x + 1
  117. except Exception:
  118. return 5
  119. res = self.interpret(f, [4])
  120. assert res == 5
  121. def test_elidable_promote(self):
  122. @elidable_promote()
  123. def g(func):
  124. return func + 1
  125. def f(x):
  126. return g(x * 2)
  127. res = self.interpret(f, [2])
  128. assert res == 5
  129. def test_elidable_promote_args(self):
  130. @elidable_promote(promote_args='0')
  131. def g(func, x):
  132. return func + 1
  133. def f(x):
  134. return g(x * 2, x)
  135. import dis
  136. from StringIO import StringIO
  137. import sys
  138. s = StringIO()
  139. prev = sys.stdout
  140. sys.stdout = s
  141. try:
  142. dis.dis(g)
  143. finally:
  144. sys.stdout = prev
  145. x = s.getvalue().find('CALL_FUNCTION')
  146. assert x != -1
  147. x = s.getvalue().find('CALL_FUNCTION', x)
  148. assert x != -1
  149. x = s.getvalue().find('CALL_FUNCTION', x)
  150. assert x != -1
  151. res = self.interpret(f, [2])
  152. assert res == 5
  153. def test_annotate_hooks(self):
  154. def get_printable_location(m): pass
  155. myjitdriver = JitDriver(greens=['m'], reds=['n'],
  156. get_printable_location=get_printable_location)
  157. def fn(n):
  158. m = 42.5
  159. while n > 0:
  160. myjitdriver.can_enter_jit(m=m, n=n)
  161. myjitdriver.jit_merge_point(m=m, n=n)
  162. n -= 1
  163. return n
  164. t, rtyper, fngraph = self.gengraph(fn, [int])
  165. # added by compute_result_annotation()
  166. assert fn._dont_reach_me_in_del_ == True
  167. def getargs(func):
  168. for graph in t.graphs:
  169. if getattr(graph, 'func', None) is func:
  170. return [v.concretetype for v in graph.getargs()]
  171. raise Exception('function %r has not been annotated' % func)
  172. get_printable_location_args = getargs(get_printable_location)
  173. assert get_printable_location_args == [lltype.Float]
  174. def test_annotate_argumenterror(self):
  175. myjitdriver = JitDriver(greens=['m'], reds=['n'])
  176. def fn(n):
  177. while n > 0:
  178. myjitdriver.can_enter_jit(m=42.5, n=n)
  179. myjitdriver.jit_merge_point(n=n)
  180. n -= 1
  181. return n
  182. py.test.raises(JitHintError, self.gengraph, fn, [int])
  183. def test_annotate_typeerror(self):
  184. myjitdriver = JitDriver(greens=['m'], reds=['n'])
  185. class A(object):
  186. pass
  187. class B(object):
  188. pass
  189. def fn(n):
  190. while n > 0:
  191. myjitdriver.can_enter_jit(m=A(), n=n)
  192. myjitdriver.jit_merge_point(m=B(), n=n)
  193. n -= 1
  194. return n
  195. py.test.raises(UnionError, self.gengraph, fn, [int])
  196. def test_green_field(self):
  197. def get_printable_location(xfoo):
  198. return str(ord(xfoo)) # xfoo must be annotated as a character
  199. myjitdriver = JitDriver(greens=['x.foo'], reds=['n', 'x'],
  200. get_printable_location=get_printable_location)
  201. class A(object):
  202. _immutable_fields_ = ['foo']
  203. def fn(n):
  204. x = A()
  205. x.foo = chr(n)
  206. while n > 0:
  207. myjitdriver.can_enter_jit(x=x, n=n)
  208. myjitdriver.jit_merge_point(x=x, n=n)
  209. n -= 1
  210. return n
  211. t = self.gengraph(fn, [int])[0]
  212. if option.view:
  213. t.view()
  214. # assert did not raise
  215. def test_isconstant(self):
  216. def f(n):
  217. assert isconstant(n) is False
  218. l = []
  219. l.append(n)
  220. return len(l)
  221. res = self.interpret(f, [-234])
  222. assert res == 1
  223. def test_argument_order_ok(self):
  224. myjitdriver = JitDriver(greens=['i1', 'r1', 'f1'], reds=[])
  225. class A(object):
  226. pass
  227. myjitdriver.jit_merge_point(i1=42, r1=A(), f1=3.5)
  228. # assert did not raise
  229. def test_argument_order_wrong(self):
  230. myjitdriver = JitDriver(greens=['r1', 'i1', 'f1'], reds=[])
  231. class A(object):
  232. pass
  233. e = py.test.raises(AssertionError,
  234. myjitdriver.jit_merge_point, i1=42, r1=A(), f1=3.5)
  235. def test_argument_order_more_precision_later(self):
  236. myjitdriver = JitDriver(greens=['r1', 'i1', 'r2', 'f1'], reds=[])
  237. class A(object):
  238. pass
  239. myjitdriver.jit_merge_point(i1=42, r1=None, r2=None, f1=3.5)
  240. e = py.test.raises(AssertionError,
  241. myjitdriver.jit_merge_point, i1=42, r1=A(), r2=None, f1=3.5)
  242. assert "got ['2:REF', '1:INT', '?', '3:FLOAT']" in repr(e.value)
  243. def test_argument_order_more_precision_later_2(self):
  244. myjitdriver = JitDriver(greens=['r1', 'i1', 'r2', 'f1'], reds=[])
  245. class A(object):
  246. pass
  247. myjitdriver.jit_merge_point(i1=42, r1=None, r2=A(), f1=3.5)
  248. e = py.test.raises(AssertionError,
  249. myjitdriver.jit_merge_point, i1=42, r1=A(), r2=None, f1=3.5)
  250. assert "got ['2:REF', '1:INT', '2:REF', '3:FLOAT']" in repr(e.value)
  251. def test_argument_order_accept_r_uint(self):
  252. # this used to fail on 64-bit, because r_uint == r_ulonglong
  253. myjitdriver = JitDriver(greens=['i1'], reds=[])
  254. myjitdriver.jit_merge_point(i1=r_uint(42))
  255. def test_conditional_call(self):
  256. def g():
  257. pass
  258. def f(n):
  259. conditional_call(n >= 0, g)
  260. def later(m):
  261. conditional_call(m, g)
  262. t = TranslationContext()
  263. t.buildannotator().build_types(f, [int])
  264. t.buildrtyper().specialize()
  265. mix = MixLevelHelperAnnotator(t.rtyper)
  266. mix.getgraph(later, [annmodel.s_Bool], annmodel.s_None)
  267. mix.finish()
  268. def test_enter_leave_portal_frame(self):
  269. from rpython.translator.interactive import Translation
  270. def g():
  271. enter_portal_frame(1)
  272. leave_portal_frame()
  273. t = Translation(g, [])
  274. t.compile_c() # does not crash