PageRenderTime 43ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/backend/llsupport/test/test_regalloc_integration.py

https://bitbucket.org/pypy/pypy/
Python | 673 lines | 643 code | 27 blank | 3 comment | 10 complexity | dcce3b9d15d65e6b49f5e827f930d540 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """ Tests for register allocation for common constructs
  2. """
  3. import py
  4. from rpython.jit.metainterp.history import BasicFailDescr, JitCellToken,\
  5. TargetToken
  6. from rpython.jit.metainterp.resoperation import rop
  7. from rpython.jit.backend.detect_cpu import getcpuclass
  8. from rpython.jit.backend.llsupport.regalloc import is_comparison_or_ovf_op
  9. from rpython.jit.tool.oparser import parse
  10. from rpython.rtyper.lltypesystem import lltype, llmemory
  11. from rpython.rtyper.annlowlevel import llhelper
  12. from rpython.rtyper.lltypesystem import rstr
  13. from rpython.rtyper import rclass
  14. from rpython.jit.codewriter import longlong
  15. from rpython.jit.codewriter.effectinfo import EffectInfo
  16. def test_is_comparison_or_ovf_op():
  17. assert not is_comparison_or_ovf_op(rop.INT_ADD)
  18. assert is_comparison_or_ovf_op(rop.INT_ADD_OVF)
  19. assert is_comparison_or_ovf_op(rop.INT_EQ)
  20. def get_zero_division_error(self):
  21. # for tests, a random emulated ll_inst will do
  22. ll_inst = lltype.malloc(rclass.OBJECT)
  23. ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
  24. immortal=True)
  25. _zer_error_vtable = llmemory.cast_ptr_to_adr(ll_inst.typeptr)
  26. zer_vtable = self.cast_adr_to_int(_zer_error_vtable)
  27. zer_inst = lltype.cast_opaque_ptr(llmemory.GCREF, ll_inst)
  28. return zer_vtable, zer_inst
  29. CPU = getcpuclass()
  30. class BaseTestRegalloc(object):
  31. cpu = CPU(None, None)
  32. cpu.setup_once()
  33. def raising_func(i):
  34. if i:
  35. raise LLException(zero_division_error,
  36. zero_division_value)
  37. FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void))
  38. raising_fptr = llhelper(FPTR, raising_func)
  39. zero_division_tp, zero_division_value = get_zero_division_error(cpu)
  40. zd_addr = cpu.cast_int_to_adr(zero_division_tp)
  41. zero_division_error = llmemory.cast_adr_to_ptr(zd_addr,
  42. lltype.Ptr(rclass.OBJECT_VTABLE))
  43. raising_calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
  44. EffectInfo.MOST_GENERAL)
  45. targettoken = TargetToken()
  46. targettoken2 = TargetToken()
  47. fdescr1 = BasicFailDescr(1)
  48. fdescr2 = BasicFailDescr(2)
  49. fdescr3 = BasicFailDescr(3)
  50. def setup_method(self, meth):
  51. self.targettoken._ll_loop_code = 0
  52. self.targettoken2._ll_loop_code = 0
  53. def f1(x):
  54. return x+1
  55. def f2(x, y):
  56. return x*y
  57. def f10(*args):
  58. assert len(args) == 10
  59. return sum(args)
  60. F1PTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
  61. F2PTR = lltype.Ptr(lltype.FuncType([lltype.Signed]*2, lltype.Signed))
  62. F10PTR = lltype.Ptr(lltype.FuncType([lltype.Signed]*10, lltype.Signed))
  63. f1ptr = llhelper(F1PTR, f1)
  64. f2ptr = llhelper(F2PTR, f2)
  65. f10ptr = llhelper(F10PTR, f10)
  66. f1_calldescr = cpu.calldescrof(F1PTR.TO, F1PTR.TO.ARGS, F1PTR.TO.RESULT,
  67. EffectInfo.MOST_GENERAL)
  68. f2_calldescr = cpu.calldescrof(F2PTR.TO, F2PTR.TO.ARGS, F2PTR.TO.RESULT,
  69. EffectInfo.MOST_GENERAL)
  70. f10_calldescr= cpu.calldescrof(F10PTR.TO, F10PTR.TO.ARGS, F10PTR.TO.RESULT,
  71. EffectInfo.MOST_GENERAL)
  72. namespace = locals().copy()
  73. def parse(self, s, boxkinds=None, namespace=None):
  74. return parse(s, self.cpu, namespace or self.namespace,
  75. boxkinds=boxkinds)
  76. def interpret(self, ops, args, run=True, namespace=None):
  77. loop = self.parse(ops, namespace=namespace)
  78. self.loop = loop
  79. looptoken = JitCellToken()
  80. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  81. arguments = []
  82. for arg in args:
  83. if isinstance(arg, int):
  84. arguments.append(arg)
  85. elif isinstance(arg, float):
  86. arg = longlong.getfloatstorage(arg)
  87. arguments.append(arg)
  88. else:
  89. assert isinstance(lltype.typeOf(arg), lltype.Ptr)
  90. llgcref = lltype.cast_opaque_ptr(llmemory.GCREF, arg)
  91. arguments.append(llgcref)
  92. loop._jitcelltoken = looptoken
  93. if run:
  94. self.deadframe = self.cpu.execute_token(looptoken, *arguments)
  95. return loop
  96. def prepare_loop(self, ops):
  97. loop = self.parse(ops)
  98. regalloc = self.cpu.build_regalloc()
  99. regalloc.prepare_loop(loop.inputargs, loop.operations,
  100. loop.original_jitcell_token, [])
  101. return regalloc
  102. def getint(self, index):
  103. return self.cpu.get_int_value(self.deadframe, index)
  104. def getfloat(self, index):
  105. return self.cpu.get_float_value(self.deadframe, index)
  106. def getints(self, end):
  107. return [self.cpu.get_int_value(self.deadframe, index) for
  108. index in range(0, end)]
  109. def getfloats(self, end):
  110. return [longlong.getrealfloat(
  111. self.cpu.get_float_value(self.deadframe, index))
  112. for index in range(0, end)]
  113. def getptr(self, index, T):
  114. gcref = self.cpu.get_ref_value(self.deadframe, index)
  115. return lltype.cast_opaque_ptr(T, gcref)
  116. def attach_bridge(self, ops, loop, guard_op_index, **kwds):
  117. guard_op = loop.operations[guard_op_index]
  118. assert guard_op.is_guard()
  119. bridge = self.parse(ops, **kwds)
  120. assert ([box.type for box in bridge.inputargs] ==
  121. [box.type for box in guard_op.getfailargs()])
  122. faildescr = guard_op.getdescr()
  123. self.cpu.compile_bridge(faildescr, bridge.inputargs,
  124. bridge.operations,
  125. loop._jitcelltoken)
  126. return bridge
  127. def run(self, loop, *arguments):
  128. self.deadframe = self.cpu.execute_token(loop._jitcelltoken, *arguments)
  129. return self.cpu.get_latest_descr(self.deadframe)
  130. class TestRegallocSimple(BaseTestRegalloc):
  131. def test_simple_loop(self):
  132. ops = '''
  133. [i0]
  134. label(i0, descr=targettoken)
  135. i1 = int_add(i0, 1)
  136. i2 = int_lt(i1, 20)
  137. guard_true(i2) [i1]
  138. jump(i1, descr=targettoken)
  139. '''
  140. self.interpret(ops, [0])
  141. assert self.getint(0) == 20
  142. def test_two_loops_and_a_bridge(self):
  143. ops = '''
  144. [i0, i1, i2, i3]
  145. label(i0, i1, i2, i3, descr=targettoken)
  146. i4 = int_add(i0, 1)
  147. i5 = int_lt(i4, 20)
  148. guard_true(i5) [i4, i1, i2, i3]
  149. jump(i4, i1, i2, i3, descr=targettoken)
  150. '''
  151. loop = self.interpret(ops, [0, 0, 0, 0])
  152. ops2 = '''
  153. [i5, i6, i7, i8]
  154. label(i5, descr=targettoken2)
  155. i1 = int_add(i5, 1)
  156. i3 = int_add(i1, 1)
  157. i4 = int_add(i3, 1)
  158. i2 = int_lt(i4, 30)
  159. guard_true(i2) [i4]
  160. jump(i4, descr=targettoken2)
  161. '''
  162. loop2 = self.interpret(ops2, [0, 0, 0, 0])
  163. bridge_ops = '''
  164. [i4]
  165. jump(i4, i4, i4, i4, descr=targettoken)
  166. '''
  167. bridge = self.attach_bridge(bridge_ops, loop2, 5)
  168. self.run(loop2, 0, 0, 0, 0)
  169. assert self.getint(0) == 31
  170. assert self.getint(1) == 30
  171. assert self.getint(2) == 30
  172. assert self.getint(3) == 30
  173. def test_pointer_arg(self):
  174. ops = '''
  175. [i0, p0]
  176. label(i0, p0, descr=targettoken)
  177. i1 = int_add(i0, 1)
  178. i2 = int_lt(i1, 10)
  179. guard_true(i2) [p0]
  180. jump(i1, p0, descr=targettoken)
  181. '''
  182. S = lltype.GcStruct('S')
  183. ptr = lltype.malloc(S)
  184. self.interpret(ops, [0, ptr])
  185. assert self.getptr(0, lltype.Ptr(S)) == ptr
  186. def test_exception_bridge_no_exception(self):
  187. ops = '''
  188. [i0]
  189. i1 = same_as_i(1)
  190. call_n(ConstClass(raising_fptr), i0, descr=raising_calldescr)
  191. guard_exception(ConstClass(zero_division_error)) [i1]
  192. finish(0)
  193. '''
  194. bridge_ops = '''
  195. [i3]
  196. i2 = same_as_i(2)
  197. guard_no_exception() [i2]
  198. finish(1)
  199. '''
  200. loop = self.interpret(ops, [0])
  201. assert self.getint(0) == 1
  202. bridge = self.attach_bridge(bridge_ops, loop, 2)
  203. self.run(loop, 0)
  204. assert self.getint(0) == 1
  205. def test_inputarg_unused(self):
  206. ops = '''
  207. [i0]
  208. finish(1)
  209. '''
  210. self.interpret(ops, [0])
  211. # assert did not explode
  212. def test_nested_guards(self):
  213. ops = '''
  214. [i0, i1]
  215. guard_true(i0) [i0, i1]
  216. finish(4)
  217. '''
  218. bridge_ops = '''
  219. [i0, i1]
  220. guard_true(i0) [i0, i1]
  221. finish(3)
  222. '''
  223. loop = self.interpret(ops, [0, 10])
  224. assert self.getint(0) == 0
  225. assert self.getint(1) == 10
  226. bridge = self.attach_bridge(bridge_ops, loop, 0)
  227. self.run(loop, 0, 10)
  228. assert self.getint(0) == 0
  229. assert self.getint(1) == 10
  230. def test_nested_unused_arg(self):
  231. ops = '''
  232. [i0, i1]
  233. guard_true(i0) [i0, i1]
  234. finish(1)
  235. '''
  236. loop = self.interpret(ops, [0, 1])
  237. assert self.getint(0) == 0
  238. bridge_ops = '''
  239. [i0, i1]
  240. finish(2)
  241. '''
  242. self.attach_bridge(bridge_ops, loop, 0)
  243. self.run(loop, 0, 1)
  244. def test_spill_for_constant(self):
  245. ops = '''
  246. [i0, i1, i2, i3]
  247. label(i0, i1, i2, i3, descr=targettoken)
  248. i4 = int_add(3, i1)
  249. i5 = int_lt(i4, 30)
  250. guard_true(i5) [i0, i4, i2, i3]
  251. jump(1, i4, 3, 4, descr=targettoken)
  252. '''
  253. self.interpret(ops, [0, 0, 0, 0])
  254. assert self.getints(4) == [1, 30, 3, 4]
  255. def test_spill_for_constant_lshift(self):
  256. ops = '''
  257. [i0, i2, i1, i3]
  258. label(i0, i2, i1, i3, descr=targettoken)
  259. i4 = int_lshift(1, i1)
  260. i5 = int_add(1, i1)
  261. i6 = int_lt(i5, 30)
  262. guard_true(i6) [i4, i5, i2, i3]
  263. jump(i4, 3, i5, 4, descr=targettoken)
  264. '''
  265. self.interpret(ops, [0, 0, 0, 0])
  266. assert self.getints(4) == [1<<29, 30, 3, 4]
  267. ops = '''
  268. [i0, i1, i2, i3]
  269. label(i0, i1, i2, i3, descr=targettoken)
  270. i4 = int_lshift(1, i1)
  271. i5 = int_add(1, i1)
  272. i6 = int_lt(i5, 30)
  273. guard_true(i6) [i4, i5, i2, i3]
  274. jump(i4, i5, 3, 4, descr=targettoken)
  275. '''
  276. self.interpret(ops, [0, 0, 0, 0])
  277. assert self.getints(4) == [1<<29, 30, 3, 4]
  278. ops = '''
  279. [i0, i3, i1, i2]
  280. label(i0, i3, i1, i2, descr=targettoken)
  281. i4 = int_lshift(1, i1)
  282. i5 = int_add(1, i1)
  283. i6 = int_lt(i5, 30)
  284. guard_true(i6) [i4, i5, i2, i3]
  285. jump(i4, 4, i5, 3, descr=targettoken)
  286. '''
  287. self.interpret(ops, [0, 0, 0, 0])
  288. assert self.getints(4) == [1<<29, 30, 3, 4]
  289. def test_result_selected_reg_via_neg(self):
  290. ops = '''
  291. [i0, i1, i2, i3]
  292. label(i0, i1, i2, i3, descr=targettoken)
  293. i6 = int_neg(i2)
  294. i7 = int_add(1, i1)
  295. i4 = int_lt(i7, 10)
  296. guard_true(i4) [i0, i6, i7]
  297. jump(1, i7, i2, i6, descr=targettoken)
  298. '''
  299. self.interpret(ops, [0, 0, 3, 0])
  300. assert self.getints(3) == [1, -3, 10]
  301. def test_compare_memory_result_survives(self):
  302. ops = '''
  303. [i0, i1, i2, i3]
  304. label(i0, i1, i2, i3, descr=targettoken)
  305. i4 = int_lt(i0, i1)
  306. i5 = int_add(i3, 1)
  307. i6 = int_lt(i5, 30)
  308. guard_true(i6) [i4]
  309. jump(i0, i1, i4, i5, descr=targettoken)
  310. '''
  311. self.interpret(ops, [0, 10, 0, 0])
  312. assert self.getint(0) == 1
  313. def test_jump_different_args(self):
  314. ops = '''
  315. [i0, i15, i16, i18, i1, i2, i3]
  316. label(i0, i15, i16, i18, i1, i2, i3, descr=targettoken)
  317. i4 = int_add(i3, 1)
  318. i5 = int_lt(i4, 20)
  319. guard_true(i5) [i2, i1]
  320. jump(i0, i18, i15, i16, i2, i1, i4, descr=targettoken)
  321. '''
  322. self.interpret(ops, [0, 1, 2, 3, 0, 0, 0])
  323. def test_op_result_unused(self):
  324. ops = '''
  325. [i0, i1]
  326. i2 = int_add(i0, i1)
  327. finish(0)
  328. '''
  329. self.interpret(ops, [0, 0])
  330. def test_guard_value_two_boxes(self):
  331. ops = '''
  332. [i0, i1, i2, i3, i4, i5, i6, i7]
  333. guard_value(i6, i1) [i0, i2, i3, i4, i5, i6]
  334. finish(i0)
  335. '''
  336. self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0])
  337. assert self.getint(0) == 0
  338. def test_bug_wrong_stack_adj(self):
  339. ops = '''
  340. [i0, i1, i2, i3, i4, i5, i6, i7, i8]
  341. i9 = same_as_i(0)
  342. guard_true(i0) [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8]
  343. finish(1)
  344. '''
  345. loop = self.interpret(ops, [0, 1, 2, 3, 4, 5, 6, 7, 8])
  346. assert self.getint(0) == 0
  347. bridge_ops = '''
  348. [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8]
  349. call_n(ConstClass(raising_fptr), 0, descr=raising_calldescr)
  350. guard_true(i9) [i0, i1, i2, i3, i4, i5, i6, i7, i8]
  351. finish()
  352. '''
  353. self.attach_bridge(bridge_ops, loop, 1)
  354. self.run(loop, 0, 1, 2, 3, 4, 5, 6, 7, 8)
  355. assert self.getints(9) == range(9)
  356. def test_loopargs(self):
  357. ops = """
  358. [i0, i1, i2, i3]
  359. i4 = int_add(i0, i1)
  360. jump(i4, i1, i2, i3)
  361. """
  362. regalloc = self.prepare_loop(ops)
  363. # we pass stuff on the frame
  364. assert len(regalloc.rm.reg_bindings) == 0
  365. assert len(regalloc.fm.bindings) == 4
  366. class TestRegallocCompOps(BaseTestRegalloc):
  367. def test_cmp_op_0(self):
  368. ops = '''
  369. [i0, i3]
  370. i1 = same_as_i(1)
  371. i2 = int_lt(i0, 100)
  372. guard_true(i3) [i1, i2]
  373. i4 = int_neg(i2)
  374. finish(0)
  375. '''
  376. self.interpret(ops, [0, 1])
  377. assert self.getint(0) == 0
  378. class TestRegallocMoreRegisters(BaseTestRegalloc):
  379. cpu = BaseTestRegalloc.cpu
  380. targettoken = TargetToken()
  381. S = lltype.GcStruct('S', ('field', lltype.Char))
  382. fielddescr = cpu.fielddescrof(S, 'field')
  383. A = lltype.GcArray(lltype.Char)
  384. arraydescr = cpu.arraydescrof(A)
  385. namespace = locals().copy()
  386. def test_int_is_true(self):
  387. ops = '''
  388. [i0, i1, i2, i3, i4, i5, i6, i7]
  389. i10 = int_is_true(i0)
  390. i11 = int_is_true(i1)
  391. i12 = int_is_true(i2)
  392. i13 = int_is_true(i3)
  393. i14 = int_is_true(i4)
  394. i15 = int_is_true(i5)
  395. i16 = int_is_true(i6)
  396. i17 = int_is_true(i7)
  397. guard_true(i0) [i10, i11, i12, i13, i14, i15, i16, i17]
  398. finish()
  399. '''
  400. self.interpret(ops, [0, 42, 12, 0, 13, 0, 0, 3333])
  401. assert self.getints(8) == [0, 1, 1, 0, 1, 0, 0, 1]
  402. def test_comparison_ops(self):
  403. ops = '''
  404. [i0, i1, i2, i3, i4, i5, i6]
  405. i10 = int_lt(i0, i1)
  406. i11 = int_le(i2, i3)
  407. i12 = int_ge(i4, i5)
  408. i13 = int_eq(i5, i6)
  409. i14 = int_gt(i6, i2)
  410. i15 = int_ne(i2, i6)
  411. guard_true(i0) [i10, i11, i12, i13, i14, i15]
  412. finish()
  413. '''
  414. self.interpret(ops, [0, 1, 2, 3, 4, 5, 6])
  415. assert self.getints(6) == [1, 1, 0, 0, 1, 1]
  416. def test_strsetitem(self):
  417. ops = '''
  418. [p0, i]
  419. strsetitem(p0, 1, i)
  420. finish()
  421. '''
  422. llstr = rstr.mallocstr(10)
  423. self.interpret(ops, [llstr, ord('a')])
  424. assert llstr.chars[1] == 'a'
  425. def test_setfield_char(self):
  426. ops = '''
  427. [p0, i]
  428. setfield_gc(p0, i, descr=fielddescr)
  429. finish()
  430. '''
  431. s = lltype.malloc(self.S)
  432. self.interpret(ops, [s, ord('a')])
  433. assert s.field == 'a'
  434. def test_setarrayitem_gc(self):
  435. ops = '''
  436. [p0, i]
  437. setarrayitem_gc(p0, 1, i, descr=arraydescr)
  438. finish()
  439. '''
  440. s = lltype.malloc(self.A, 3)
  441. self.interpret(ops, [s, ord('a')])
  442. assert s[1] == 'a'
  443. class TestRegallocFloats(BaseTestRegalloc):
  444. def setup_class(cls):
  445. if not cls.cpu.supports_floats:
  446. py.test.skip("needs float support")
  447. def test_float_add(self):
  448. ops = '''
  449. [f0, f1]
  450. f2 = float_add(f0, f1)
  451. i0 = same_as_i(0)
  452. guard_true(i0) [f2, f0, f1]
  453. finish()
  454. '''
  455. self.interpret(ops, [3.0, 1.5])
  456. assert self.getfloats(3) == [4.5, 3.0, 1.5]
  457. def test_float_adds_stack(self):
  458. ops = '''
  459. [f0, f1, f2, f3, f4, f5, f6, f7, f8]
  460. f9 = float_add(f0, f1)
  461. f10 = float_add(f8, 3.5)
  462. i0 = same_as_i(0)
  463. guard_true(i0) [f9, f10, f2, f3, f4, f5, f6, f7, f8]
  464. finish()
  465. '''
  466. self.interpret(ops, [0.1, .2, .3, .4, .5, .6, .7, .8, .9])
  467. assert self.getfloats(9) == [.1+.2, .9+3.5, .3, .4, .5, .6, .7, .8, .9]
  468. def test_lt_const(self):
  469. ops = '''
  470. [f0]
  471. i1 = float_lt(3.5, f0)
  472. finish(i1)
  473. '''
  474. self.interpret(ops, [0.1])
  475. assert self.getint(0) == 0
  476. def test_bug_float_is_true_stack(self):
  477. # NB. float_is_true no longer exists. Unsure if keeping this test
  478. # makes sense any more.
  479. ops = '''
  480. [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]
  481. i0 = float_ne(f0, 0.0)
  482. i1 = float_ne(f1, 0.0)
  483. i2 = float_ne(f2, 0.0)
  484. i3 = float_ne(f3, 0.0)
  485. i4 = float_ne(f4, 0.0)
  486. i5 = float_ne(f5, 0.0)
  487. i6 = float_ne(f6, 0.0)
  488. i7 = float_ne(f7, 0.0)
  489. i8 = float_ne(f8, 0.0)
  490. i9 = float_ne(f9, 0.0)
  491. guard_true(i0) [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  492. finish()
  493. '''
  494. loop = self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9])
  495. assert self.getints(9) == [0, 1, 1, 1, 1, 1, 1, 1, 1]
  496. class TestRegAllocCallAndStackDepth(BaseTestRegalloc):
  497. def setup_class(cls):
  498. py.test.skip("skip for now, not sure what do we do")
  499. def expected_frame_depth(self, num_call_args, num_pushed_input_args=0):
  500. # Assumes the arguments are all non-float
  501. if not self.cpu.IS_64_BIT:
  502. extra_esp = num_call_args
  503. return extra_esp
  504. elif self.cpu.IS_64_BIT:
  505. # 'num_pushed_input_args' is for X86_64 only
  506. extra_esp = max(num_call_args - 6, 0)
  507. return num_pushed_input_args + extra_esp
  508. def test_one_call(self):
  509. ops = '''
  510. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i9b]
  511. i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  512. guard_false(i10) [i10, i1, i2, i3, i4, i5, i6, i7, i8, i9, i9b]
  513. '''
  514. loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9, 8])
  515. assert self.getints(11) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9, 8]
  516. clt = loop._jitcelltoken.compiled_loop_token
  517. assert clt.frame_depth == self.expected_frame_depth(1, 5)
  518. def test_one_call_reverse(self):
  519. ops = '''
  520. [i1, i2, i3, i4, i5, i6, i7, i8, i9, i9b, i0]
  521. i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  522. guard_false(i10) [i10, i1, i2, i3, i4, i5, i6, i7, i8, i9, i9b]
  523. '''
  524. loop = self.interpret(ops, [7, 9, 9 ,9, 9, 9, 9, 9, 9, 8, 4])
  525. assert self.getints(11) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9, 8]
  526. clt = loop._jitcelltoken.compiled_loop_token
  527. assert clt.frame_depth == self.expected_frame_depth(1, 6)
  528. def test_two_calls(self):
  529. ops = '''
  530. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  531. i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  532. i11 = call(ConstClass(f2ptr), i10, i1, descr=f2_calldescr)
  533. guard_false(i5) [i11, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  534. '''
  535. loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9])
  536. assert self.getints(10) == [5*7, 7, 9, 9, 9, 9, 9, 9, 9, 9]
  537. clt = loop._jitcelltoken.compiled_loop_token
  538. assert clt.frame_depth == self.expected_frame_depth(2, 5)
  539. def test_call_many_arguments(self):
  540. # NB: The first and last arguments in the call are constants. This
  541. # is primarily for x86-64, to ensure that loading a constant to an
  542. # argument register or to the stack works correctly
  543. ops = '''
  544. [i0, i1, i2, i3, i4, i5, i6, i7]
  545. i8 = call(ConstClass(f10ptr), 1, i0, i1, i2, i3, i4, i5, i6, i7, 10, descr=f10_calldescr)
  546. finish(i8)
  547. '''
  548. loop = self.interpret(ops, [2, 3, 4, 5, 6, 7, 8, 9])
  549. assert self.getint(0) == 55
  550. clt = loop._jitcelltoken.compiled_loop_token
  551. assert clt.frame_depth == self.expected_frame_depth(10)
  552. def test_bridge_calls_1(self):
  553. ops = '''
  554. [i0, i1]
  555. i2 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  556. guard_value(i2, 0, descr=fdescr1) [i2, i0, i1]
  557. guard_false(i1) [i1]
  558. '''
  559. loop = self.interpret(ops, [4, 7])
  560. assert self.getint(0) == 5
  561. clt = loop._jitcelltoken.compiled_loop_token
  562. orgdepth = clt.frame_depth
  563. assert orgdepth == self.expected_frame_depth(1, 2)
  564. ops = '''
  565. [i2, i0, i1]
  566. i3 = call(ConstClass(f2ptr), i2, i1, descr=f2_calldescr)
  567. guard_false(i0, descr=fdescr2) [i3, i0]
  568. '''
  569. bridge = self.attach_bridge(ops, loop, -2)
  570. assert clt.frame_depth == max(orgdepth, self.expected_frame_depth(2, 2))
  571. assert loop.operations[-2].getdescr()._x86_bridge_frame_depth == \
  572. self.expected_frame_depth(2, 2)
  573. self.run(loop, 4, 7)
  574. assert self.getint(0) == 5*7
  575. def test_bridge_calls_2(self):
  576. ops = '''
  577. [i0, i1]
  578. i2 = call(ConstClass(f2ptr), i0, i1, descr=f2_calldescr)
  579. guard_value(i2, 0, descr=fdescr1) [i2]
  580. guard_false(i2) [i2]
  581. '''
  582. loop = self.interpret(ops, [4, 7])
  583. assert self.getint(0) == 4*7
  584. clt = loop._jitcelltoken.compiled_loop_token
  585. orgdepth = clt.frame_depth
  586. assert orgdepth == self.expected_frame_depth(2)
  587. ops = '''
  588. [i2]
  589. i3 = call(ConstClass(f1ptr), i2, descr=f1_calldescr)
  590. guard_false(i3, descr=fdescr2) [i3]
  591. '''
  592. bridge = self.attach_bridge(ops, loop, -2)
  593. assert clt.frame_depth == max(orgdepth, self.expected_frame_depth(1))
  594. assert loop.operations[-2].getdescr()._x86_bridge_frame_depth == \
  595. self.expected_frame_depth(1)
  596. self.run(loop, 4, 7)
  597. assert self.getint(0) == 29