PageRenderTime 58ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/rpython/jit/codewriter/test/test_flatten.py

https://bitbucket.org/pypy/pypy/
Python | 1168 lines | 1142 code | 20 blank | 6 comment | 15 complexity | e4645ce556668e7e53a7e5a8cd1d4b60 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py, sys
  2. from rpython.jit.codewriter import support
  3. from rpython.jit.codewriter.heaptracker import int_signext
  4. from rpython.jit.codewriter.flatten import flatten_graph, reorder_renaming_list
  5. from rpython.jit.codewriter.flatten import GraphFlattener, ListOfKind, Register
  6. from rpython.jit.codewriter.format import assert_format
  7. from rpython.jit.codewriter import longlong
  8. from rpython.jit.codewriter.effectinfo import EffectInfo
  9. from rpython.jit.metainterp.history import AbstractDescr
  10. from rpython.rtyper.lltypesystem import lltype, rstr, rffi
  11. from rpython.rtyper import rclass
  12. from rpython.flowspace.model import SpaceOperation, Variable, Constant
  13. from rpython.translator.unsimplify import varoftype
  14. from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
  15. from rpython.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver
  16. from rpython.rlib.objectmodel import keepalive_until_here
  17. from rpython.rlib import jit, debug
  18. class FakeRegAlloc:
  19. # a RegAllocator that answers "0, 1, 2, 3, 4..." for the colors
  20. def __init__(self):
  21. self.seen = {}
  22. self.num_colors = 0
  23. def getcolor(self, v):
  24. if v not in self.seen:
  25. self.seen[v] = self.num_colors
  26. self.num_colors += 1
  27. return self.seen[v]
  28. def fake_regallocs():
  29. return {'int': FakeRegAlloc(),
  30. 'ref': FakeRegAlloc(),
  31. 'float': FakeRegAlloc()}
  32. class FakeDescr(AbstractDescr):
  33. _for_tests_only = True
  34. def __init__(self, oopspecindex=None):
  35. self.oopspecindex = oopspecindex
  36. def __repr__(self):
  37. return '<Descr>'
  38. class FakeDict(object):
  39. def __getitem__(self, key):
  40. F = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
  41. f = lltype.functionptr(F, key[0])
  42. c_func = Constant(f, lltype.typeOf(f))
  43. return c_func, lltype.Signed
  44. class FakeCPU:
  45. class tracker:
  46. pass
  47. def __init__(self, rtyper):
  48. rtyper._builtin_func_for_spec_cache = FakeDict()
  49. self.rtyper = rtyper
  50. def calldescrof(self, FUNC, ARGS, RESULT, effectinfo):
  51. return FakeDescr()
  52. def fielddescrof(self, STRUCT, name):
  53. return FakeDescr()
  54. def sizeof(self, STRUCT, vtable=None):
  55. return FakeDescr()
  56. def arraydescrof(self, ARRAY):
  57. return FakeDescr()
  58. class FakeCallInfoCollection:
  59. def add(self, *args):
  60. pass
  61. class FakeCallControl:
  62. _descr_cannot_raise = FakeDescr()
  63. callinfocollection = FakeCallInfoCollection()
  64. def guess_call_kind(self, op):
  65. return 'residual'
  66. def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
  67. extraeffect=None, extradescr=None):
  68. try:
  69. name = op.args[0].value._obj._name
  70. if 'cannot_raise' in name or name.startswith('cast_'):
  71. return self._descr_cannot_raise
  72. except AttributeError:
  73. pass
  74. return FakeDescr(oopspecindex)
  75. def calldescr_canraise(self, calldescr):
  76. return calldescr is not self._descr_cannot_raise and calldescr.oopspecindex == EffectInfo.OS_NONE
  77. def get_vinfo(self, VTYPEPTR):
  78. if hasattr(VTYPEPTR.TO, 'inst_vlist'):
  79. return FakeVInfo()
  80. return None
  81. class FakeCallControlWithVRefInfo:
  82. class virtualref_info:
  83. JIT_VIRTUAL_REF = lltype.GcStruct('VREF', ('parent', rclass.OBJECT))
  84. jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE,
  85. immortal=True)
  86. def guess_call_kind(self, op):
  87. if op.args[0].value._obj._name == 'jit_force_virtual':
  88. return 'residual'
  89. return 'builtin'
  90. def getcalldescr(self, op, **kwds):
  91. return FakeDescr()
  92. def calldescr_canraise(self, calldescr):
  93. return False
  94. class FakeVInfo:
  95. static_field_to_extra_box = {}
  96. array_fields = {'inst_vlist': '?'}
  97. array_field_counter = {'inst_vlist': 0}
  98. array_field_descrs = [FakeDescr()]
  99. array_descrs = [FakeDescr()]
  100. # ____________________________________________________________
  101. def test_reorder_renaming_list():
  102. result = reorder_renaming_list([], [])
  103. assert result == []
  104. result = reorder_renaming_list([1, 2, 3], [4, 5, 6])
  105. assert result == [(1, 4), (2, 5), (3, 6)]
  106. result = reorder_renaming_list([4, 5, 1, 2], [1, 2, 3, 4])
  107. assert result == [(1, 3), (4, 1), (2, 4), (5, 2)]
  108. result = reorder_renaming_list([1, 2], [2, 1])
  109. assert result == [(1, None), (2, 1), (None, 2)]
  110. result = reorder_renaming_list([4, 3, 6, 1, 2, 5, 7],
  111. [1, 2, 5, 3, 4, 6, 8])
  112. assert result == [(7, 8),
  113. (4, None), (2, 4), (3, 2), (1, 3), (None, 1),
  114. (6, None), (5, 6), (None, 5)]
  115. def test_repr():
  116. assert repr(Register('int', 13)) == '%i13'
  117. # ____________________________________________________________
  118. class TestFlatten:
  119. def make_graphs(self, func, values):
  120. self.rtyper = support.annotate(func, values)
  121. return self.rtyper.annotator.translator.graphs
  122. def encoding_test(self, func, args, expected,
  123. transform=False, liveness=False, cc=None, jd=None):
  124. graphs = self.make_graphs(func, args)
  125. #graphs[0].show()
  126. if transform:
  127. from rpython.jit.codewriter.jtransform import transform_graph
  128. cc = cc or FakeCallControl()
  129. transform_graph(graphs[0], FakeCPU(self.rtyper), cc, jd)
  130. ssarepr = flatten_graph(graphs[0], fake_regallocs(),
  131. _include_all_exc_links=not transform,
  132. cpu=FakeCPU(self.rtyper))
  133. if liveness:
  134. from rpython.jit.codewriter.liveness import compute_liveness
  135. compute_liveness(ssarepr)
  136. if expected is not None:
  137. assert_format(ssarepr, expected)
  138. def test_simple(self):
  139. def f(n):
  140. return n + 10
  141. self.encoding_test(f, [5], """
  142. int_add %i0, $10 -> %i1
  143. int_return %i1
  144. """)
  145. def test_if(self):
  146. def f(n):
  147. if n > 0:
  148. n -= 3
  149. return n + 1
  150. self.encoding_test(f, [10], """
  151. int_gt %i0, $0 -> %i1
  152. -live-
  153. goto_if_not %i1, L1
  154. int_copy %i0 -> %i2
  155. int_sub %i2, $3 -> %i3
  156. int_copy %i3 -> %i4
  157. L2:
  158. int_add %i4, $1 -> %i5
  159. int_return %i5
  160. ---
  161. L1:
  162. int_copy %i0 -> %i4
  163. goto L2
  164. """)
  165. def test_loop(self):
  166. def f(a, b):
  167. while a > 0:
  168. b += a
  169. a -= 1
  170. return b
  171. self.encoding_test(f, [5, 6], """
  172. int_copy %i0 -> %i2
  173. int_copy %i1 -> %i3
  174. L1:
  175. int_gt %i2, $0 -> %i4
  176. -live-
  177. goto_if_not %i4, L2
  178. int_copy %i2 -> %i5
  179. int_copy %i3 -> %i6
  180. int_add %i6, %i5 -> %i7
  181. int_sub %i5, $1 -> %i8
  182. int_copy %i8 -> %i2
  183. int_copy %i7 -> %i3
  184. goto L1
  185. ---
  186. L2:
  187. int_return %i3
  188. """)
  189. def test_loop_opt(self):
  190. def f(a, b):
  191. while a > 0:
  192. b += a
  193. a -= 1
  194. return b
  195. self.encoding_test(f, [5, 6], """
  196. int_copy %i0 -> %i2
  197. int_copy %i1 -> %i3
  198. L1:
  199. -live-
  200. goto_if_not_int_gt %i2, $0, L2
  201. int_copy %i2 -> %i4
  202. int_copy %i3 -> %i5
  203. int_add %i5, %i4 -> %i6
  204. int_sub %i4, $1 -> %i7
  205. int_copy %i7 -> %i2
  206. int_copy %i6 -> %i3
  207. goto L1
  208. ---
  209. L2:
  210. int_return %i3
  211. """, transform=True)
  212. def test_float(self):
  213. def f(i, f):
  214. return (i*5) + (f*0.25)
  215. self.encoding_test(f, [4, 7.5], """
  216. int_mul %i0, $5 -> %i1
  217. float_mul %f0, $0.25 -> %f1
  218. cast_int_to_float %i1 -> %f2
  219. float_add %f2, %f1 -> %f3
  220. float_return %f3
  221. """)
  222. def test_arg_sublist_1(self):
  223. v1 = varoftype(lltype.Signed)
  224. v2 = varoftype(lltype.Char)
  225. v3 = varoftype(rclass.OBJECTPTR)
  226. v4 = varoftype(lltype.Ptr(rstr.STR))
  227. v5 = varoftype(lltype.Float)
  228. op = SpaceOperation('residual_call_ir_f',
  229. [Constant(12345, lltype.Signed), # function ptr
  230. ListOfKind('int', [v1, v2]), # int args
  231. ListOfKind('ref', [v3, v4])], # ref args
  232. v5) # result
  233. flattener = GraphFlattener(None, fake_regallocs())
  234. flattener.serialize_op(op)
  235. assert_format(flattener.ssarepr, """
  236. residual_call_ir_f $12345, I[%i0, %i1], R[%r0, %r1] -> %f0
  237. """)
  238. def test_same_as_removal(self):
  239. def f(a):
  240. b = chr(a)
  241. return ord(b) + a
  242. self.encoding_test(f, [65], """
  243. int_add %i0, %i0 -> %i1
  244. int_return %i1
  245. """, transform=True)
  246. def test_descr(self):
  247. class FooDescr(AbstractDescr):
  248. def __repr__(self):
  249. return 'hi_there!'
  250. op = SpaceOperation('foobar', [FooDescr()], None)
  251. flattener = GraphFlattener(None, fake_regallocs())
  252. flattener.serialize_op(op)
  253. assert_format(flattener.ssarepr, """
  254. foobar hi_there!
  255. """)
  256. def test_switch_dict(self):
  257. def f(x):
  258. if x == 1: return 61
  259. elif x == 2: return 511
  260. elif x == 3: return -22
  261. elif x == 4: return 81
  262. elif x == 5: return 17
  263. elif x == 6: return 54
  264. return -1
  265. self.encoding_test(f, [65], """
  266. -live-
  267. switch %i0, <SwitchDictDescr 1:L1, 2:L2, 3:L3, 4:L4, 5:L5, 6:L6>
  268. int_return $-1
  269. ---
  270. L1:
  271. -live-
  272. int_return $61
  273. ---
  274. L2:
  275. -live-
  276. int_return $511
  277. ---
  278. L3:
  279. -live-
  280. int_return $-22
  281. ---
  282. L4:
  283. -live-
  284. int_return $81
  285. ---
  286. L5:
  287. -live-
  288. int_return $17
  289. ---
  290. L6:
  291. -live-
  292. int_return $54
  293. """)
  294. def test_switch_longlong(self):
  295. def f(n):
  296. n = r_longlong(n)
  297. if n == r_longlong(-5): return 12
  298. elif n == r_longlong(2): return 51
  299. elif n == r_longlong(7): return 1212
  300. else: return 42
  301. self.encoding_test(f, [65], None)
  302. def test_exc_exitswitch(self):
  303. def g(i):
  304. pass
  305. def f(i):
  306. try:
  307. g(i)
  308. except ValueError:
  309. return 1
  310. except KeyError:
  311. return 2
  312. else:
  313. return 3
  314. self.encoding_test(f, [65], """
  315. direct_call $<* fn g>, %i0
  316. catch_exception L1
  317. int_return $3
  318. ---
  319. L1:
  320. goto_if_exception_mismatch $<* struct object_vtable>, L2
  321. int_return $1
  322. ---
  323. L2:
  324. goto_if_exception_mismatch $<* struct object_vtable>, L3
  325. int_return $2
  326. ---
  327. L3:
  328. reraise
  329. """)
  330. def test_exc_exitswitch_2(self):
  331. class FooError(Exception):
  332. pass
  333. @dont_look_inside
  334. def g(i):
  335. FooError().num = 1
  336. FooError().num = 2
  337. def f(i):
  338. try:
  339. g(i)
  340. except FooError as e:
  341. return e.num
  342. except Exception:
  343. return 3
  344. else:
  345. return 4
  346. self.encoding_test(f, [65], """
  347. residual_call_ir_v $<* fn g>, I[%i0], R[], <Descr>
  348. -live-
  349. catch_exception L1
  350. int_return $4
  351. ---
  352. L1:
  353. goto_if_exception_mismatch $<* struct object_vtable>, L2
  354. last_exc_value -> %r0
  355. getfield_gc_i %r0, <Descr> -> %i1
  356. int_return %i1
  357. ---
  358. L2:
  359. int_return $3
  360. """, transform=True)
  361. def test_exc_raise_1(self):
  362. class FooError(Exception):
  363. pass
  364. fooerror = FooError()
  365. def f(i):
  366. raise fooerror
  367. self.encoding_test(f, [65], """
  368. raise $<* struct object>
  369. """)
  370. def test_exc_raise_2(self):
  371. def g(i):
  372. pass
  373. def f(i):
  374. try:
  375. g(i)
  376. except Exception:
  377. raise KeyError
  378. self.encoding_test(f, [65], """
  379. direct_call $<* fn g>, %i0
  380. catch_exception L1
  381. void_return
  382. ---
  383. L1:
  384. raise $<* struct object>
  385. """)
  386. def test_exc_finally(self):
  387. def get_exception(n):
  388. if n > 5:
  389. raise ValueError
  390. class Foo:
  391. pass
  392. Foo.__module__ = "test"
  393. foo = Foo()
  394. def f(i):
  395. try:
  396. get_exception(i)
  397. finally:
  398. foo.sideeffect = 5
  399. self.encoding_test(f, [65], """
  400. residual_call_ir_v $<* fn get_exception>, I[%i0], R[], <Descr>
  401. -live-
  402. catch_exception L1
  403. setfield_gc_i $<* struct test.Foo>, $5, <Descr>
  404. void_return
  405. ---
  406. L1:
  407. last_exception -> %i1
  408. last_exc_value -> %r0
  409. setfield_gc_i $<* struct test.Foo>, $5, <Descr>
  410. -live-
  411. raise %r0
  412. """, transform=True)
  413. def test_goto_if_not_int_is_true(self):
  414. def f(i):
  415. return not i
  416. # note that 'goto_if_not_int_is_true' is not the same thing
  417. # as just 'goto_if_not', because the last one expects a boolean
  418. self.encoding_test(f, [7], """
  419. -live-
  420. goto_if_not_int_is_true %i0, L1
  421. int_return $False
  422. ---
  423. L1:
  424. int_return $True
  425. """, transform=True)
  426. def test_int_floordiv_ovf_zer(self):
  427. def f(i, j):
  428. assert i >= 0
  429. assert j >= 0
  430. try:
  431. return ovfcheck(i // j)
  432. except OverflowError:
  433. return 42
  434. except ZeroDivisionError:
  435. return -42
  436. self.encoding_test(f, [7, 2], """
  437. residual_call_ir_i $<* fn ll_int_py_div_ovf_zer__Signed_Signed>, I[%i0, %i1], R[], <Descr> -> %i2
  438. -live-
  439. catch_exception L1
  440. int_return %i2
  441. ---
  442. L1:
  443. goto_if_exception_mismatch $<* struct object_vtable>, L2
  444. int_return $42
  445. ---
  446. L2:
  447. goto_if_exception_mismatch $<* struct object_vtable>, L3
  448. int_return $-42
  449. ---
  450. L3:
  451. reraise
  452. """, transform=True)
  453. def test_int_mod_ovf(self):
  454. def f(i, j):
  455. assert i >= 0
  456. assert j >= 0
  457. try:
  458. return ovfcheck(i % j)
  459. except OverflowError:
  460. return 42
  461. # XXX so far, this really produces a int_mod_ovf_zer...
  462. self.encoding_test(f, [7, 2], """
  463. residual_call_ir_i $<* fn ll_int_py_mod_ovf_zer__Signed_Signed>, I[%i0, %i1], R[], <Descr> -> %i2
  464. -live-
  465. catch_exception L1
  466. int_return %i2
  467. ---
  468. L1:
  469. goto_if_exception_mismatch $<* struct object_vtable>, L2
  470. int_return $42
  471. ---
  472. L2:
  473. reraise
  474. """, transform=True)
  475. def test_simple_branch(self):
  476. def f(n, m1, m2):
  477. if n:
  478. return m1
  479. else:
  480. return m2
  481. self.encoding_test(f, [4, 5, 6], """
  482. -live- %i0, %i1, %i2
  483. goto_if_not_int_is_true %i0, L1
  484. int_return %i1
  485. ---
  486. L1:
  487. int_return %i2
  488. """, transform=True, liveness=True)
  489. def test_int_add_ovf(self):
  490. def f(i, j):
  491. try:
  492. return ovfcheck(i + j)
  493. except OverflowError:
  494. return 42
  495. self.encoding_test(f, [7, 2], """
  496. -live- %i0, %i1
  497. int_add_jump_if_ovf L1, %i0, %i1 -> %i2
  498. int_return %i2
  499. ---
  500. L1:
  501. int_return $42
  502. """, transform=True, liveness=True)
  503. def test_int_sub_ovf(self):
  504. def f(i, j):
  505. try:
  506. return ovfcheck(i - j)
  507. except OverflowError:
  508. return 42
  509. self.encoding_test(f, [7, 2], """
  510. -live- %i0, %i1
  511. int_sub_jump_if_ovf L1, %i0, %i1 -> %i2
  512. int_return %i2
  513. ---
  514. L1:
  515. int_return $42
  516. """, transform=True, liveness=True)
  517. def test_int_mul_ovf(self):
  518. def f(i, j):
  519. try:
  520. return ovfcheck(i * j)
  521. except OverflowError:
  522. return 42
  523. self.encoding_test(f, [7, 2], """
  524. -live- %i0, %i1
  525. int_mul_jump_if_ovf L1, %i0, %i1 -> %i2
  526. int_return %i2
  527. ---
  528. L1:
  529. int_return $42
  530. """, transform=True, liveness=True)
  531. def test_multiple_int_add_ovf(self):
  532. def f(i, j):
  533. try:
  534. ovfcheck(j + i)
  535. return ovfcheck(i + j)
  536. except OverflowError:
  537. return 42
  538. self.encoding_test(f, [7, 2], """
  539. -live- %i0, %i1
  540. int_add_jump_if_ovf L1, %i1, %i0 -> %i2
  541. int_copy %i1 -> %i3
  542. int_copy %i0 -> %i4
  543. -live- %i3, %i4
  544. int_add_jump_if_ovf L2, %i4, %i3 -> %i5
  545. int_return %i5
  546. ---
  547. L2:
  548. int_return $42
  549. ---
  550. L1:
  551. int_return $42
  552. """, transform=True, liveness=True)
  553. def test_ovfcheck_no_catch(self):
  554. def f(i, j):
  555. return ovfcheck(i + j)
  556. err = py.test.raises(Exception, "self.encoding_test(f, [7, 2], '',"
  557. "transform=True, liveness=True)")
  558. assert "ovfcheck()" in str(err.value)
  559. def test_ovfcheck_reraise(self):
  560. def f(i, j):
  561. try:
  562. ovfcheck(j + i)
  563. except OverflowError:
  564. raise
  565. self.encoding_test(f, [7, 2], """
  566. -live- %i0, %i1
  567. int_add_jump_if_ovf L1, %i1, %i0 -> %i2
  568. void_return
  569. ---
  570. L1:
  571. raise $<* struct object>
  572. """, transform=True, liveness=True)
  573. def test_residual_call_raising(self):
  574. @dont_look_inside
  575. def g(i, j):
  576. return ovfcheck(i + j)
  577. def f(i, j):
  578. try:
  579. return g(i, j)
  580. except Exception:
  581. return 42 + j
  582. self.encoding_test(f, [7, 2], """
  583. residual_call_ir_i $<* fn g>, I[%i0, %i1], R[], <Descr> -> %i2
  584. -live- %i1, %i2
  585. catch_exception L1
  586. int_return %i2
  587. ---
  588. L1:
  589. int_copy %i1 -> %i3
  590. int_add %i3, $42 -> %i4
  591. int_return %i4
  592. """, transform=True, liveness=True)
  593. def test_residual_call_nonraising(self):
  594. @dont_look_inside
  595. def cannot_raise(i, j):
  596. return i + j
  597. def f(i, j):
  598. try:
  599. return cannot_raise(i, j)
  600. except Exception:
  601. return 42 + j
  602. self.encoding_test(f, [7, 2], """
  603. residual_call_ir_i $<* fn cannot_raise>, I[%i0, %i1], R[], <Descr> -> %i2
  604. int_return %i2
  605. """, transform=True, liveness=True)
  606. def test_we_are_jitted(self):
  607. def f(x):
  608. if _we_are_jitted:
  609. return 2
  610. else:
  611. return 3 + x
  612. self.encoding_test(f, [5], """
  613. int_return $2
  614. """, transform=True)
  615. def test_jitdriver(self):
  616. myjitdriver = JitDriver(greens = ['x'], reds = ['y'])
  617. def f(x, y):
  618. myjitdriver.jit_merge_point(x=x, y=y)
  619. myjitdriver.can_enter_jit(x=y, y=x)
  620. class FakeJitDriverSD:
  621. jitdriver = myjitdriver
  622. index = 27
  623. jd = FakeJitDriverSD()
  624. class MyFakeCallControl(FakeCallControl):
  625. def jitdriver_sd_from_jitdriver(self, jitdriver):
  626. assert jitdriver == myjitdriver
  627. return jd
  628. self.encoding_test(f, [4, 5], """
  629. -live- %i0, %i1
  630. int_guard_value %i0
  631. -live- %i0, %i1
  632. jit_merge_point $27, I[%i0], R[], F[], I[%i1], R[], F[]
  633. -live-
  634. loop_header $27
  635. void_return
  636. """, transform=True, liveness=True, cc=MyFakeCallControl(), jd=jd)
  637. def test_keepalive(self):
  638. S = lltype.GcStruct('S')
  639. def g():
  640. return lltype.malloc(S)
  641. def f(x):
  642. p = g()
  643. q = g()
  644. keepalive_until_here(p)
  645. keepalive_until_here(q)
  646. return x
  647. self.encoding_test(f, [5], """
  648. residual_call_r_r $<* fn g>, R[], <Descr> -> %r0
  649. -live-
  650. residual_call_r_r $<* fn g>, R[], <Descr> -> %r1
  651. -live-
  652. -live- %r0
  653. -live- %r1
  654. int_return %i0
  655. """, transform=True)
  656. self.encoding_test(f, [5], """
  657. residual_call_r_r $<* fn g>, R[], <Descr> -> %r0
  658. -live- %i0, %r0
  659. residual_call_r_r $<* fn g>, R[], <Descr> -> %r1
  660. -live- %i0, %r0, %r1
  661. -live- %i0, %r0, %r1
  662. -live- %i0, %r1
  663. int_return %i0
  664. """, transform=True, liveness=True)
  665. def test_ptr_nonzero(self):
  666. def f(p):
  667. if p:
  668. return 12
  669. return 34
  670. S = lltype.GcStruct('S')
  671. self.encoding_test(f, [lltype.malloc(S)], """
  672. -live- %r0
  673. goto_if_not_ptr_nonzero %r0, L1
  674. int_return $12
  675. ---
  676. L1:
  677. int_return $34
  678. """, transform=True, liveness=True)
  679. def test_vref_simple(self):
  680. class X:
  681. pass
  682. def f():
  683. return jit.virtual_ref(X())
  684. self.encoding_test(f, [], """
  685. new_with_vtable <Descr> -> %r0
  686. virtual_ref %r0 -> %r1
  687. ref_return %r1
  688. """, transform=True, cc=FakeCallControlWithVRefInfo())
  689. def test_vref_forced(self):
  690. class X:
  691. pass
  692. def f():
  693. vref = jit.virtual_ref(X())
  694. return vref()
  695. # The call vref() is a jit_force_virtual operation in the original
  696. # graph. It becomes in the JitCode a residual call to a helper that
  697. # contains itself a jit_force_virtual.
  698. self.encoding_test(f, [], """
  699. new_with_vtable <Descr> -> %r0
  700. virtual_ref %r0 -> %r1
  701. -live-
  702. residual_call_r_r $<* fn jit_force_virtual>, R[%r1], <Descr> -> %r2
  703. ref_return %r2
  704. """, transform=True, cc=FakeCallControlWithVRefInfo())
  705. def test_array_operations(self):
  706. A = lltype.GcArray(lltype.Signed)
  707. def f():
  708. array = lltype.malloc(A, 5)
  709. array[2] = 5
  710. return array[2] + len(array)
  711. self.encoding_test(f, [], """
  712. new_array $5, <Descr> -> %r0
  713. setarrayitem_gc_i %r0, $2, $5, <Descr>
  714. getarrayitem_gc_i %r0, $2, <Descr> -> %i0
  715. arraylen_gc %r0, <Descr> -> %i1
  716. int_add %i0, %i1 -> %i2
  717. int_return %i2
  718. """, transform=True)
  719. def test_void_array_operations(self):
  720. A = lltype.GcArray(lltype.Void)
  721. def f():
  722. array = lltype.malloc(A, 5)
  723. array[2] = None
  724. x = array[2]
  725. return len(array)
  726. self.encoding_test(f, [], """
  727. new_array $5, <Descr> -> %r0
  728. arraylen_gc %r0, <Descr> -> %i0
  729. int_return %i0
  730. """, transform=True)
  731. def test_string_operations(self):
  732. from rpython.rtyper.lltypesystem import rstr
  733. def f(n):
  734. s = lltype.malloc(rstr.STR, 2)
  735. s.chars[1] = chr(n)
  736. return ord(s.chars[1]) + len(s.chars)
  737. self.encoding_test(f, [512], """
  738. newstr $2 -> %r0
  739. strsetitem %r0, $1, %i0
  740. strgetitem %r0, $1 -> %i1
  741. strlen %r0 -> %i2
  742. int_add %i1, %i2 -> %i3
  743. int_return %i3
  744. """, transform=True)
  745. def test_uint_operations(self):
  746. def f(n):
  747. return ((r_uint(n) - 123) >> 1) <= r_uint(456)
  748. self.encoding_test(f, [200], """
  749. int_sub %i0, $123L -> %i1
  750. uint_rshift %i1, $1 -> %i2
  751. uint_le %i2, $456L -> %i3
  752. int_return %i3
  753. """, transform=True)
  754. def test_int_between(self):
  755. from rpython.rtyper.lltypesystem.lloperation import llop
  756. def f(n, m, p):
  757. return llop.int_between(lltype.Bool, n, m, p)
  758. self.encoding_test(f, [5, 6, 7], """
  759. int_between %i0, %i1, %i2 -> %i3
  760. int_return %i3
  761. """, transform=True)
  762. def test_force_cast(self):
  763. # NB: we don't need to test for INT here, the logic in jtransform is
  764. # general enough so that if we have the below cases it should
  765. # generalize also to INT
  766. for FROM, TO, expected in [
  767. (rffi.SIGNEDCHAR, rffi.SIGNEDCHAR, ""),
  768. (rffi.SIGNEDCHAR, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  769. (rffi.SIGNEDCHAR, rffi.SHORT, ""),
  770. (rffi.SIGNEDCHAR, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  771. (rffi.SIGNEDCHAR, rffi.LONG, ""),
  772. (rffi.SIGNEDCHAR, rffi.ULONG, ""),
  773. (rffi.UCHAR, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
  774. (rffi.UCHAR, rffi.UCHAR, ""),
  775. (rffi.UCHAR, rffi.SHORT, ""),
  776. (rffi.UCHAR, rffi.USHORT, ""),
  777. (rffi.UCHAR, rffi.LONG, ""),
  778. (rffi.UCHAR, rffi.ULONG, ""),
  779. (rffi.SHORT, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
  780. (rffi.SHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  781. (rffi.SHORT, rffi.SHORT, ""),
  782. (rffi.SHORT, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  783. (rffi.SHORT, rffi.LONG, ""),
  784. (rffi.SHORT, rffi.ULONG, ""),
  785. (rffi.USHORT, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
  786. (rffi.USHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  787. (rffi.USHORT, rffi.SHORT, "int_signext %i0, $2 -> %i1"),
  788. (rffi.USHORT, rffi.USHORT, ""),
  789. (rffi.USHORT, rffi.LONG, ""),
  790. (rffi.USHORT, rffi.ULONG, ""),
  791. (rffi.USHORT, lltype.Bool, "int_is_true %i0 -> %i1"),
  792. (rffi.LONG, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
  793. (rffi.LONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  794. (rffi.LONG, rffi.SHORT, "int_signext %i0, $2 -> %i1"),
  795. (rffi.LONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  796. (rffi.LONG, lltype.Bool, "int_is_true %i0 -> %i1"),
  797. (rffi.LONG, rffi.LONG, ""),
  798. (rffi.LONG, rffi.ULONG, ""),
  799. (rffi.ULONG, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
  800. (rffi.ULONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  801. (rffi.ULONG, rffi.SHORT, "int_signext %i0, $2 -> %i1"),
  802. (rffi.ULONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  803. (rffi.ULONG, lltype.Bool, "int_is_true %i0 -> %i1"),
  804. (rffi.ULONG, rffi.LONG, ""),
  805. (rffi.ULONG, rffi.ULONG, ""),
  806. ]:
  807. expected = [s.strip() for s in expected.splitlines()]
  808. check_force_cast(FROM, TO, expected, 42)
  809. check_force_cast(FROM, TO, expected, -42)
  810. returnvar = "%i" + str(len(expected))
  811. expected.append('int_return ' + returnvar)
  812. expectedstr = '\n'.join(expected)
  813. #
  814. def f(n):
  815. return rffi.cast(TO, n)
  816. self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
  817. transform=True)
  818. if not longlong.is_64_bit:
  819. if FROM in (rffi.LONG, rffi.ULONG):
  820. if FROM == rffi.LONG:
  821. FROM = rffi.LONGLONG
  822. else:
  823. FROM = rffi.ULONGLONG
  824. if TO == lltype.Bool:
  825. prefix = 'u' if FROM == rffi.ULONGLONG else ''
  826. expected = [
  827. "residual_call_irf_i $<* fn %sllong_ne>, I[], R[], F[%%f0, $0L], <Descr> -> %%i0" % prefix,
  828. "int_return %i0",
  829. ]
  830. else:
  831. expected.insert(0,
  832. "residual_call_irf_i $<* fn llong_to_int>, I[], R[], F[%f0], <Descr> -> %i0")
  833. expectedstr = '\n'.join(expected)
  834. self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
  835. transform=True)
  836. elif TO in (rffi.LONG, rffi.ULONG):
  837. if rffi.cast(FROM, -1) < 0:
  838. fnname = "llong_from_int"
  839. else:
  840. fnname = "llong_from_uint"
  841. if TO == rffi.LONG:
  842. TO = rffi.LONGLONG
  843. else:
  844. TO = rffi.ULONGLONG
  845. fnname = "u" + fnname
  846. expected.pop() # remove int_return
  847. expected.append(
  848. "residual_call_irf_f $<* fn %s>, I[%s], R[], F[], <Descr> -> %%f0"
  849. % (fnname, returnvar))
  850. expected.append("float_return %f0")
  851. expectedstr = '\n'.join(expected)
  852. self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
  853. transform=True)
  854. def test_force_cast_pointer(self):
  855. def h(p):
  856. return rffi.cast(rffi.VOIDP, p)
  857. self.encoding_test(h, [lltype.nullptr(rffi.CCHARP.TO)], """
  858. int_return %i0
  859. """, transform=True)
  860. def test_force_cast_floats(self):
  861. # Caststs to lltype.Float
  862. def f(n):
  863. return rffi.cast(lltype.Float, n)
  864. self.encoding_test(f, [12.456], """
  865. float_return %f0
  866. """, transform=True)
  867. self.encoding_test(f, [rffi.cast(rffi.SIGNEDCHAR, 42)], """
  868. cast_int_to_float %i0 -> %f0
  869. float_return %f0
  870. """, transform=True)
  871. def f(n):
  872. return rffi.cast(lltype.Bool, n)
  873. self.encoding_test(f, [0.1], """
  874. float_ne %f0, $0.0 -> %i0
  875. int_return %i0
  876. """, transform=True)
  877. self.encoding_test(f, [rffi.cast(lltype.SingleFloat, 0.5)], """
  878. cast_singlefloat_to_float %i0 -> %f0
  879. float_ne %f0, $0.0 -> %i1
  880. int_return %i1
  881. """, transform=True)
  882. # Casts to lltype.SingleFloat
  883. def g(n):
  884. return rffi.cast(lltype.SingleFloat, n)
  885. self.encoding_test(g, [12.456], """
  886. cast_float_to_singlefloat %f0 -> %i0
  887. int_return %i0
  888. """, transform=True)
  889. self.encoding_test(g, [rffi.cast(rffi.SIGNEDCHAR, 42)], """
  890. cast_int_to_float %i0 -> %f0
  891. cast_float_to_singlefloat %f0 -> %i1
  892. int_return %i1
  893. """, transform=True)
  894. # Casts from floats
  895. def f(n):
  896. return rffi.cast(rffi.SIGNEDCHAR, n)
  897. self.encoding_test(f, [12.456], """
  898. cast_float_to_int %f0 -> %i0
  899. int_signext %i0, $1 -> %i1
  900. int_return %i1
  901. """, transform=True)
  902. self.encoding_test(f, [rffi.cast(lltype.SingleFloat, 12.456)], """
  903. cast_singlefloat_to_float %i0 -> %f0
  904. cast_float_to_int %f0 -> %i1
  905. int_signext %i1, $1 -> %i2
  906. int_return %i2
  907. """, transform=True)
  908. def f(dbl):
  909. return rffi.cast(rffi.UCHAR, dbl)
  910. self.encoding_test(f, [12.456], """
  911. cast_float_to_int %f0 -> %i0
  912. int_and %i0, $255 -> %i1
  913. int_return %i1
  914. """, transform=True)
  915. def f(dbl):
  916. return rffi.cast(lltype.Unsigned, dbl)
  917. self.encoding_test(f, [12.456], """
  918. residual_call_irf_i $<* fn cast_float_to_uint>, I[], R[], F[%f0], <Descr> -> %i0
  919. int_return %i0
  920. """, transform=True)
  921. def f(i):
  922. return rffi.cast(lltype.Float, chr(i)) # "char -> float"
  923. self.encoding_test(f, [12], """
  924. cast_int_to_float %i0 -> %f0
  925. float_return %f0
  926. """, transform=True)
  927. def f(i):
  928. return rffi.cast(lltype.Float, r_uint(i)) # "uint -> float"
  929. self.encoding_test(f, [12], """
  930. residual_call_irf_f $<* fn cast_uint_to_float>, I[%i0], R[], F[], <Descr> -> %f0
  931. float_return %f0
  932. """, transform=True)
  933. if not longlong.is_64_bit:
  934. def f(dbl):
  935. return rffi.cast(lltype.SignedLongLong, dbl)
  936. self.encoding_test(f, [12.3], """
  937. residual_call_irf_f $<* fn llong_from_float>, I[], R[], F[%f0], <Descr> -> %f1
  938. float_return %f1
  939. """, transform=True)
  940. def f(dbl):
  941. return rffi.cast(lltype.UnsignedLongLong, dbl)
  942. self.encoding_test(f, [12.3], """
  943. residual_call_irf_f $<* fn ullong_from_float>, I[], R[], F[%f0], <Descr> -> %f1
  944. float_return %f1
  945. """, transform=True)
  946. def f(x):
  947. ll = r_longlong(x)
  948. return rffi.cast(lltype.Float, ll)
  949. self.encoding_test(f, [12], """
  950. residual_call_irf_f $<* fn llong_from_int>, I[%i0], R[], F[], <Descr> -> %f0
  951. residual_call_irf_f $<* fn llong_to_float>, I[], R[], F[%f0], <Descr> -> %f1
  952. float_return %f1
  953. """, transform=True)
  954. def f(x):
  955. ll = r_ulonglong(x)
  956. return rffi.cast(lltype.Float, ll)
  957. self.encoding_test(f, [12], """
  958. residual_call_irf_f $<* fn ullong_from_int>, I[%i0], R[], F[], <Descr> -> %f0
  959. residual_call_irf_f $<* fn ullong_u_to_float>, I[], R[], F[%f0], <Descr> -> %f1
  960. float_return %f1
  961. """, transform=True)
  962. def test_direct_ptradd(self):
  963. def f(p, n):
  964. return lltype.direct_ptradd(p, n)
  965. self.encoding_test(f, [lltype.nullptr(rffi.CCHARP.TO), 123], """
  966. int_add %i0, %i1 -> %i2
  967. int_return %i2
  968. """, transform=True)
  969. def test_direct_ptradd_2(self):
  970. def f(p, n):
  971. return lltype.direct_ptradd(p, n + 2)
  972. self.encoding_test(f, [lltype.nullptr(rffi.SHORTP.TO), 123], """
  973. int_add %i1, $2 -> %i2
  974. int_mul %i2, $<ItemOffset <SHORT> 1> -> %i3
  975. int_add %i0, %i3 -> %i4
  976. int_return %i4
  977. """, transform=True)
  978. def test_convert_float_bytes(self):
  979. from rpython.rlib.longlong2float import float2longlong, longlong2float
  980. def f(x):
  981. ll = float2longlong(x)
  982. return longlong2float(ll)
  983. if longlong.is_64_bit:
  984. tmp_var = "%i0"
  985. result_var = "%f1"
  986. else:
  987. tmp_var = "%f1"
  988. result_var = "%f2"
  989. self.encoding_test(f, [25.0], """
  990. convert_float_bytes_to_longlong %%f0 -> %(tmp_var)s
  991. convert_longlong_bytes_to_float %(tmp_var)s -> %(result_var)s
  992. float_return %(result_var)s
  993. """ % {"result_var": result_var, "tmp_var": tmp_var}, transform=True)
  994. def test_vable_attribute_list_is_not_None(self):
  995. class F:
  996. _virtualizable_ = ['vlist[*]']
  997. vlist = None
  998. def __init__(self, x):
  999. self.vlist = [x]
  1000. def g():
  1001. return F(42)
  1002. def f():
  1003. f = g()
  1004. if f.vlist is not None:
  1005. pass
  1006. e = py.test.raises(AssertionError, self.encoding_test, f, [], "!",
  1007. transform=True)
  1008. assert str(e.value).startswith("A virtualizable array is passed aroun")
  1009. assert "<Descr>" in str(e.value)
  1010. def test_vable_attribute_list_copied_around(self):
  1011. class F:
  1012. _virtualizable_ = ['vlist[*]']
  1013. vlist = None
  1014. def __init__(self, x):
  1015. self.vlist = [x]
  1016. def g():
  1017. return F(42)
  1018. def f():
  1019. f = g()
  1020. f.extrastuff = f.vlist
  1021. e = py.test.raises(AssertionError, self.encoding_test, f, [], "!",
  1022. transform=True)
  1023. assert str(e.value).startswith("A virtualizable array is passed aroun")
  1024. assert "<Descr>" in str(e.value)
  1025. def test_rvmprof_code(self):
  1026. from rpython.rlib.rvmprof import cintf
  1027. class MyFakeCallControl(FakeCallControl):
  1028. def guess_call_kind(self, op):
  1029. if 'jitted' in repr(op):
  1030. return 'builtin'
  1031. return 'residual'
  1032. class X:
  1033. pass
  1034. def g(x, y):
  1035. debug.debug_print("foo")
  1036. return X()
  1037. @jit.oopspec("rvmprof.jitted(unique_id)")
  1038. def decorated_jitted_function(unique_id, *args):
  1039. return g(*args)
  1040. def f(id, x, y):
  1041. return decorated_jitted_function(id, x, y)
  1042. self.encoding_test(f, [42, 56, 74], """
  1043. rvmprof_code $0, %i0
  1044. residual_call_ir_r $<* fn g>, I[%i1, %i2], R[], <Descr> -> %r0
  1045. -live-
  1046. rvmprof_code $1, %i0
  1047. ref_return %r0
  1048. """, transform=True, cc=MyFakeCallControl())
  1049. def check_force_cast(FROM, TO, operations, value):
  1050. """Check that the test is correctly written..."""
  1051. import re
  1052. r = re.compile('(\w+) \%i\d, \$(-?\d+)')
  1053. r2 = re.compile('(\w+) \%i\d')
  1054. #
  1055. value = rffi.cast(FROM, value)
  1056. value = rffi.cast(lltype.Signed, value)
  1057. #
  1058. expected_value = rffi.cast(TO, value)
  1059. expected_value = rffi.cast(lltype.Signed, expected_value)
  1060. #
  1061. for op in operations:
  1062. match = r.match(op)
  1063. if match is None:
  1064. match = r2.match(op)
  1065. assert match, "line %r does not match regexp" % (op,)
  1066. opname = match.group(1)
  1067. if opname == 'int_and':
  1068. value &= int(match.group(2))
  1069. elif opname == 'int_signext':
  1070. numbytes = int(match.group(2))
  1071. value = int_signext(value, numbytes)
  1072. elif opname == 'int_is_true':
  1073. value = bool(value)
  1074. else:
  1075. assert 0, opname
  1076. #
  1077. assert rffi.cast(lltype.Signed, value) == expected_value