PageRenderTime 1308ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/jit/backend/arm/test/test_regalloc.py

https://bitbucket.org/pypy/pypy/
Python | 796 lines | 758 code | 35 blank | 3 comment | 3 complexity | c231b510288da04915d264d262005050 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,
  5. BasicFinalDescr,
  6. JitCellToken,
  7. TargetToken)
  8. from rpython.jit.metainterp.resoperation import rop
  9. from rpython.jit.backend.llsupport.descr import GcCache
  10. from rpython.jit.backend.detect_cpu import getcpuclass
  11. from rpython.jit.backend.arm.regalloc import Regalloc, ARMFrameManager
  12. from rpython.jit.backend.llsupport.regalloc import is_comparison_or_ovf_op
  13. from rpython.jit.tool.oparser import parse
  14. from rpython.rtyper.lltypesystem import lltype, llmemory
  15. from rpython.rtyper.annlowlevel import llhelper
  16. from rpython.rtyper.lltypesystem import rstr
  17. from rpython.rtyper import rclass
  18. from rpython.jit.codewriter.effectinfo import EffectInfo
  19. from rpython.jit.codewriter import longlong
  20. from rpython.jit.backend.llsupport.test.test_regalloc_integration import BaseTestRegalloc
  21. def test_is_comparison_or_ovf_op():
  22. assert not is_comparison_or_ovf_op(rop.INT_ADD)
  23. assert is_comparison_or_ovf_op(rop.INT_ADD_OVF)
  24. assert is_comparison_or_ovf_op(rop.INT_EQ)
  25. CPU = getcpuclass()
  26. class MockGcDescr(GcCache):
  27. def get_funcptr_for_new(self):
  28. return 123
  29. get_funcptr_for_newarray = get_funcptr_for_new
  30. get_funcptr_for_newstr = get_funcptr_for_new
  31. get_funcptr_for_newunicode = get_funcptr_for_new
  32. def rewrite_assembler(self, cpu, operations):
  33. pass
  34. class MockAssembler(object):
  35. gcrefs = None
  36. _float_constants = None
  37. def __init__(self, cpu=None, gc_ll_descr=None):
  38. self.movs = []
  39. self.performs = []
  40. self.lea = []
  41. if cpu is None:
  42. cpu = CPU(None, None)
  43. cpu.setup_once()
  44. self.cpu = cpu
  45. if gc_ll_descr is None:
  46. gc_ll_descr = MockGcDescr(False)
  47. self.cpu.gc_ll_descr = gc_ll_descr
  48. def dump(self, *args):
  49. pass
  50. def regalloc_mov(self, from_loc, to_loc):
  51. self.movs.append((from_loc, to_loc))
  52. def regalloc_perform(self, op, arglocs, resloc):
  53. self.performs.append((op, arglocs, resloc))
  54. def regalloc_perform_discard(self, op, arglocs):
  55. self.performs.append((op, arglocs))
  56. def load_effective_addr(self, *args):
  57. self.lea.append(args)
  58. class RegAllocForTests(Regalloc):
  59. position = 0
  60. def _compute_next_usage(self, v, _):
  61. return -1
  62. def get_zero_division_error(self):
  63. # for tests, a random emulated ll_inst will do
  64. ll_inst = lltype.malloc(rclass.OBJECT)
  65. ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
  66. immortal=True)
  67. _zer_error_vtable = llmemory.cast_ptr_to_adr(ll_inst.typeptr)
  68. zer_vtable = self.cast_adr_to_int(_zer_error_vtable)
  69. zer_inst = lltype.cast_opaque_ptr(llmemory.GCREF, ll_inst)
  70. return zer_vtable, zer_inst
  71. class CustomBaseTestRegalloc(BaseTestRegalloc):
  72. cpu = CPU(None, None)
  73. cpu.setup_once()
  74. def raising_func(i):
  75. if i:
  76. raise LLException(zero_division_error,
  77. zero_division_value)
  78. FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void))
  79. raising_fptr = llhelper(FPTR, raising_func)
  80. def f(a):
  81. return 23
  82. FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
  83. f_fptr = llhelper(FPTR, f)
  84. f_calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
  85. EffectInfo.MOST_GENERAL)
  86. zero_division_tp, zero_division_value = get_zero_division_error(cpu)
  87. zd_addr = cpu.cast_int_to_adr(zero_division_tp)
  88. zero_division_error = llmemory.cast_adr_to_ptr(zd_addr,
  89. lltype.Ptr(rclass.OBJECT_VTABLE))
  90. raising_calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
  91. EffectInfo.MOST_GENERAL)
  92. targettoken = TargetToken()
  93. targettoken2 = TargetToken()
  94. fdescr1 = BasicFailDescr(1)
  95. fdescr2 = BasicFailDescr(2)
  96. fdescr3 = BasicFailDescr(3)
  97. def setup_method(self, meth):
  98. self.targettoken._ll_loop_code = 0
  99. self.targettoken2._ll_loop_code = 0
  100. def f1(x):
  101. return x + 1
  102. def f2(x, y):
  103. return x * y
  104. def f10(*args):
  105. assert len(args) == 10
  106. return sum(args)
  107. F1PTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
  108. F2PTR = lltype.Ptr(lltype.FuncType([lltype.Signed] * 2, lltype.Signed))
  109. F10PTR = lltype.Ptr(lltype.FuncType([lltype.Signed] * 10, lltype.Signed))
  110. f1ptr = llhelper(F1PTR, f1)
  111. f2ptr = llhelper(F2PTR, f2)
  112. f10ptr = llhelper(F10PTR, f10)
  113. f1_calldescr = cpu.calldescrof(F1PTR.TO, F1PTR.TO.ARGS, F1PTR.TO.RESULT,
  114. EffectInfo.MOST_GENERAL)
  115. f2_calldescr = cpu.calldescrof(F2PTR.TO, F2PTR.TO.ARGS, F2PTR.TO.RESULT,
  116. EffectInfo.MOST_GENERAL)
  117. f10_calldescr = cpu.calldescrof(F10PTR.TO, F10PTR.TO.ARGS,
  118. F10PTR.TO.RESULT, EffectInfo.MOST_GENERAL)
  119. typesystem = 'lltype'
  120. namespace = locals().copy()
  121. class TestRegallocSimple(CustomBaseTestRegalloc):
  122. def test_simple_loop(self):
  123. ops = '''
  124. [i0]
  125. label(i0, descr=targettoken)
  126. i1 = int_add(i0, 1)
  127. i2 = int_lt(i1, 20)
  128. guard_true(i2) [i1]
  129. jump(i1, descr=targettoken)
  130. '''
  131. self.interpret(ops, [0])
  132. assert self.getint(0) == 20
  133. def test_two_loops_and_a_bridge(self):
  134. ops = '''
  135. [i0, i1, i2, i3]
  136. label(i0, i1, i2, i3, descr=targettoken)
  137. i4 = int_add(i0, 1)
  138. i5 = int_lt(i4, 20)
  139. guard_true(i5) [i4, i1, i2, i3]
  140. jump(i4, i1, i2, i3, descr=targettoken)
  141. '''
  142. loop = self.interpret(ops, [0, 0, 0, 0])
  143. ops2 = '''
  144. [i5, i6, i7, i8]
  145. label(i5, descr=targettoken2)
  146. i1 = int_add(i5, 1)
  147. i3 = int_add(i1, 1)
  148. i4 = int_add(i3, 1)
  149. i2 = int_lt(i4, 30)
  150. guard_true(i2) [i4]
  151. jump(i4, descr=targettoken2)
  152. '''
  153. loop2 = self.interpret(ops2, [0, 0, 0, 0])
  154. bridge_ops = '''
  155. [i4]
  156. jump(i4, i4, i4, i4, descr=targettoken)
  157. '''
  158. bridge = self.attach_bridge(bridge_ops, loop2, 5)
  159. self.run(loop2, 0, 0, 0, 0)
  160. assert self.getint(0) == 31
  161. assert self.getint(1) == 30
  162. assert self.getint(2) == 30
  163. assert self.getint(3) == 30
  164. def test_pointer_arg(self):
  165. ops = '''
  166. [i0, p0]
  167. label(i0, p0, descr=targettoken)
  168. i1 = int_add(i0, 1)
  169. i2 = int_lt(i1, 10)
  170. guard_true(i2) [p0]
  171. jump(i1, p0, descr=targettoken)
  172. '''
  173. S = lltype.GcStruct('S')
  174. ptr = lltype.malloc(S)
  175. self.interpret(ops, [0, ptr])
  176. assert self.getptr(0, lltype.Ptr(S)) == ptr
  177. def test_exception_bridge_no_exception(self):
  178. ops = '''
  179. [i0]
  180. i1 = same_as_i(1)
  181. call_n(ConstClass(raising_fptr), i0, descr=raising_calldescr)
  182. guard_exception(ConstClass(zero_division_error)) [i1]
  183. finish(0)
  184. '''
  185. bridge_ops = '''
  186. [i3]
  187. i2 = same_as_i(2)
  188. guard_no_exception() [i2]
  189. finish(1)
  190. '''
  191. loop = self.interpret(ops, [0])
  192. assert self.getint(0) == 1
  193. bridge = self.attach_bridge(bridge_ops, loop, 2)
  194. self.run(loop, 0)
  195. assert self.getint(0) == 1
  196. def test_inputarg_unused(self):
  197. ops = '''
  198. [i0]
  199. finish(1)
  200. '''
  201. self.interpret(ops, [0])
  202. # assert did not explode
  203. def test_nested_guards(self):
  204. ops = '''
  205. [i0, i1]
  206. guard_true(i0) [i0, i1]
  207. finish(4)
  208. '''
  209. bridge_ops = '''
  210. [i0, i1]
  211. guard_true(i0) [i0, i1]
  212. finish(3)
  213. '''
  214. loop = self.interpret(ops, [0, 10])
  215. assert self.getint(0) == 0
  216. assert self.getint(1) == 10
  217. bridge = self.attach_bridge(bridge_ops, loop, 0)
  218. self.run(loop, 0, 10)
  219. assert self.getint(0) == 0
  220. assert self.getint(1) == 10
  221. def test_nested_unused_arg(self):
  222. ops = '''
  223. [i0, i1]
  224. guard_true(i0) [i0, i1]
  225. finish(1)
  226. '''
  227. loop = self.interpret(ops, [0, 1])
  228. assert self.getint(0) == 0
  229. bridge_ops = '''
  230. [i0, i1]
  231. guard_true(i0) [i0]
  232. finish(1)
  233. '''
  234. self.attach_bridge(bridge_ops, loop, 0)
  235. self.run(loop, 0, 1)
  236. def test_spill_for_constant(self):
  237. ops = '''
  238. [i0, i1, i2, i3]
  239. label(i0, i1, i2, i3, descr=targettoken)
  240. i4 = int_add(3, i1)
  241. i5 = int_lt(i4, 30)
  242. guard_true(i5) [i0, i4, i2, i3]
  243. jump(1, i4, 3, 4, descr=targettoken)
  244. '''
  245. self.interpret(ops, [0, 0, 0, 0])
  246. assert self.getints(4) == [1, 30, 3, 4]
  247. def test_spill_for_constant_lshift(self):
  248. ops = '''
  249. [i0, i2, i1, i3]
  250. label(i0, i2, i1, i3, descr=targettoken)
  251. i4 = int_lshift(1, i1)
  252. i5 = int_add(1, i1)
  253. i6 = int_lt(i5, 30)
  254. guard_true(i6) [i4, i5, i2, i3]
  255. jump(i4, 3, i5, 4, descr=targettoken)
  256. '''
  257. self.interpret(ops, [0, 0, 0, 0])
  258. assert self.getints(4) == [1<<29, 30, 3, 4]
  259. ops = '''
  260. [i0, i1, i2, i3]
  261. label(i0, i1, i2, i3, descr=targettoken)
  262. i4 = int_lshift(1, i1)
  263. i5 = int_add(1, i1)
  264. i6 = int_lt(i5, 30)
  265. guard_true(i6) [i4, i5, i2, i3]
  266. jump(i4, i5, 3, 4, descr=targettoken)
  267. '''
  268. self.interpret(ops, [0, 0, 0, 0])
  269. assert self.getints(4) == [1<<29, 30, 3, 4]
  270. ops = '''
  271. [i0, i3, i1, i2]
  272. label(i0, i3, i1, i2, descr=targettoken)
  273. i4 = int_lshift(1, i1)
  274. i5 = int_add(1, i1)
  275. i6 = int_lt(i5, 30)
  276. guard_true(i6) [i4, i5, i2, i3]
  277. jump(i4, 4, i5, 3, descr=targettoken)
  278. '''
  279. self.interpret(ops, [0, 0, 0, 0])
  280. assert self.getints(4) == [1<<29, 30, 3, 4]
  281. def test_result_selected_reg_via_neg(self):
  282. ops = '''
  283. [i0, i1, i2, i3]
  284. label(i0, i1, i2, i3, descr=targettoken)
  285. i6 = int_neg(i2)
  286. i7 = int_add(1, i1)
  287. i4 = int_lt(i7, 10)
  288. guard_true(i4) [i0, i6, i7]
  289. jump(1, i7, i2, i6, descr=targettoken)
  290. '''
  291. self.interpret(ops, [0, 0, 3, 0])
  292. assert self.getints(3) == [1, -3, 10]
  293. def test_compare_memory_result_survives(self):
  294. ops = '''
  295. [i0, i1, i2, i3]
  296. label(i0, i1, i2, i3, descr=targettoken)
  297. i4 = int_lt(i0, i1)
  298. i5 = int_add(i3, 1)
  299. i6 = int_lt(i5, 30)
  300. guard_true(i6) [i4]
  301. jump(i0, i1, i4, i5, descr=targettoken)
  302. '''
  303. self.interpret(ops, [0, 10, 0, 0])
  304. assert self.getint(0) == 1
  305. def test_jump_different_args(self):
  306. ops = '''
  307. [i0, i15, i16, i18, i1, i2, i3]
  308. label(i0, i15, i16, i18, i1, i2, i3, descr=targettoken)
  309. i4 = int_add(i3, 1)
  310. i5 = int_lt(i4, 20)
  311. guard_true(i5) [i2, i1]
  312. jump(i0, i18, i15, i16, i2, i1, i4, descr=targettoken)
  313. '''
  314. self.interpret(ops, [0, 1, 2, 3, 0, 0, 0])
  315. def test_op_result_unused(self):
  316. ops = '''
  317. [i0, i1]
  318. i2 = int_add(i0, i1)
  319. finish(0)
  320. '''
  321. self.interpret(ops, [0, 0])
  322. def test_guard_value_two_boxes(self):
  323. ops = '''
  324. [i0, i1, i2, i3, i4, i5, i6, i7]
  325. guard_value(i6, i1) [i0, i2, i3, i4, i5, i6]
  326. finish(i0)
  327. '''
  328. self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0])
  329. assert self.getint(0) == 0
  330. def test_bug_wrong_stack_adj(self):
  331. ops = '''
  332. [i0, i1, i2, i3, i4, i5, i6, i7, i8]
  333. i9 = same_as_i(0)
  334. guard_true(i0) [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8]
  335. finish(1)
  336. '''
  337. loop = self.interpret(ops, [0, 1, 2, 3, 4, 5, 6, 7, 8])
  338. assert self.getint(0) == 0
  339. bridge_ops = '''
  340. [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8]
  341. call_n(ConstClass(raising_fptr), 0, descr=raising_calldescr)
  342. guard_true(i0) [i0, i1, i2, i3, i4, i5, i6, i7, i8]
  343. finish(1)
  344. '''
  345. self.attach_bridge(bridge_ops, loop, 1)
  346. self.run(loop, 0, 1, 2, 3, 4, 5, 6, 7, 8)
  347. assert self.getints(9) == range(9)
  348. def test_loopargs(self):
  349. ops = """
  350. [i0, i1, i2, i3]
  351. i4 = int_add(i0, i1)
  352. jump(i4, i1, i2, i3)
  353. """
  354. regalloc = self.prepare_loop(ops)
  355. assert len(regalloc.rm.reg_bindings) == 0
  356. assert len(regalloc.frame_manager.bindings) == 4
  357. def test_loopargs_2(self):
  358. ops = """
  359. [i0, i1, i2, i3]
  360. i4 = int_add(i0, i1)
  361. guard_false(i0) [i4, i1, i2, i3]
  362. """
  363. regalloc = self.prepare_loop(ops)
  364. assert len(regalloc.frame_manager.bindings) == 4
  365. def test_loopargs_3(self):
  366. ops = """
  367. [i0, i1, i2, i3]
  368. i4 = int_add(i0, i1)
  369. guard_true(i4) [i0, i1, i2, i3, i4]
  370. jump(i4, i1, i2, i3)
  371. """
  372. regalloc = self.prepare_loop(ops)
  373. assert len(regalloc.frame_manager.bindings) == 4
  374. class TestRegallocCompOps(CustomBaseTestRegalloc):
  375. def test_cmp_op_0(self):
  376. ops = '''
  377. [i0, i3]
  378. i1 = same_as_i(1)
  379. i2 = int_lt(i0, 100)
  380. guard_true(i3) [i1, i2]
  381. finish(i2)
  382. '''
  383. self.interpret(ops, [0, 1])
  384. assert self.getint(0) == 1
  385. class TestRegallocMoreRegisters(CustomBaseTestRegalloc):
  386. cpu = CustomBaseTestRegalloc.cpu
  387. targettoken = TargetToken()
  388. S = lltype.GcStruct('S', ('field', lltype.Char))
  389. fielddescr = cpu.fielddescrof(S, 'field')
  390. A = lltype.GcArray(lltype.Char)
  391. I = lltype.GcArray(lltype.Signed)
  392. arraydescr = cpu.arraydescrof(A)
  393. arraydescr_i = cpu.arraydescrof(I)
  394. namespace = locals().copy()
  395. def test_int_is_true(self):
  396. ops = '''
  397. [i0, i1, i2, i3, i4, i5, i6, i7]
  398. i10 = int_is_true(i0)
  399. i11 = int_is_true(i1)
  400. i12 = int_is_true(i2)
  401. i13 = int_is_true(i3)
  402. i14 = int_is_true(i4)
  403. i15 = int_is_true(i5)
  404. i16 = int_is_true(i6)
  405. i17 = int_is_true(i7)
  406. guard_true(i0) [i10, i11, i12, i13, i14, i15, i16, i17]
  407. '''
  408. self.interpret(ops, [0, 42, 12, 0, 13, 0, 0, 3333])
  409. assert self.getints(8) == [0, 1, 1, 0, 1, 0, 0, 1]
  410. def test_comparison_ops(self):
  411. ops = '''
  412. [i0, i1, i2, i3, i4, i5, i6]
  413. i10 = int_lt(i0, i1)
  414. i11 = int_le(i2, i3)
  415. i12 = int_ge(i4, i5)
  416. i13 = int_eq(i5, i6)
  417. i14 = int_gt(i6, i2)
  418. i15 = int_ne(i2, i6)
  419. guard_true(i0) [i10, i11, i12, i13, i14, i15]
  420. '''
  421. self.interpret(ops, [0, 1, 2, 3, 4, 5, 6])
  422. assert self.getints(6) == [1, 1, 0, 0, 1, 1]
  423. def test_strsetitem(self):
  424. ops = '''
  425. [p0, i]
  426. strsetitem(p0, 1, i)
  427. finish()
  428. '''
  429. llstr = rstr.mallocstr(10)
  430. self.interpret(ops, [llstr, ord('a')])
  431. assert llstr.chars[1] == 'a'
  432. def test_setfield_char(self):
  433. ops = '''
  434. [p0, i]
  435. setfield_gc(p0, i, descr=fielddescr)
  436. finish()
  437. '''
  438. s = lltype.malloc(self.S)
  439. self.interpret(ops, [s, ord('a')])
  440. assert s.field == 'a'
  441. def test_setarrayitem_gc(self):
  442. ops = '''
  443. [p0, i]
  444. setarrayitem_gc(p0, 1, i, descr=arraydescr)
  445. finish()
  446. '''
  447. s = lltype.malloc(self.A, 3)
  448. self.interpret(ops, [s, ord('a')])
  449. assert s[1] == 'a'
  450. def test_setarrayitem2_gc(self):
  451. ops = '''
  452. [p0, i, i1]
  453. setarrayitem_gc(p0, i1, i, descr=arraydescr)
  454. finish()
  455. '''
  456. s = lltype.malloc(self.A, 3)
  457. self.interpret(ops, [s, ord('a'), 1])
  458. assert s[1] == 'a'
  459. def test_setarrayitem3_gc(self):
  460. ops = '''
  461. [p0, i0, i1]
  462. setarrayitem_gc(p0, i1, i0, descr=arraydescr_i)
  463. finish()
  464. '''
  465. s = lltype.malloc(self.I, 3)
  466. self.interpret(ops, [s, 1234567890, 1])
  467. assert s[1] == 1234567890
  468. def test_setarrayitem4_gc(self):
  469. ops = '''
  470. [p0, i0]
  471. setarrayitem_gc(p0, 1, i0, descr=arraydescr_i)
  472. finish()
  473. '''
  474. s = lltype.malloc(self.I, 3)
  475. self.interpret(ops, [s, 1234567890])
  476. assert s[1] == 1234567890
  477. class TestRegallocFloats(CustomBaseTestRegalloc):
  478. def test_float_add(self):
  479. if not self.cpu.supports_floats:
  480. py.test.skip("requires floats")
  481. ops = '''
  482. [f0, f1]
  483. f2 = float_add(f0, f1)
  484. guard_value(f0, f1) [f2, f0, f1]
  485. '''
  486. self.interpret(ops, [3.0, 1.5])
  487. assert self.getfloats(3) == [4.5, 3.0, 1.5]
  488. def test_float_adds_stack(self):
  489. if not self.cpu.supports_floats:
  490. py.test.skip("requires floats")
  491. ops = '''
  492. [f0, f1, f2, f3, f4, f5, f6, f7, f8]
  493. f9 = float_add(f0, f1)
  494. f10 = float_add(f8, 3.5)
  495. guard_value(f0, f1) [f9, f10, f2, f3, f4, f5, f6, f7, f8]
  496. '''
  497. self.interpret(ops, [0.1, .2, .3, .4, .5, .6, .7, .8, .9])
  498. assert self.getfloats(9) == [.1 + .2, .9 + 3.5, .3,
  499. .4, .5, .6, .7, .8, .9]
  500. def test_lt_const(self):
  501. if not self.cpu.supports_floats:
  502. py.test.skip("requires floats")
  503. ops = '''
  504. [f0]
  505. i1 = float_lt(3.5, f0)
  506. finish(i1)
  507. '''
  508. self.interpret(ops, [0.1])
  509. assert self.getint(0) == 0
  510. def test_bug_float_is_true_stack(self):
  511. if not self.cpu.supports_floats:
  512. py.test.skip("requires floats")
  513. # NB. float_is_true no longer exists. Unsure if keeping this test
  514. # makes sense any more.
  515. ops = '''
  516. [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]
  517. i0 = float_ne(f0, 0.0)
  518. i1 = float_ne(f1, 0.0)
  519. i2 = float_ne(f2, 0.0)
  520. i3 = float_ne(f3, 0.0)
  521. i4 = float_ne(f4, 0.0)
  522. i5 = float_ne(f5, 0.0)
  523. i6 = float_ne(f6, 0.0)
  524. i7 = float_ne(f7, 0.0)
  525. i8 = float_ne(f8, 0.0)
  526. i9 = float_ne(f9, 0.0)
  527. guard_false(i9), [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  528. '''
  529. self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9])
  530. assert self.getints(9) == [0, 1, 1, 1, 1, 1, 1, 1, 1]
  531. class TestRegAllocCallAndStackDepth(CustomBaseTestRegalloc):
  532. def expected_param_depth(self, num_args):
  533. # Assumes the arguments are all non-float
  534. return num_args
  535. def test_one_call(self):
  536. ops = '''
  537. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  538. i10 = call_i(ConstClass(f1ptr), i0, descr=f1_calldescr)
  539. guard_false(i10), [i10, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  540. '''
  541. self.interpret(ops, [4, 7, 9, 9, 9, 9, 9, 9, 9, 9])
  542. assert self.getints(10) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9]
  543. def test_two_calls(self):
  544. ops = '''
  545. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  546. i10 = call_i(ConstClass(f1ptr), i0, descr=f1_calldescr)
  547. i11 = call_i(ConstClass(f2ptr), i10, i1, descr=f2_calldescr)
  548. guard_false(i11) [i11, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  549. '''
  550. self.interpret(ops, [4, 7, 9, 9, 9, 9, 9, 9, 9, 9])
  551. assert self.getints(10) == [5 * 7, 7, 9, 9, 9, 9, 9, 9, 9, 9]
  552. def test_call_many_arguments(self):
  553. ops = '''
  554. [i0, i1, i2, i3, i4, i5, i6, i7]
  555. i8 = call_i(ConstClass(f10ptr), 1, i0, i1, i2, i3, i4, i5, i6, i7, 10, descr=f10_calldescr)
  556. finish(i8)
  557. '''
  558. self.interpret(ops, [2, 3, 4, 5, 6, 7, 8, 9])
  559. assert self.getint(0) == 55
  560. def test_bridge_calls_1(self):
  561. ops = '''
  562. [i0, i1]
  563. i2 = call_i(ConstClass(f1ptr), i0, descr=f1_calldescr)
  564. guard_value(i2, 0, descr=fdescr1) [i2, i1]
  565. finish(i1)
  566. '''
  567. loop = self.interpret(ops, [4, 7])
  568. assert self.getint(0) == 5
  569. ops = '''
  570. [i2, i1]
  571. i3 = call_i(ConstClass(f2ptr), i2, i1, descr=f2_calldescr)
  572. finish(i3)
  573. '''
  574. self.attach_bridge(ops, loop, -2)
  575. self.run(loop, 4, 7)
  576. assert self.getint(0) == 5 * 7
  577. def test_bridge_calls_2(self):
  578. ops = '''
  579. [i0, i1]
  580. i2 = call_i(ConstClass(f2ptr), i0, i1, descr=f2_calldescr)
  581. guard_value(i2, 0, descr=fdescr1) [i2]
  582. finish(i1)
  583. '''
  584. loop = self.interpret(ops, [4, 7])
  585. assert self.getint(0) == 4 * 7
  586. ops = '''
  587. [i2]
  588. i3 = call_i(ConstClass(f1ptr), i2, descr=f1_calldescr)
  589. finish(i3)
  590. '''
  591. self.attach_bridge(ops, loop, -2)
  592. self.run(loop, 4, 7)
  593. assert self.getint(0) == 29
  594. class TestJumps(TestRegallocSimple):
  595. def test_jump_with_consts(self):
  596. loop = """
  597. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14]
  598. label(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, descr=targettoken)
  599. jump(i1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, descr=targettoken)
  600. """
  601. self.interpret(loop, range(15), run=False)
  602. # ensure compiling this loop works
  603. assert 1
  604. def test_from_loop_to_loop(self):
  605. def assembler_helper(failindex, virtualizable):
  606. return 3
  607. FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
  608. lltype.Signed))
  609. class FakeJitDriverSD:
  610. index_of_virtualizable = -1
  611. _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
  612. assembler_helper_adr = llmemory.cast_ptr_to_adr(
  613. _assembler_helper_ptr)
  614. FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
  615. lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)), \
  616. [lltype.Signed], lltype.Signed, EffectInfo.MOST_GENERAL)
  617. self.cpu.done_with_this_frame_descr_int = BasicFinalDescr()
  618. loop1 = """
  619. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10]
  620. i11 = int_add(i0, i1)
  621. guard_false(i0) [i11, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10]
  622. """
  623. large = self.interpret(loop1, range(11), run=False)
  624. large._jitcelltoken.outermost_jitdriver_sd = FakeJitDriverSD()
  625. self.namespace['looptoken'] = large._jitcelltoken
  626. assert self.namespace['looptoken']._ll_function_addr != 0
  627. loop2 = """
  628. [i0]
  629. i1 = force_token()
  630. i2 = call_assembler_i(1,2,3,4,5,6,7,8,9,10,11, descr=looptoken)
  631. guard_not_forced() [i0]
  632. guard_false(i0) [i0, i2]
  633. """
  634. self.interpret(loop2, [110])
  635. assert self.getint(0) == 110
  636. assert self.getint(1) == 3
  637. def test_far_far_jump(self):
  638. ops = """
  639. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10]
  640. label(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, descr=targettoken)
  641. i11 = int_add(i0, 1)
  642. i12 = int_lt(i11, 2)
  643. i13 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  644. i14 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  645. i15 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  646. i16 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  647. i17 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  648. i18 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  649. i19 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  650. i20 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  651. i21 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  652. i22 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  653. i23 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  654. i24 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  655. i26 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  656. i27 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  657. i28 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  658. i29 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  659. i30 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr)
  660. guard_true(i12) [i11, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10]
  661. jump(i11, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, descr=targettoken)
  662. """
  663. self.interpret(ops, range(11))
  664. assert self.getint(0) == 2 # and not segfault()
  665. class TestStrOps(CustomBaseTestRegalloc):
  666. def test_newstr(self):
  667. ops = """
  668. [i0]
  669. p1 = newstr(300)
  670. i2 = strlen(p1)
  671. finish(i2)
  672. """
  673. self.interpret(ops, [0])
  674. assert self.getint(0) == 300
  675. ops = """
  676. [i0]
  677. p1 = newstr(i0)
  678. i2 = strlen(p1)
  679. finish(i2)
  680. """
  681. self.interpret(ops, [300])
  682. assert self.getint(0) == 300
  683. def test_strlen(self):
  684. s = rstr.mallocstr(300)
  685. ops = """
  686. [p0]
  687. i1 = strlen(p0)
  688. finish(i1)
  689. """
  690. self.interpret(ops, [s])
  691. assert self.getint(0) == 300
  692. def test_len_of_newstr(self):
  693. ops = """
  694. []
  695. p0 = newstr(300)
  696. finish(p0)
  697. """
  698. self.interpret(ops, [])
  699. string = self.getptr(0, lltype.Ptr(rstr.STR))
  700. assert len(string.chars) == 300