PageRenderTime 37ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/metainterp/test/test_executor.py

https://bitbucket.org/pypy/pypy/
Python | 347 lines | 293 code | 36 blank | 18 comment | 42 complexity | cf289d9325c31000fea94ab226d6e462 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. import sys, random
  3. from rpython.rlib.rarithmetic import r_uint, intmask
  4. from rpython.jit.metainterp.executor import execute, wrap_constant
  5. from rpython.jit.metainterp.executor import execute_varargs, _execute_arglist
  6. from rpython.jit.metainterp.resoperation import rop, opname, opclasses,\
  7. InputArgInt, InputArgFloat, InputArgRef
  8. from rpython.jit.metainterp.history import ConstInt, ConstPtr, ConstFloat
  9. from rpython.jit.metainterp.history import AbstractDescr
  10. from rpython.jit.metainterp import history
  11. from rpython.jit.codewriter import longlong
  12. from rpython.jit.backend.model import AbstractCPU
  13. from rpython.rtyper.lltypesystem import llmemory, rffi
  14. class FakeDescr(AbstractDescr):
  15. pass
  16. class FakeCallDescr(FakeDescr):
  17. def get_result_type(self):
  18. return history.FLOAT
  19. class FakeFieldDescr(FakeDescr):
  20. def is_pointer_field(self):
  21. return False
  22. def is_float_field(self):
  23. return True
  24. class FakeArrayDescr(FakeDescr):
  25. def is_array_of_pointers(self):
  26. return False
  27. def is_array_of_floats(self):
  28. return True
  29. class FakeResultR:
  30. _TYPE = llmemory.GCREF
  31. def __init__(self, *args):
  32. self.fakeargs = args
  33. class FakeMetaInterp:
  34. pass
  35. class FakeCPU(AbstractCPU):
  36. supports_floats = True
  37. def bh_new(self, descr):
  38. return FakeResultR('new', descr)
  39. def bh_arraylen_gc(self, array, descr):
  40. assert not array
  41. assert isinstance(descr, FakeDescr)
  42. return 55
  43. def bh_setfield_gc_f(self, struct, newvalue, fielddescr):
  44. self.fakesetfield = (struct, newvalue, fielddescr)
  45. def bh_setarrayitem_gc_f(self, array, index, newvalue, arraydescr):
  46. self.fakesetarrayitem = (array, index, newvalue, arraydescr)
  47. def bh_call_f(self, func, args_i, args_r, args_f, calldescr):
  48. self.fakecalled = (func, args_i, args_r, args_f, calldescr)
  49. return longlong.getfloatstorage(42.5)
  50. def bh_strsetitem(self, string, index, newvalue):
  51. self.fakestrsetitem = (string, index, newvalue)
  52. boxfloat = InputArgFloat.fromfloat
  53. constfloat = ConstFloat.fromfloat
  54. def test_execute():
  55. cpu = FakeCPU()
  56. descr = FakeDescr()
  57. box = execute(cpu, None, rop.INT_ADD, None, InputArgInt(40), ConstInt(2))
  58. assert box == 42
  59. box = execute(cpu, None, rop.NEW, descr)
  60. assert box.fakeargs == ('new', descr)
  61. def test_execute_varargs():
  62. cpu = FakeCPU()
  63. descr = FakeCallDescr()
  64. argboxes = [InputArgInt(99999), InputArgInt(321), constfloat(2.25), ConstInt(123),
  65. InputArgRef(), boxfloat(5.5)]
  66. box = execute_varargs(cpu, FakeMetaInterp(), rop.CALL_F, argboxes, descr)
  67. assert longlong.getrealfloat(box) == 42.5
  68. assert cpu.fakecalled == (99999, [321, 123],
  69. [ConstPtr.value],
  70. [longlong.getfloatstorage(2.25),
  71. longlong.getfloatstorage(5.5)],
  72. descr)
  73. def test_execute_nonspec():
  74. cpu = FakeCPU()
  75. descr = FakeDescr()
  76. # cases with a descr
  77. # arity == -1
  78. argboxes = [InputArgInt(321), ConstInt(123)]
  79. box = _execute_arglist(cpu, FakeMetaInterp(), rop.CALL_F,
  80. argboxes, FakeCallDescr())
  81. assert longlong.getrealfloat(box) == 42.5
  82. # arity == 0
  83. box = _execute_arglist(cpu, None, rop.NEW, [], descr)
  84. assert box.fakeargs == ('new', descr)
  85. # arity == 1
  86. box1 = InputArgRef()
  87. box = _execute_arglist(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
  88. assert box == 55
  89. # arity == 2
  90. box2 = boxfloat(222.2)
  91. fielddescr = FakeFieldDescr()
  92. _execute_arglist(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
  93. assert cpu.fakesetfield == (box1.getref_base(), box2.getfloatstorage(),
  94. fielddescr)
  95. # arity == 3
  96. box3 = InputArgInt(33)
  97. arraydescr = FakeArrayDescr()
  98. _execute_arglist(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
  99. arraydescr)
  100. assert cpu.fakesetarrayitem == (box1.getref_base(), box3.getint(),
  101. box2.getfloatstorage(), arraydescr)
  102. # cases without descr
  103. # arity == 1
  104. box = _execute_arglist(cpu, None, rop.INT_INVERT, [box3])
  105. assert box == ~33
  106. # arity == 2
  107. box = _execute_arglist(cpu, None, rop.INT_LSHIFT, [box3, InputArgInt(3)])
  108. assert box == 33 << 3
  109. # arity == 3
  110. _execute_arglist(cpu, None, rop.STRSETITEM, [box1, InputArgInt(3), box3])
  111. assert cpu.fakestrsetitem == (box1.getref_base(), 3, box3.getint())
  112. # ints
  113. def _int_binary_operations():
  114. minint = -sys.maxint-1
  115. # Test cases. Note that for each operation there should be at least
  116. # one case in which the two input arguments are equal.
  117. for opnum, testcases in [
  118. (rop.INT_ADD, [(10, -2, 8),
  119. (-60, -60, -120)]),
  120. (rop.INT_SUB, [(10, -2, 12),
  121. (133, 133, 0)]),
  122. (rop.INT_MUL, [(-6, -3, 18),
  123. (15, 15, 225)]),
  124. (rop.INT_AND, [(0xFF00, 0x0FF0, 0x0F00),
  125. (-111, -111, -111)]),
  126. (rop.INT_OR, [(0xFF00, 0x0FF0, 0xFFF0),
  127. (-111, -111, -111)]),
  128. (rop.INT_XOR, [(0xFF00, 0x0FF0, 0xF0F0),
  129. (-111, -111, 0)]),
  130. (rop.INT_LSHIFT, [(10, 4, 10<<4),
  131. (-5, 2, -20),
  132. (-5, 0, -5),
  133. (3, 3, 24)]),
  134. (rop.INT_RSHIFT, [(-17, 2, -5),
  135. (19, 1, 9),
  136. (3, 3, 0)]),
  137. (rop.UINT_RSHIFT, [(-1, 4, intmask(r_uint(-1) >> r_uint(4))),
  138. ( 1, 4, intmask(r_uint(1) >> r_uint(4))),
  139. ( 3, 3, 0)]),
  140. (rop.UINT_MUL_HIGH, [(5, 6, 0),
  141. (0xffff, 0xffff, 0),
  142. (-1, -1, -2),
  143. (-1, 123, 122)]),
  144. ]:
  145. for x, y, z in testcases:
  146. yield opnum, [x, y], z
  147. def _int_comparison_operations():
  148. cpu = FakeCPU()
  149. random_numbers = [-sys.maxint-1, -1, 0, 1, sys.maxint]
  150. def pick():
  151. r = random.randrange(-99999, 100000)
  152. if r & 1:
  153. return r
  154. else:
  155. return random_numbers[r % len(random_numbers)]
  156. minint = -sys.maxint-1
  157. for opnum, operation in [
  158. (rop.INT_LT, lambda x, y: x < y),
  159. (rop.INT_LE, lambda x, y: x <= y),
  160. (rop.INT_EQ, lambda x, y: x == y),
  161. (rop.INT_NE, lambda x, y: x != y),
  162. (rop.INT_GT, lambda x, y: x > y),
  163. (rop.INT_GE, lambda x, y: x >= y),
  164. (rop.UINT_LT, lambda x, y: r_uint(x) < r_uint(y)),
  165. (rop.UINT_LE, lambda x, y: r_uint(x) <= r_uint(y)),
  166. (rop.UINT_GT, lambda x, y: r_uint(x) > r_uint(y)),
  167. (rop.UINT_GE, lambda x, y: r_uint(x) >= r_uint(y)),
  168. ]:
  169. for i in range(20):
  170. x = pick()
  171. if i == 1: # there should be at least one case
  172. y = x # where the two arguments are equal
  173. else:
  174. y = pick()
  175. z = int(operation(x, y))
  176. yield opnum, [x, y], z
  177. def _int_unary_operations():
  178. minint = -sys.maxint-1
  179. for opnum, testcases in [
  180. (rop.INT_IS_TRUE, [(0, 0), (1, 1), (2, 1), (-1, 1), (minint, 1)]),
  181. (rop.INT_NEG, [(0, 0), (123, -123), (-23127, 23127)]),
  182. (rop.INT_INVERT, [(0, ~0), (-1, ~(-1)), (123, ~123)]),
  183. (rop.INT_IS_ZERO, [(0, 1), (1, 0), (2, 0), (-1, 0), (minint, 0)]),
  184. ]:
  185. for x, y in testcases:
  186. yield opnum, [x], y
  187. def get_int_tests():
  188. for opnum, args, retvalue in (
  189. list(_int_binary_operations()) +
  190. list(_int_comparison_operations()) +
  191. list(_int_unary_operations())):
  192. yield opnum, [InputArgInt(x) for x in args], retvalue
  193. if len(args) > 1:
  194. assert len(args) == 2
  195. yield opnum, [InputArgInt(args[0]), ConstInt(args[1])], retvalue
  196. yield opnum, [ConstInt(args[0]), InputArgInt(args[1])], retvalue
  197. if args[0] == args[1]:
  198. commonbox = InputArgInt(args[0])
  199. yield opnum, [commonbox, commonbox], retvalue
  200. def test_int_ops():
  201. cpu = FakeCPU()
  202. for opnum, boxargs, retvalue in get_int_tests():
  203. r = _execute_arglist(cpu, None, opnum, boxargs)
  204. assert r == retvalue
  205. # floats
  206. def _float_binary_operations():
  207. # Test cases. Note that for each operation there should be at least
  208. # one case in which the two input arguments are equal.
  209. for opnum, testcases in [
  210. (rop.FLOAT_ADD, [(10.5, -2.25, 8.25),
  211. (5.25, 5.25, 10.5)]),
  212. (rop.FLOAT_SUB, [(10.5, -2.25, 12.75),
  213. (5.25, 5.25, 0.0)]),
  214. (rop.FLOAT_MUL, [(-6.5, -3.5, 22.75),
  215. (1.5, 1.5, 2.25)]),
  216. (rop.FLOAT_TRUEDIV, [(118.75, 12.5, 9.5),
  217. (-6.5, -6.5, 1.0)]),
  218. ]:
  219. for x, y, z in testcases:
  220. yield (opnum, [x, y], 'float', z)
  221. def _float_comparison_operations():
  222. # Test cases. Note that for each operation there should be at least
  223. # one case in which the two input arguments are equal.
  224. for y in [-522.25, 10.125, 22.6]:
  225. yield (rop.FLOAT_LT, [10.125, y], 'int', 10.125 < y)
  226. yield (rop.FLOAT_LE, [10.125, y], 'int', 10.125 <= y)
  227. yield (rop.FLOAT_EQ, [10.125, y], 'int', 10.125 == y)
  228. yield (rop.FLOAT_NE, [10.125, y], 'int', 10.125 != y)
  229. yield (rop.FLOAT_GT, [10.125, y], 'int', 10.125 > y)
  230. yield (rop.FLOAT_GE, [10.125, y], 'int', 10.125 >= y)
  231. yield (rop.FLOAT_EQ, [0.0, -0.0], 'int', 0.0 == -0.0)
  232. def _float_unary_operations():
  233. yield (rop.FLOAT_NEG, [-5.9], 'float', 5.9)
  234. yield (rop.FLOAT_NEG, [15.9], 'float', -15.9)
  235. yield (rop.FLOAT_ABS, [-5.9], 'float', 5.9)
  236. yield (rop.FLOAT_ABS, [15.9], 'float', 15.9)
  237. yield (rop.CAST_FLOAT_TO_INT, [-5.9], 'int', -5)
  238. yield (rop.CAST_FLOAT_TO_INT, [5.9], 'int', 5)
  239. yield (rop.CAST_INT_TO_FLOAT, [123], 'float', 123.0)
  240. yield (rop.CAST_INT_TO_FLOAT, [-123], 'float', -123.0)
  241. def get_float_tests(cpu):
  242. if not cpu.supports_floats:
  243. py.test.skip("requires float support from the backend")
  244. for opnum, args, rettype, retvalue in (
  245. list(_float_binary_operations()) +
  246. list(_float_comparison_operations()) +
  247. list(_float_unary_operations())):
  248. boxargs = []
  249. for x in args:
  250. if isinstance(x, float):
  251. boxargs.append(boxfloat(x))
  252. else:
  253. boxargs.append(InputArgInt(x))
  254. yield opnum, boxargs, rettype, retvalue
  255. if len(args) > 1:
  256. assert len(args) == 2
  257. yield opnum, [boxargs[0], wrap_constant(boxargs[1].getvalue())], rettype, retvalue
  258. yield opnum, [wrap_constant(boxargs[0].getvalue()), boxargs[1]], rettype, retvalue
  259. if (isinstance(args[0], float) and
  260. isinstance(args[1], float) and
  261. args[0] == args[1]):
  262. commonbox = boxfloat(args[0])
  263. yield opnum, [commonbox, commonbox], rettype, retvalue
  264. def test_float_ops():
  265. cpu = FakeCPU()
  266. for opnum, boxargs, rettype, retvalue in get_float_tests(cpu):
  267. res = _execute_arglist(cpu, None, opnum, boxargs)
  268. if rettype == 'float':
  269. res = longlong.getrealfloat(res)
  270. assert res == retvalue
  271. def make_args_for_op(op, a, b):
  272. n=opname[op]
  273. if n[0:3] == 'INT' or n[0:4] == 'UINT':
  274. arg1 = ConstInt(a)
  275. arg2 = ConstInt(b)
  276. elif n[0:5] == 'FLOAT':
  277. arg1 = constfloat(float(a))
  278. arg2 = constfloat(float(b))
  279. elif n[0:3] == 'PTR':
  280. arg1 = ConstPtr(rffi.cast(llmemory.GCREF, a))
  281. arg2 = ConstPtr(rffi.cast(llmemory.GCREF, b))
  282. else:
  283. raise NotImplementedError(
  284. "Don't know how to make args for " + n)
  285. return arg1, arg2
  286. def test_opboolinvers():
  287. cpu = FakeCPU()
  288. for op1 in opclasses:
  289. if op1 is None or op1.boolinverse == -1:
  290. continue
  291. op2 = opclasses[op1.boolinverse].opnum
  292. op1 = op1.opnum
  293. for a in (1,2,3):
  294. for b in (1,2,3):
  295. arg1, arg2 = make_args_for_op(op1, a, b)
  296. box1 = execute(cpu, None, op1, None, arg1, arg2)
  297. box2 = execute(cpu, None, op2, None, arg1, arg2)
  298. assert box1 == (not box2)
  299. def test_opboolreflex():
  300. cpu = FakeCPU()
  301. for op1 in opclasses:
  302. if op1 is None or op1.boolreflex == -1:
  303. continue
  304. op2 = opclasses[op1.boolreflex].opnum
  305. op1 = op1.opnum
  306. for a in (1,2,3):
  307. for b in (1,2,3):
  308. arg1, arg2 = make_args_for_op(op1, a, b)
  309. box1 = execute(cpu, None, op1, None, arg1, arg2)
  310. box2 = execute(cpu, None, op2, None, arg2, arg1)
  311. assert box1 == box2