PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/jit/backend/x86/test/test_runner.py

https://bitbucket.org/pypy/pypy/
Python | 605 lines | 544 code | 46 blank | 15 comment | 28 complexity | e357b95385a7fa41ee8785593b4c8677 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
  3. from rpython.jit.metainterp.history import ResOperation, TargetToken,\
  4. JitCellToken
  5. from rpython.jit.metainterp.history import (ConstInt, ConstPtr, Const,
  6. BasicFailDescr, BasicFinalDescr)
  7. from rpython.jit.backend.detect_cpu import getcpuclass
  8. from rpython.jit.backend.x86.arch import WORD
  9. from rpython.jit.backend.x86.rx86 import fits_in_32bits
  10. from rpython.jit.backend.llsupport import symbolic
  11. from rpython.jit.metainterp.resoperation import rop, InputArgInt, InputArgRef
  12. from rpython.jit.metainterp.executor import execute
  13. from rpython.jit.backend.test.runner_test import LLtypeBackendTest
  14. from rpython.jit.tool.oparser import parse
  15. import ctypes
  16. CPU = getcpuclass()
  17. class FakeStats(object):
  18. pass
  19. U = LLtypeBackendTest.U
  20. S = LLtypeBackendTest.S
  21. # ____________________________________________________________
  22. class TestX86(LLtypeBackendTest):
  23. # for the individual tests see
  24. # ====> ../../test/runner_test.py
  25. if WORD == 4:
  26. add_loop_instructions = ('mov; '
  27. 'lea; ' # a nop, for the label
  28. 'add; test; je; jmp;') # plus some padding
  29. bridge_loop_instructions = 'cmp; jge; mov; mov; call; jmp;'
  30. else:
  31. add_loop_instructions = ('mov; '
  32. 'nop; ' # for the label
  33. 'add; test; je; jmp;') # plus some padding
  34. bridge_loop_instructions = (
  35. 'cmp; jge; mov;( movabs;)? mov; mov(abs)?; call; mov(abs)?; jmp;')
  36. def get_cpu(self):
  37. cpu = CPU(rtyper=None, stats=FakeStats())
  38. cpu.setup_once()
  39. return cpu
  40. def test_execute_ptr_operation(self):
  41. cpu = self.cpu
  42. u_box, _, _ = self.alloc_instance(U)
  43. u = u_box.getref(lltype.Ptr(U))
  44. ofs = cpu.fielddescrof(S, 'value')
  45. assert self.execute_operation(rop.SETFIELD_GC,
  46. [u_box, InputArgInt(3)],
  47. 'void', ofs) == None
  48. assert u.parent.parent.value == 3
  49. u.parent.parent.value += 100
  50. assert (self.execute_operation(rop.GETFIELD_GC_I, [u_box], 'int', ofs)
  51. == 103)
  52. def test_unicode(self):
  53. ofs = symbolic.get_field_token(rstr.UNICODE, 'chars', False)[0]
  54. u = rstr.mallocunicode(13)
  55. for i in range(13):
  56. u.chars[i] = unichr(ord(u'a') + i)
  57. b = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, u))
  58. r = self.execute_operation(rop.UNICODEGETITEM, [b, ConstInt(2)], 'int')
  59. assert r == ord(u'a') + 2
  60. self.execute_operation(rop.UNICODESETITEM, [b, ConstInt(2),
  61. ConstInt(ord(u'z'))],
  62. 'void')
  63. assert u.chars[2] == u'z'
  64. assert u.chars[3] == u'd'
  65. @staticmethod
  66. def _resbuf(res, item_tp=ctypes.c_long):
  67. return ctypes.cast(res._obj.intval, ctypes.POINTER(item_tp))
  68. def test_allocations(self):
  69. py.test.skip("rewrite or kill")
  70. from rpython.rtyper.lltypesystem import rstr
  71. allocs = [None]
  72. all = []
  73. orig_new = self.cpu.gc_ll_descr.funcptr_for_new
  74. def f(size):
  75. allocs.insert(0, size)
  76. return orig_new(size)
  77. self.cpu.assembler.setup_once()
  78. self.cpu.gc_ll_descr.funcptr_for_new = f
  79. ofs = symbolic.get_field_token(rstr.STR, 'chars', False)[0]
  80. res = self.execute_operation(rop.NEWSTR, [ConstInt(7)], 'ref')
  81. assert allocs[0] == 7 + ofs + WORD
  82. resbuf = self._resbuf(res)
  83. assert resbuf[ofs/WORD] == 7
  84. # ------------------------------------------------------------
  85. res = self.execute_operation(rop.NEWSTR, [InputArgInt(7)], 'ref')
  86. assert allocs[0] == 7 + ofs + WORD
  87. resbuf = self._resbuf(res)
  88. assert resbuf[ofs/WORD] == 7
  89. # ------------------------------------------------------------
  90. TP = lltype.GcArray(lltype.Signed)
  91. ofs = symbolic.get_field_token(TP, 'length', False)[0]
  92. descr = self.cpu.arraydescrof(TP)
  93. res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)],
  94. 'ref', descr)
  95. assert allocs[0] == 10*WORD + ofs + WORD
  96. resbuf = self._resbuf(res)
  97. assert resbuf[ofs/WORD] == 10
  98. # ------------------------------------------------------------
  99. res = self.execute_operation(rop.NEW_ARRAY, [InputArgInt(10)],
  100. 'ref', descr)
  101. assert allocs[0] == 10*WORD + ofs + WORD
  102. resbuf = self._resbuf(res)
  103. assert resbuf[ofs/WORD] == 10
  104. def test_stringitems(self):
  105. from rpython.rtyper.lltypesystem.rstr import STR
  106. ofs = symbolic.get_field_token(STR, 'chars', False)[0]
  107. ofs_items = symbolic.get_field_token(STR.chars, 'items', False)[0]
  108. res = self.execute_operation(rop.NEWSTR, [ConstInt(10)], 'ref')
  109. self.execute_operation(rop.STRSETITEM, [InputArgRef(res), ConstInt(2), ConstInt(ord('d'))], 'void')
  110. resbuf = self._resbuf(res, ctypes.c_char)
  111. assert resbuf[ofs + ofs_items + 2] == 'd'
  112. self.execute_operation(rop.STRSETITEM, [InputArgRef(res), InputArgInt(2), ConstInt(ord('z'))], 'void')
  113. assert resbuf[ofs + ofs_items + 2] == 'z'
  114. r = self.execute_operation(rop.STRGETITEM, [InputArgRef(res), InputArgInt(2)], 'int')
  115. assert r == ord('z')
  116. def test_arrayitems(self):
  117. TP = lltype.GcArray(lltype.Signed)
  118. ofs = symbolic.get_field_token(TP, 'length', False)[0]
  119. itemsofs = symbolic.get_field_token(TP, 'items', False)[0]
  120. descr = self.cpu.arraydescrof(TP)
  121. res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)],
  122. 'ref', descr)
  123. resbuf = self._resbuf(res)
  124. assert resbuf[ofs/WORD] == 10
  125. self.execute_operation(rop.SETARRAYITEM_GC, [InputArgRef(res),
  126. ConstInt(2), InputArgInt(38)],
  127. 'void', descr)
  128. assert resbuf[itemsofs/WORD + 2] == 38
  129. self.execute_operation(rop.SETARRAYITEM_GC, [InputArgRef(res),
  130. InputArgInt(3), InputArgInt(42)],
  131. 'void', descr)
  132. assert resbuf[itemsofs/WORD + 3] == 42
  133. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [InputArgRef(res), ConstInt(2)],
  134. 'int', descr)
  135. assert r == 38
  136. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [ConstPtr(res),
  137. InputArgInt(2)],
  138. 'int', descr)
  139. assert r == 38
  140. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [ConstPtr(res),
  141. ConstInt(2)],
  142. 'int', descr)
  143. assert r == 38
  144. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [InputArgRef(res),
  145. InputArgInt(2)],
  146. 'int', descr)
  147. assert r == 38
  148. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [InputArgRef(res), InputArgInt(3)],
  149. 'int', descr)
  150. assert r == 42
  151. def test_arrayitems_not_int(self):
  152. TP = lltype.GcArray(lltype.Char)
  153. ofs = symbolic.get_field_token(TP, 'length', False)[0]
  154. itemsofs = symbolic.get_field_token(TP, 'items', False)[0]
  155. descr = self.cpu.arraydescrof(TP)
  156. res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)],
  157. 'ref', descr)
  158. resbuf = self._resbuf(res, ctypes.c_char)
  159. res = InputArgRef(res)
  160. assert resbuf[ofs] == chr(10)
  161. for i in range(10):
  162. self.execute_operation(rop.SETARRAYITEM_GC, [res,
  163. ConstInt(i), InputArgInt(i)],
  164. 'void', descr)
  165. for i in range(10):
  166. assert resbuf[itemsofs + i] == chr(i)
  167. for i in range(10):
  168. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [res,
  169. ConstInt(i)],
  170. 'int', descr)
  171. assert r == i
  172. def test_getfield_setfield(self):
  173. TP = lltype.GcStruct('x', ('s', lltype.Signed),
  174. ('i', rffi.INT),
  175. ('f', lltype.Float),
  176. ('u', rffi.USHORT),
  177. ('c1', lltype.Char),
  178. ('c2', lltype.Char),
  179. ('c3', lltype.Char))
  180. res = InputArgRef(self.execute_operation(rop.NEW, [],
  181. 'ref', self.cpu.sizeof(TP)))
  182. ofs_s = self.cpu.fielddescrof(TP, 's')
  183. ofs_i = self.cpu.fielddescrof(TP, 'i')
  184. #ofs_f = self.cpu.fielddescrof(TP, 'f')
  185. ofs_u = self.cpu.fielddescrof(TP, 'u')
  186. ofsc1 = self.cpu.fielddescrof(TP, 'c1')
  187. ofsc2 = self.cpu.fielddescrof(TP, 'c2')
  188. ofsc3 = self.cpu.fielddescrof(TP, 'c3')
  189. self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(3)], 'void',
  190. ofs_s)
  191. # XXX ConstFloat
  192. #self.execute_operation(rop.SETFIELD_GC, [res, ofs_f, 1e100], 'void')
  193. # XXX we don't support shorts (at all)
  194. #self.execute_operation(rop.SETFIELD_GC, [res, ofs_u, ConstInt(5)], 'void')
  195. s = self.execute_operation(rop.GETFIELD_GC_I, [res], 'int', ofs_s)
  196. assert s == 3
  197. self.execute_operation(rop.SETFIELD_GC, [res, InputArgInt(3)], 'void',
  198. ofs_s)
  199. s = self.execute_operation(rop.GETFIELD_GC_I, [res], 'int', ofs_s)
  200. assert s == 3
  201. self.execute_operation(rop.SETFIELD_GC, [res, InputArgInt(1234)], 'void', ofs_i)
  202. i = self.execute_operation(rop.GETFIELD_GC_I, [res], 'int', ofs_i)
  203. assert i == 1234
  204. #u = self.execute_operation(rop.GETFIELD_GC, [res, ofs_u], 'int')
  205. #assert u.value == 5
  206. self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(1)], 'void',
  207. ofsc1)
  208. self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(3)], 'void',
  209. ofsc3)
  210. self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(2)], 'void',
  211. ofsc2)
  212. c = self.execute_operation(rop.GETFIELD_GC_I, [res], 'int', ofsc1)
  213. assert c == 1
  214. c = self.execute_operation(rop.GETFIELD_GC_I, [res], 'int', ofsc2)
  215. assert c == 2
  216. c = self.execute_operation(rop.GETFIELD_GC_I, [res], 'int', ofsc3)
  217. assert c == 3
  218. def test_bug_setfield_64bit(self):
  219. if WORD == 4:
  220. py.test.skip("only for 64 bits")
  221. TP = lltype.GcStruct('S', ('i', lltype.Signed))
  222. ofsi = self.cpu.fielddescrof(TP, 'i')
  223. for i in range(500):
  224. p = lltype.malloc(TP)
  225. addr = rffi.cast(lltype.Signed, p)
  226. if fits_in_32bits(addr):
  227. break # fitting in 32 bits, good
  228. else:
  229. py.test.skip("cannot get a 32-bit pointer")
  230. res = ConstPtr(rffi.cast(llmemory.GCREF, addr))
  231. self.execute_operation(rop.SETFIELD_RAW, [res, ConstInt(3**33)],
  232. 'void', ofsi)
  233. assert p.i == 3**33
  234. def test_getfield_64bit_offset(self):
  235. if WORD == 4:
  236. py.test.skip("only for 64 bits")
  237. TP = lltype.Struct('S', ('i', lltype.Signed))
  238. p = lltype.malloc(TP, flavor='raw')
  239. p.i = 0x123456789ABC
  240. offset = 3**33
  241. val = rffi.cast(lltype.Signed, rffi.cast(lltype.Signed, p) - offset)
  242. res = self.execute_operation(rop.GC_LOAD_I,
  243. [InputArgInt(val),
  244. ConstInt(offset),
  245. ConstInt(WORD)],
  246. 'int')
  247. assert res == 0x123456789ABC
  248. lltype.free(p, flavor='raw')
  249. def test_and_mask_common_patterns(self):
  250. cases = [8, 16, 24]
  251. if WORD == 8:
  252. cases.append(32)
  253. for i in cases:
  254. box = InputArgInt(0xAAAAAAAAAAAA)
  255. res = self.execute_operation(rop.INT_AND,
  256. [box, ConstInt(2 ** i - 1)],
  257. 'int')
  258. assert res == 0xAAAAAAAAAAAA & (2 ** i - 1)
  259. def test_nullity_with_guard(self):
  260. allops = [rop.INT_IS_TRUE]
  261. guards = [rop.GUARD_TRUE, rop.GUARD_FALSE]
  262. p = lltype.cast_opaque_ptr(llmemory.GCREF,
  263. lltype.malloc(lltype.GcStruct('x')))
  264. nullptr = lltype.nullptr(llmemory.GCREF.TO)
  265. f = InputArgInt()
  266. for op in allops:
  267. for guard in guards:
  268. if op == rop.INT_IS_TRUE:
  269. bp = InputArgInt(1)
  270. n = InputArgInt(0)
  271. else:
  272. bp = InputArgRef(p)
  273. n = InputArgRef(nullptr)
  274. for b in (bp, n):
  275. i1 = ResOperation(rop.SAME_AS_I, [ConstInt(1)])
  276. f = ResOperation(op, [b])
  277. ops = [
  278. i1,
  279. f,
  280. ResOperation(guard, [f],
  281. descr=BasicFailDescr()),
  282. ResOperation(rop.FINISH, [ConstInt(0)],
  283. descr=BasicFinalDescr()),
  284. ]
  285. ops[-2].setfailargs([i1])
  286. looptoken = JitCellToken()
  287. self.cpu.compile_loop([b], ops, looptoken)
  288. deadframe = self.cpu.execute_token(looptoken, b.getint())
  289. result = self.cpu.get_int_value(deadframe, 0)
  290. if guard == rop.GUARD_FALSE:
  291. assert result == execute(self.cpu, None,
  292. op, None, b)
  293. else:
  294. assert result != execute(self.cpu, None,
  295. op, None, b)
  296. def test_stuff_followed_by_guard(self):
  297. boxes = [(InputArgInt(1), InputArgInt(0)),
  298. (InputArgInt(0), InputArgInt(1)),
  299. (InputArgInt(1), InputArgInt(1)),
  300. (InputArgInt(-1), InputArgInt(1)),
  301. (InputArgInt(1), InputArgInt(-1)),
  302. (ConstInt(1), InputArgInt(0)),
  303. (ConstInt(0), InputArgInt(1)),
  304. (ConstInt(1), InputArgInt(1)),
  305. (ConstInt(-1), InputArgInt(1)),
  306. (ConstInt(1), InputArgInt(-1)),
  307. (InputArgInt(1), ConstInt(0)),
  308. (InputArgInt(0), ConstInt(1)),
  309. (InputArgInt(1), ConstInt(1)),
  310. (InputArgInt(-1), ConstInt(1)),
  311. (InputArgInt(1), ConstInt(-1))]
  312. guards = [rop.GUARD_FALSE, rop.GUARD_TRUE]
  313. all = [rop.INT_EQ, rop.INT_NE, rop.INT_LE, rop.INT_LT, rop.INT_GT,
  314. rop.INT_GE, rop.UINT_GT, rop.UINT_LT, rop.UINT_LE, rop.UINT_GE]
  315. for a, b in boxes:
  316. for guard in guards:
  317. for op in all:
  318. i1 = ResOperation(rop.SAME_AS_I, [ConstInt(1)])
  319. res = ResOperation(op, [a, b])
  320. ops = [
  321. i1, res,
  322. ResOperation(guard, [res],
  323. descr=BasicFailDescr()),
  324. ResOperation(rop.FINISH, [ConstInt(0)],
  325. descr=BasicFinalDescr()),
  326. ]
  327. ops[-2].setfailargs([i1])
  328. inputargs = [i for i in (a, b) if not isinstance(i, Const)]
  329. looptoken = JitCellToken()
  330. self.cpu.compile_loop(inputargs, ops, looptoken)
  331. inputvalues = [box.getint() for box in inputargs]
  332. deadframe = self.cpu.execute_token(looptoken, *inputvalues)
  333. result = self.cpu.get_int_value(deadframe, 0)
  334. expected = execute(self.cpu, None, op, None, a, b)
  335. if guard == rop.GUARD_FALSE:
  336. assert result == expected
  337. else:
  338. assert result != expected
  339. def test_compile_bridge_check_profile_info(self):
  340. py.test.skip("does not work, reinvestigate")
  341. class FakeProfileAgent(object):
  342. def __init__(self):
  343. self.functions = []
  344. def native_code_written(self, name, address, size):
  345. self.functions.append((name, address, size))
  346. self.cpu.profile_agent = agent = FakeProfileAgent()
  347. i0 = InputArgInt()
  348. i1 = InputArgInt()
  349. i2 = InputArgInt()
  350. targettoken = TargetToken()
  351. faildescr1 = BasicFailDescr(1)
  352. faildescr2 = BasicFailDescr(2)
  353. looptoken = JitCellToken()
  354. looptoken.number = 17
  355. class FakeString(object):
  356. def __init__(self, val):
  357. self.val = val
  358. def _get_str(self):
  359. return self.val
  360. operations = [
  361. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  362. ResOperation(rop.DEBUG_MERGE_POINT, [FakeString("hello"), 0, 0], None),
  363. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  364. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  365. ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
  366. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  367. ]
  368. inputargs = [i0]
  369. operations[-2].setfailargs([i1])
  370. self.cpu.compile_loop(inputargs, operations, looptoken)
  371. name, loopaddress, loopsize = agent.functions[0]
  372. assert name == "Loop # 17: hello (loop counter 0)"
  373. assert loopaddress <= looptoken._ll_loop_code
  374. assert loopsize >= 40 # randomish number
  375. i1b = InputArgInt()
  376. i3 = InputArgInt()
  377. bridge = [
  378. ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
  379. ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
  380. ResOperation(rop.DEBUG_MERGE_POINT, [FakeString("bye"), 0, 0], None),
  381. ResOperation(rop.JUMP, [i1b], None, descr=targettoken),
  382. ]
  383. bridge[1].setfailargs([i1b])
  384. self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
  385. name, address, size = agent.functions[1]
  386. assert name == "Bridge # 0: bye (loop counter 1)"
  387. # Would be exactly ==, but there are some guard failure recovery
  388. # stubs in-between
  389. assert address >= loopaddress + loopsize
  390. assert size >= 10 # randomish number
  391. deadframe = self.cpu.execute_token(looptoken, 2)
  392. fail = self.cpu.get_latest_descr(deadframe)
  393. assert fail.identifier == 2
  394. res = self.cpu.get_int_value(deadframe, 0)
  395. assert res == 20
  396. def test_ops_offset(self):
  397. from rpython.rlib import debug
  398. looptoken = JitCellToken()
  399. targettoken = TargetToken()
  400. loop = parse("""
  401. [i0]
  402. label(i0, descr=targettoken)
  403. i1 = int_add(i0, 1)
  404. i2 = int_le(i1, 9)
  405. jump(i1, descr=targettoken)
  406. """, namespace=locals())
  407. debug._log = dlog = debug.DebugLog()
  408. info = self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  409. ops_offset = info.ops_offset
  410. debug._log = None
  411. #
  412. assert ops_offset is looptoken._x86_ops_offset
  413. # 2*increment_debug_counter + ops + None
  414. assert len(ops_offset) == 2 + len(loop.operations) + 1
  415. assert (ops_offset[loop.operations[0]] <=
  416. ops_offset[loop.operations[1]] <=
  417. ops_offset[loop.operations[2]] <=
  418. ops_offset[None])
  419. def test_calling_convention(self, monkeypatch):
  420. if WORD != 4:
  421. py.test.skip("32-bit only test")
  422. from rpython.jit.backend.x86.regloc import eax, edx
  423. from rpython.jit.backend.x86 import codebuf, callbuilder
  424. from rpython.jit.codewriter.effectinfo import EffectInfo
  425. from rpython.rlib.libffi import types, clibffi
  426. had_stdcall = hasattr(clibffi, 'FFI_STDCALL')
  427. if not had_stdcall: # not running on Windows, but we can still test
  428. monkeypatch.setattr(clibffi, 'FFI_STDCALL', 12345, raising=False)
  429. monkeypatch.setattr(callbuilder, 'stdcall_or_cdecl', True)
  430. else:
  431. assert callbuilder.stdcall_or_cdecl
  432. #
  433. for real_ffi, reported_ffi in [
  434. (clibffi.FFI_DEFAULT_ABI, clibffi.FFI_DEFAULT_ABI),
  435. (clibffi.FFI_STDCALL, clibffi.FFI_DEFAULT_ABI),
  436. (clibffi.FFI_STDCALL, clibffi.FFI_STDCALL)]:
  437. cpu = self.cpu
  438. mc = codebuf.MachineCodeBlockWrapper()
  439. mc.MOV_rs(eax.value, 4) # argument 1
  440. mc.MOV_rs(edx.value, 40) # argument 10
  441. mc.SUB_rr(eax.value, edx.value) # return arg1 - arg10
  442. if real_ffi == clibffi.FFI_DEFAULT_ABI:
  443. mc.RET()
  444. else:
  445. mc.RET16_i(40)
  446. rawstart = mc.materialize(cpu, [])
  447. #
  448. calldescr = cpu._calldescr_dynamic_for_tests([types.slong] * 10,
  449. types.slong)
  450. calldescr.get_call_conv = lambda: reported_ffi # <==== hack
  451. # ^^^ we patch get_call_conv() so that the test also makes sense
  452. # on Linux, because clibffi.get_call_conv() would always
  453. # return FFI_DEFAULT_ABI on non-Windows platforms.
  454. funcbox = ConstInt(rawstart)
  455. i1 = InputArgInt()
  456. i2 = InputArgInt()
  457. c = ConstInt(-1)
  458. faildescr = BasicFailDescr(1)
  459. cz = ConstInt(0)
  460. # we must call it repeatedly: if the stack pointer gets increased
  461. # by 40 bytes by the STDCALL call, and if we don't expect it,
  462. # then we are going to get our stack emptied unexpectedly by
  463. # several repeated calls
  464. ops = [
  465. ResOperation(rop.CALL_RELEASE_GIL_I,
  466. [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
  467. descr=calldescr),
  468. ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
  469. ResOperation(rop.CALL_RELEASE_GIL_I,
  470. [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
  471. descr=calldescr),
  472. ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
  473. ResOperation(rop.CALL_RELEASE_GIL_I,
  474. [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
  475. descr=calldescr),
  476. ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
  477. ResOperation(rop.CALL_RELEASE_GIL_I,
  478. [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
  479. descr=calldescr),
  480. ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
  481. ]
  482. i3 = ops[0]
  483. i4 = ops[2]
  484. i5 = ops[4]
  485. i6 = ops[6]
  486. ops += [
  487. ResOperation(rop.GUARD_FALSE, [i3],
  488. descr=BasicFailDescr(0)),
  489. ResOperation(rop.FINISH, [],
  490. descr=BasicFinalDescr(1))
  491. ]
  492. ops[-2].setfailargs([i3, i4, i5, i6])
  493. ops[1].setfailargs([])
  494. ops[3].setfailargs([])
  495. ops[5].setfailargs([])
  496. ops[7].setfailargs([])
  497. looptoken = JitCellToken()
  498. self.cpu.compile_loop([i1, i2], ops, looptoken)
  499. deadframe = self.cpu.execute_token(looptoken, 123450, 123408)
  500. fail = self.cpu.get_latest_descr(deadframe)
  501. assert fail.identifier == 0
  502. assert self.cpu.get_int_value(deadframe, 0) == 42
  503. assert self.cpu.get_int_value(deadframe, 1) == 42
  504. assert self.cpu.get_int_value(deadframe, 2) == 42
  505. assert self.cpu.get_int_value(deadframe, 3) == 42
  506. class TestDebuggingAssembler(object):
  507. def setup_method(self, meth):
  508. self.cpu = CPU(rtyper=None, stats=FakeStats())
  509. self.cpu.setup_once()
  510. def test_debugger_on(self):
  511. from rpython.tool.logparser import parse_log_file, extract_category
  512. from rpython.rlib import debug
  513. targettoken, preambletoken = TargetToken(), TargetToken()
  514. loop = """
  515. [i0]
  516. label(i0, descr=preambletoken)
  517. debug_merge_point('xyz', 0, 0)
  518. i1 = int_add(i0, 1)
  519. i2 = int_ge(i1, 10)
  520. guard_false(i2) []
  521. label(i1, descr=targettoken)
  522. debug_merge_point('xyz', 0, 0)
  523. i11 = int_add(i1, 1)
  524. i12 = int_ge(i11, 10)
  525. guard_false(i12) []
  526. jump(i11, descr=targettoken)
  527. """
  528. ops = parse(loop, namespace={'targettoken': targettoken,
  529. 'preambletoken': preambletoken})
  530. debug._log = dlog = debug.DebugLog()
  531. try:
  532. self.cpu.assembler.set_debug(True)
  533. looptoken = JitCellToken()
  534. self.cpu.compile_loop(ops.inputargs, ops.operations, looptoken)
  535. self.cpu.execute_token(looptoken, 0)
  536. # check debugging info
  537. struct = self.cpu.assembler.get_loop_run_counters(0)
  538. assert struct.i == 1
  539. struct = self.cpu.assembler.get_loop_run_counters(1)
  540. assert struct.i == 1
  541. struct = self.cpu.assembler.get_loop_run_counters(2)
  542. assert struct.i == 9
  543. self.cpu.finish_once()
  544. finally:
  545. debug._log = None
  546. l0 = ('debug_print', 'entry -1:1')
  547. l1 = ('debug_print', preambletoken.repr_of_descr() + ':1')
  548. l2 = ('debug_print', targettoken.repr_of_descr() + ':9')
  549. assert ('jit-backend-counts', [l0, l1, l2]) in dlog