PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/jit/backend/test/runner_test.py

http://github.com/pypy/pypy
Python | 3299 lines | 3048 code | 145 blank | 106 comment | 194 complexity | 6a2f55e39c425e24ba25e3c9b6b599bb MD5 | raw file
  1. import py, sys, random, os, struct, operator
  2. from pypy.jit.metainterp.history import (AbstractFailDescr,
  3. AbstractDescr,
  4. BasicFailDescr,
  5. BoxInt, Box, BoxPtr,
  6. JitCellToken, TargetToken,
  7. ConstInt, ConstPtr,
  8. BoxObj,
  9. ConstObj, BoxFloat, ConstFloat)
  10. from pypy.jit.metainterp.resoperation import ResOperation, rop
  11. from pypy.jit.metainterp.typesystem import deref
  12. from pypy.jit.codewriter.effectinfo import EffectInfo
  13. from pypy.jit.tool.oparser import parse
  14. from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
  15. from pypy.rpython.ootypesystem import ootype
  16. from pypy.rpython.annlowlevel import llhelper
  17. from pypy.rpython.llinterp import LLException
  18. from pypy.jit.codewriter import heaptracker, longlong
  19. from pypy.rlib import longlong2float
  20. from pypy.rlib.rarithmetic import intmask, is_valid_int
  21. from pypy.jit.backend.detect_cpu import autodetect_main_model_and_size
  22. def boxfloat(x):
  23. return BoxFloat(longlong.getfloatstorage(x))
  24. def constfloat(x):
  25. return ConstFloat(longlong.getfloatstorage(x))
  26. def boxlonglong(ll):
  27. if longlong.is_64_bit:
  28. return BoxInt(ll)
  29. else:
  30. return BoxFloat(ll)
  31. class Runner(object):
  32. add_loop_instruction = ['overload for a specific cpu']
  33. bridge_loop_instruction = ['overload for a specific cpu']
  34. def execute_operation(self, opname, valueboxes, result_type, descr=None):
  35. inputargs, operations = self._get_single_operation_list(opname,
  36. result_type,
  37. valueboxes,
  38. descr)
  39. looptoken = JitCellToken()
  40. self.cpu.compile_loop(inputargs, operations, looptoken)
  41. args = []
  42. for box in inputargs:
  43. if isinstance(box, BoxInt):
  44. args.append(box.getint())
  45. elif isinstance(box, (BoxPtr, BoxObj)):
  46. args.append(box.getref_base())
  47. elif isinstance(box, BoxFloat):
  48. args.append(box.getfloatstorage())
  49. else:
  50. raise NotImplementedError(box)
  51. res = self.cpu.execute_token(looptoken, *args)
  52. if res is operations[-1].getdescr():
  53. self.guard_failed = False
  54. else:
  55. self.guard_failed = True
  56. if result_type == 'int':
  57. return BoxInt(self.cpu.get_latest_value_int(0))
  58. elif result_type == 'ref':
  59. return BoxPtr(self.cpu.get_latest_value_ref(0))
  60. elif result_type == 'float':
  61. return BoxFloat(self.cpu.get_latest_value_float(0))
  62. elif result_type == 'void':
  63. return None
  64. else:
  65. assert False
  66. def _get_single_operation_list(self, opnum, result_type, valueboxes,
  67. descr):
  68. if result_type == 'void':
  69. result = None
  70. elif result_type == 'int':
  71. result = BoxInt()
  72. elif result_type == 'ref':
  73. result = BoxPtr()
  74. elif result_type == 'float':
  75. result = BoxFloat()
  76. else:
  77. raise ValueError(result_type)
  78. if result is None:
  79. results = []
  80. else:
  81. results = [result]
  82. operations = [ResOperation(opnum, valueboxes, result),
  83. ResOperation(rop.FINISH, results, None,
  84. descr=BasicFailDescr(0))]
  85. if operations[0].is_guard():
  86. operations[0].setfailargs([])
  87. if not descr:
  88. descr = BasicFailDescr(1)
  89. if descr is not None:
  90. operations[0].setdescr(descr)
  91. inputargs = []
  92. for box in valueboxes:
  93. if isinstance(box, Box) and box not in inputargs:
  94. inputargs.append(box)
  95. return inputargs, operations
  96. class BaseBackendTest(Runner):
  97. avoid_instances = False
  98. def test_compile_linear_loop(self):
  99. i0 = BoxInt()
  100. i1 = BoxInt()
  101. operations = [
  102. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  103. ResOperation(rop.FINISH, [i1], None, descr=BasicFailDescr(1))
  104. ]
  105. inputargs = [i0]
  106. looptoken = JitCellToken()
  107. self.cpu.compile_loop(inputargs, operations, looptoken)
  108. fail = self.cpu.execute_token(looptoken, 2)
  109. res = self.cpu.get_latest_value_int(0)
  110. assert res == 3
  111. assert fail.identifier == 1
  112. def test_compile_loop(self):
  113. i0 = BoxInt()
  114. i1 = BoxInt()
  115. i2 = BoxInt()
  116. looptoken = JitCellToken()
  117. targettoken = TargetToken()
  118. operations = [
  119. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  120. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  121. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  122. ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr(2)),
  123. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  124. ]
  125. inputargs = [i0]
  126. operations[3].setfailargs([i1])
  127. self.cpu.compile_loop(inputargs, operations, looptoken)
  128. fail = self.cpu.execute_token(looptoken, 2)
  129. assert fail.identifier == 2
  130. res = self.cpu.get_latest_value_int(0)
  131. assert res == 10
  132. def test_compile_with_holes_in_fail_args(self):
  133. i0 = BoxInt()
  134. i1 = BoxInt()
  135. i2 = BoxInt()
  136. i3 = BoxInt()
  137. looptoken = JitCellToken()
  138. targettoken = TargetToken()
  139. operations = [
  140. ResOperation(rop.INT_SUB, [i3, ConstInt(42)], i0),
  141. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  142. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  143. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  144. ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr(2)),
  145. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  146. ]
  147. inputargs = [i3]
  148. operations[4].setfailargs([None, None, i1, None])
  149. self.cpu.compile_loop(inputargs, operations, looptoken)
  150. fail = self.cpu.execute_token(looptoken, 44)
  151. assert fail.identifier == 2
  152. res = self.cpu.get_latest_value_int(2)
  153. assert res == 10
  154. def test_backends_dont_keep_loops_alive(self):
  155. import weakref, gc
  156. self.cpu.dont_keepalive_stuff = True
  157. i0 = BoxInt()
  158. i1 = BoxInt()
  159. i2 = BoxInt()
  160. looptoken = JitCellToken()
  161. targettoken = TargetToken()
  162. operations = [
  163. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  164. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  165. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  166. ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr()),
  167. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  168. ]
  169. inputargs = [i0]
  170. operations[3].setfailargs([i1])
  171. wr_i1 = weakref.ref(i1)
  172. wr_guard = weakref.ref(operations[2])
  173. self.cpu.compile_loop(inputargs, operations, looptoken)
  174. if hasattr(looptoken, '_x86_ops_offset'):
  175. del looptoken._x86_ops_offset # else it's kept alive
  176. del i0, i1, i2
  177. del inputargs
  178. del operations
  179. gc.collect()
  180. assert not wr_i1() and not wr_guard()
  181. def test_compile_bridge(self):
  182. self.cpu.total_compiled_loops = 0
  183. self.cpu.total_compiled_bridges = 0
  184. i0 = BoxInt()
  185. i1 = BoxInt()
  186. i2 = BoxInt()
  187. faildescr1 = BasicFailDescr(1)
  188. faildescr2 = BasicFailDescr(2)
  189. looptoken = JitCellToken()
  190. targettoken = TargetToken()
  191. operations = [
  192. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  193. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  194. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  195. ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
  196. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  197. ]
  198. inputargs = [i0]
  199. operations[3].setfailargs([i1])
  200. self.cpu.compile_loop(inputargs, operations, looptoken)
  201. i1b = BoxInt()
  202. i3 = BoxInt()
  203. bridge = [
  204. ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
  205. ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
  206. ResOperation(rop.JUMP, [i1b], None, descr=targettoken),
  207. ]
  208. bridge[1].setfailargs([i1b])
  209. self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
  210. fail = self.cpu.execute_token(looptoken, 2)
  211. assert fail.identifier == 2
  212. res = self.cpu.get_latest_value_int(0)
  213. assert res == 20
  214. assert self.cpu.total_compiled_loops == 1
  215. assert self.cpu.total_compiled_bridges == 1
  216. return looptoken
  217. def test_compile_bridge_with_holes(self):
  218. i0 = BoxInt()
  219. i1 = BoxInt()
  220. i2 = BoxInt()
  221. i3 = BoxInt()
  222. faildescr1 = BasicFailDescr(1)
  223. faildescr2 = BasicFailDescr(2)
  224. looptoken = JitCellToken()
  225. targettoken = TargetToken()
  226. operations = [
  227. ResOperation(rop.INT_SUB, [i3, ConstInt(42)], i0),
  228. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  229. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  230. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  231. ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
  232. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  233. ]
  234. inputargs = [i3]
  235. operations[4].setfailargs([None, i1, None])
  236. self.cpu.compile_loop(inputargs, operations, looptoken)
  237. i1b = BoxInt()
  238. i3 = BoxInt()
  239. bridge = [
  240. ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
  241. ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
  242. ResOperation(rop.JUMP, [i1b], None, descr=targettoken),
  243. ]
  244. bridge[1].setfailargs([i1b])
  245. self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
  246. fail = self.cpu.execute_token(looptoken, 2)
  247. assert fail.identifier == 2
  248. res = self.cpu.get_latest_value_int(0)
  249. assert res == 20
  250. def test_compile_big_bridge_out_of_small_loop(self):
  251. i0 = BoxInt()
  252. faildescr1 = BasicFailDescr(1)
  253. looptoken = JitCellToken()
  254. operations = [
  255. ResOperation(rop.GUARD_FALSE, [i0], None, descr=faildescr1),
  256. ResOperation(rop.FINISH, [], None, descr=BasicFailDescr(2)),
  257. ]
  258. inputargs = [i0]
  259. operations[0].setfailargs([i0])
  260. self.cpu.compile_loop(inputargs, operations, looptoken)
  261. i1list = [BoxInt() for i in range(1000)]
  262. bridge = []
  263. iprev = i0
  264. for i1 in i1list:
  265. bridge.append(ResOperation(rop.INT_ADD, [iprev, ConstInt(1)], i1))
  266. iprev = i1
  267. bridge.append(ResOperation(rop.GUARD_FALSE, [i0], None,
  268. descr=BasicFailDescr(3)))
  269. bridge.append(ResOperation(rop.FINISH, [], None,
  270. descr=BasicFailDescr(4)))
  271. bridge[-2].setfailargs(i1list)
  272. self.cpu.compile_bridge(faildescr1, [i0], bridge, looptoken)
  273. fail = self.cpu.execute_token(looptoken, 1)
  274. assert fail.identifier == 3
  275. for i in range(1000):
  276. res = self.cpu.get_latest_value_int(i)
  277. assert res == 2 + i
  278. def test_get_latest_value_count(self):
  279. i0 = BoxInt()
  280. i1 = BoxInt()
  281. i2 = BoxInt()
  282. faildescr1 = BasicFailDescr(1)
  283. looptoken = JitCellToken()
  284. targettoken = TargetToken()
  285. operations = [
  286. ResOperation(rop.LABEL, [i0], None, descr=targettoken),
  287. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  288. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  289. ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
  290. ResOperation(rop.JUMP, [i1], None, descr=targettoken),
  291. ]
  292. inputargs = [i0]
  293. operations[3].setfailargs([None, i1, None])
  294. self.cpu.compile_loop(inputargs, operations, looptoken)
  295. fail = self.cpu.execute_token(looptoken, 2)
  296. assert fail is faildescr1
  297. count = self.cpu.get_latest_value_count()
  298. assert count == 3
  299. assert self.cpu.get_latest_value_int(1) == 10
  300. assert self.cpu.get_latest_value_int(1) == 10 # multiple reads ok
  301. self.cpu.clear_latest_values(3)
  302. def test_finish(self):
  303. i0 = BoxInt()
  304. class UntouchableFailDescr(AbstractFailDescr):
  305. def __setattr__(self, name, value):
  306. if name == 'index':
  307. return AbstractFailDescr.__setattr__(self, name, value)
  308. py.test.fail("finish descrs should not be touched")
  309. faildescr = UntouchableFailDescr() # to check that is not touched
  310. looptoken = JitCellToken()
  311. operations = [
  312. ResOperation(rop.FINISH, [i0], None, descr=faildescr)
  313. ]
  314. self.cpu.compile_loop([i0], operations, looptoken)
  315. fail = self.cpu.execute_token(looptoken, 99)
  316. assert fail is faildescr
  317. res = self.cpu.get_latest_value_int(0)
  318. assert res == 99
  319. looptoken = JitCellToken()
  320. operations = [
  321. ResOperation(rop.FINISH, [ConstInt(42)], None, descr=faildescr)
  322. ]
  323. self.cpu.compile_loop([], operations, looptoken)
  324. fail = self.cpu.execute_token(looptoken)
  325. assert fail is faildescr
  326. res = self.cpu.get_latest_value_int(0)
  327. assert res == 42
  328. looptoken = JitCellToken()
  329. operations = [
  330. ResOperation(rop.FINISH, [], None, descr=faildescr)
  331. ]
  332. self.cpu.compile_loop([], operations, looptoken)
  333. fail = self.cpu.execute_token(looptoken)
  334. assert fail is faildescr
  335. if self.cpu.supports_floats:
  336. looptoken = JitCellToken()
  337. f0 = BoxFloat()
  338. operations = [
  339. ResOperation(rop.FINISH, [f0], None, descr=faildescr)
  340. ]
  341. self.cpu.compile_loop([f0], operations, looptoken)
  342. value = longlong.getfloatstorage(-61.25)
  343. fail = self.cpu.execute_token(looptoken, value)
  344. assert fail is faildescr
  345. res = self.cpu.get_latest_value_float(0)
  346. assert longlong.getrealfloat(res) == -61.25
  347. looptoken = JitCellToken()
  348. operations = [
  349. ResOperation(rop.FINISH, [constfloat(42.5)], None, descr=faildescr)
  350. ]
  351. self.cpu.compile_loop([], operations, looptoken)
  352. fail = self.cpu.execute_token(looptoken)
  353. assert fail is faildescr
  354. res = self.cpu.get_latest_value_float(0)
  355. assert longlong.getrealfloat(res) == 42.5
  356. def test_execute_operations_in_env(self):
  357. cpu = self.cpu
  358. x = BoxInt(123)
  359. y = BoxInt(456)
  360. z = BoxInt(579)
  361. t = BoxInt(455)
  362. u = BoxInt(0) # False
  363. looptoken = JitCellToken()
  364. targettoken = TargetToken()
  365. operations = [
  366. ResOperation(rop.LABEL, [y, x], None, descr=targettoken),
  367. ResOperation(rop.INT_ADD, [x, y], z),
  368. ResOperation(rop.INT_SUB, [y, ConstInt(1)], t),
  369. ResOperation(rop.INT_EQ, [t, ConstInt(0)], u),
  370. ResOperation(rop.GUARD_FALSE, [u], None,
  371. descr=BasicFailDescr()),
  372. ResOperation(rop.JUMP, [t, z], None, descr=targettoken),
  373. ]
  374. operations[-2].setfailargs([t, z])
  375. cpu.compile_loop([x, y], operations, looptoken)
  376. res = self.cpu.execute_token(looptoken, 0, 10)
  377. assert self.cpu.get_latest_value_int(0) == 0
  378. assert self.cpu.get_latest_value_int(1) == 55
  379. def test_int_operations(self):
  380. from pypy.jit.metainterp.test.test_executor import get_int_tests
  381. for opnum, boxargs, retvalue in get_int_tests():
  382. res = self.execute_operation(opnum, boxargs, 'int')
  383. assert res.value == retvalue
  384. def test_float_operations(self):
  385. from pypy.jit.metainterp.test.test_executor import get_float_tests
  386. for opnum, boxargs, rettype, retvalue in get_float_tests(self.cpu):
  387. res = self.execute_operation(opnum, boxargs, rettype)
  388. if isinstance(res, BoxFloat):
  389. assert res.getfloat() == retvalue
  390. else:
  391. assert res.value == retvalue
  392. def test_ovf_operations(self, reversed=False):
  393. minint = -sys.maxint-1
  394. boom = 'boom'
  395. for opnum, testcases in [
  396. (rop.INT_ADD_OVF, [(10, -2, 8),
  397. (-1, minint, boom),
  398. (sys.maxint//2, sys.maxint//2+2, boom)]),
  399. (rop.INT_SUB_OVF, [(-20, -23, 3),
  400. (-2, sys.maxint, boom),
  401. (sys.maxint//2, -(sys.maxint//2+2), boom)]),
  402. (rop.INT_MUL_OVF, [(minint/2, 2, minint),
  403. (-2, -(minint/2), minint),
  404. (minint/2, -2, boom)]),
  405. ]:
  406. v1 = BoxInt(testcases[0][0])
  407. v2 = BoxInt(testcases[0][1])
  408. v_res = BoxInt()
  409. #
  410. if not reversed:
  411. ops = [
  412. ResOperation(opnum, [v1, v2], v_res),
  413. ResOperation(rop.GUARD_NO_OVERFLOW, [], None,
  414. descr=BasicFailDescr(1)),
  415. ResOperation(rop.FINISH, [v_res], None,
  416. descr=BasicFailDescr(2)),
  417. ]
  418. ops[1].setfailargs([])
  419. else:
  420. v_exc = self.cpu.ts.BoxRef()
  421. ops = [
  422. ResOperation(opnum, [v1, v2], v_res),
  423. ResOperation(rop.GUARD_OVERFLOW, [], None,
  424. descr=BasicFailDescr(1)),
  425. ResOperation(rop.FINISH, [], None, descr=BasicFailDescr(2)),
  426. ]
  427. ops[1].setfailargs([v_res])
  428. #
  429. looptoken = JitCellToken()
  430. self.cpu.compile_loop([v1, v2], ops, looptoken)
  431. for x, y, z in testcases:
  432. excvalue = self.cpu.grab_exc_value()
  433. assert not excvalue
  434. fail = self.cpu.execute_token(looptoken, x, y)
  435. if (z == boom) ^ reversed:
  436. assert fail.identifier == 1
  437. else:
  438. assert fail.identifier == 2
  439. if z != boom:
  440. assert self.cpu.get_latest_value_int(0) == z
  441. excvalue = self.cpu.grab_exc_value()
  442. assert not excvalue
  443. def test_ovf_operations_reversed(self):
  444. self.test_ovf_operations(reversed=True)
  445. def test_bh_call(self):
  446. cpu = self.cpu
  447. #
  448. def func(c):
  449. return chr(ord(c) + 1)
  450. FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char))
  451. func_ptr = llhelper(FPTR, func)
  452. calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char,
  453. EffectInfo.MOST_GENERAL)
  454. x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value,
  455. calldescr, [ord('A')], None, None)
  456. assert x == ord('B')
  457. if cpu.supports_floats:
  458. def func(f, i):
  459. assert isinstance(f, float)
  460. assert is_valid_int(i)
  461. return f - float(i)
  462. FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed],
  463. lltype.Float))
  464. func_ptr = llhelper(FPTR, func)
  465. FTP = deref(FPTR)
  466. calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT,
  467. EffectInfo.MOST_GENERAL)
  468. x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value,
  469. calldescr,
  470. [42], None, [longlong.getfloatstorage(3.5)])
  471. assert longlong.getrealfloat(x) == 3.5 - 42
  472. def test_call(self):
  473. from pypy.rlib.libffi import types, FUNCFLAG_CDECL
  474. def func_int(a, b):
  475. return a + b
  476. def func_char(c, c1):
  477. return chr(ord(c) + ord(c1))
  478. functions = [
  479. (func_int, lltype.Signed, types.sint, 655360),
  480. (func_int, rffi.SHORT, types.sint16, 1213),
  481. (func_char, lltype.Char, types.uchar, 12)
  482. ]
  483. for func, TP, ffi_type, num in functions:
  484. cpu = self.cpu
  485. #
  486. FPTR = self.Ptr(self.FuncType([TP, TP], TP))
  487. func_ptr = llhelper(FPTR, func)
  488. FUNC = deref(FPTR)
  489. funcbox = self.get_funcbox(cpu, func_ptr)
  490. # first, try it with the "normal" calldescr
  491. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  492. EffectInfo.MOST_GENERAL)
  493. res = self.execute_operation(rop.CALL,
  494. [funcbox, BoxInt(num), BoxInt(num)],
  495. 'int', descr=calldescr)
  496. assert res.value == 2 * num
  497. # then, try it with the dynamic calldescr
  498. dyn_calldescr = cpu.calldescrof_dynamic([ffi_type, ffi_type], ffi_type,
  499. EffectInfo.MOST_GENERAL,
  500. ffi_flags=FUNCFLAG_CDECL)
  501. res = self.execute_operation(rop.CALL,
  502. [funcbox, BoxInt(num), BoxInt(num)],
  503. 'int', descr=dyn_calldescr)
  504. assert res.value == 2 * num
  505. if cpu.supports_floats:
  506. def func(f0, f1, f2, f3, f4, f5, f6, i0, i1, f7, f8, f9):
  507. return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
  508. F = lltype.Float
  509. I = lltype.Signed
  510. FUNC = self.FuncType([F] * 7 + [I] * 2 + [F] * 3, F)
  511. FPTR = self.Ptr(FUNC)
  512. func_ptr = llhelper(FPTR, func)
  513. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  514. EffectInfo.MOST_GENERAL)
  515. funcbox = self.get_funcbox(cpu, func_ptr)
  516. args = ([boxfloat(.1) for i in range(7)] +
  517. [BoxInt(1), BoxInt(2), boxfloat(.2), boxfloat(.3),
  518. boxfloat(.4)])
  519. res = self.execute_operation(rop.CALL,
  520. [funcbox] + args,
  521. 'float', descr=calldescr)
  522. assert abs(res.getfloat() - 4.6) < 0.0001
  523. def test_call_many_arguments(self):
  524. # Test calling a function with a large number of arguments (more than
  525. # 6, which will force passing some arguments on the stack on 64-bit)
  526. def func(*args):
  527. assert len(args) == 16
  528. # Try to sum up args in a way that would probably detect a
  529. # transposed argument
  530. return sum(arg * (2**i) for i, arg in enumerate(args))
  531. FUNC = self.FuncType([lltype.Signed]*16, lltype.Signed)
  532. FPTR = self.Ptr(FUNC)
  533. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  534. EffectInfo.MOST_GENERAL)
  535. func_ptr = llhelper(FPTR, func)
  536. args = range(16)
  537. funcbox = self.get_funcbox(self.cpu, func_ptr)
  538. res = self.execute_operation(rop.CALL, [funcbox] + map(BoxInt, args), 'int', descr=calldescr)
  539. assert res.value == func(*args)
  540. def test_call_box_func(self):
  541. def a(a1, a2):
  542. return a1 + a2
  543. def b(b1, b2):
  544. return b1 * b2
  545. arg1 = 40
  546. arg2 = 2
  547. for f in [a, b]:
  548. TP = lltype.Signed
  549. FPTR = self.Ptr(self.FuncType([TP, TP], TP))
  550. func_ptr = llhelper(FPTR, f)
  551. FUNC = deref(FPTR)
  552. funcconst = self.get_funcbox(self.cpu, func_ptr)
  553. funcbox = funcconst.clonebox()
  554. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  555. EffectInfo.MOST_GENERAL)
  556. res = self.execute_operation(rop.CALL,
  557. [funcbox, BoxInt(arg1), BoxInt(arg2)],
  558. 'int', descr=calldescr)
  559. assert res.getint() == f(arg1, arg2)
  560. def test_call_stack_alignment(self):
  561. # test stack alignment issues, notably for Mac OS/X.
  562. # also test the ordering of the arguments.
  563. def func_ints(*ints):
  564. s = str(ints) + '\n'
  565. os.write(1, s) # don't remove -- crash if the stack is misaligned
  566. return sum([(10+i)*(5+j) for i, j in enumerate(ints)])
  567. for nb_args in range(0, 35):
  568. cpu = self.cpu
  569. TP = lltype.Signed
  570. #
  571. FPTR = self.Ptr(self.FuncType([TP] * nb_args, TP))
  572. func_ptr = llhelper(FPTR, func_ints)
  573. FUNC = deref(FPTR)
  574. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  575. EffectInfo.MOST_GENERAL)
  576. funcbox = self.get_funcbox(cpu, func_ptr)
  577. args = [280-24*i for i in range(nb_args)]
  578. res = self.execute_operation(rop.CALL,
  579. [funcbox] + map(BoxInt, args),
  580. 'int', descr=calldescr)
  581. assert res.value == func_ints(*args)
  582. def test_call_with_const_floats(self):
  583. def func(f1, f2):
  584. return f1 + f2
  585. FUNC = self.FuncType([lltype.Float, lltype.Float], lltype.Float)
  586. FPTR = self.Ptr(FUNC)
  587. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  588. EffectInfo.MOST_GENERAL)
  589. func_ptr = llhelper(FPTR, func)
  590. funcbox = self.get_funcbox(self.cpu, func_ptr)
  591. res = self.execute_operation(rop.CALL, [funcbox, constfloat(1.5),
  592. constfloat(2.5)], 'float',
  593. descr=calldescr)
  594. assert res.getfloat() == 4.0
  595. def test_field_basic(self):
  596. t_box, T_box = self.alloc_instance(self.T)
  597. fielddescr = self.cpu.fielddescrof(self.S, 'value')
  598. assert not fielddescr.is_pointer_field()
  599. #
  600. res = self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(39082)],
  601. 'void', descr=fielddescr)
  602. assert res is None
  603. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  604. 'int', descr=fielddescr)
  605. assert res.value == 39082
  606. #
  607. fielddescr1 = self.cpu.fielddescrof(self.S, 'chr1')
  608. fielddescr2 = self.cpu.fielddescrof(self.S, 'chr2')
  609. shortdescr = self.cpu.fielddescrof(self.S, 'short')
  610. self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(250)],
  611. 'void', descr=fielddescr2)
  612. self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(133)],
  613. 'void', descr=fielddescr1)
  614. self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(1331)],
  615. 'void', descr=shortdescr)
  616. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  617. 'int', descr=fielddescr2)
  618. assert res.value == 250
  619. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  620. 'int', descr=fielddescr1)
  621. assert res.value == 133
  622. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  623. 'int', descr=shortdescr)
  624. assert res.value == 1331
  625. #
  626. u_box, U_box = self.alloc_instance(self.U)
  627. fielddescr2 = self.cpu.fielddescrof(self.S, 'next')
  628. assert fielddescr2.is_pointer_field()
  629. res = self.execute_operation(rop.SETFIELD_GC, [t_box, u_box],
  630. 'void', descr=fielddescr2)
  631. assert res is None
  632. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  633. 'ref', descr=fielddescr2)
  634. assert res.value == u_box.value
  635. #
  636. null_const = self.null_instance().constbox()
  637. res = self.execute_operation(rop.SETFIELD_GC, [t_box, null_const],
  638. 'void', descr=fielddescr2)
  639. assert res is None
  640. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  641. 'ref', descr=fielddescr2)
  642. assert res.value == null_const.value
  643. if self.cpu.supports_floats:
  644. floatdescr = self.cpu.fielddescrof(self.S, 'float')
  645. self.execute_operation(rop.SETFIELD_GC, [t_box, boxfloat(3.4)],
  646. 'void', descr=floatdescr)
  647. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  648. 'float', descr=floatdescr)
  649. assert res.getfloat() == 3.4
  650. #
  651. self.execute_operation(rop.SETFIELD_GC, [t_box, constfloat(-3.6)],
  652. 'void', descr=floatdescr)
  653. res = self.execute_operation(rop.GETFIELD_GC, [t_box],
  654. 'float', descr=floatdescr)
  655. assert res.getfloat() == -3.6
  656. def test_passing_guards(self):
  657. t_box, T_box = self.alloc_instance(self.T)
  658. nullbox = self.null_instance()
  659. all = [(rop.GUARD_TRUE, [BoxInt(1)]),
  660. (rop.GUARD_FALSE, [BoxInt(0)]),
  661. (rop.GUARD_VALUE, [BoxInt(42), ConstInt(42)]),
  662. ]
  663. if not self.avoid_instances:
  664. all.extend([
  665. (rop.GUARD_NONNULL, [t_box]),
  666. (rop.GUARD_ISNULL, [nullbox])
  667. ])
  668. if self.cpu.supports_floats:
  669. all.append((rop.GUARD_VALUE, [boxfloat(3.5), constfloat(3.5)]))
  670. for (opname, args) in all:
  671. assert self.execute_operation(opname, args, 'void') == None
  672. assert not self.guard_failed
  673. def test_passing_guard_class(self):
  674. t_box, T_box = self.alloc_instance(self.T)
  675. #null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T)))
  676. self.execute_operation(rop.GUARD_CLASS, [t_box, T_box], 'void')
  677. assert not self.guard_failed
  678. self.execute_operation(rop.GUARD_NONNULL_CLASS, [t_box, T_box], 'void')
  679. assert not self.guard_failed
  680. def test_failing_guards(self):
  681. t_box, T_box = self.alloc_instance(self.T)
  682. nullbox = self.null_instance()
  683. all = [(rop.GUARD_TRUE, [BoxInt(0)]),
  684. (rop.GUARD_FALSE, [BoxInt(1)]),
  685. (rop.GUARD_VALUE, [BoxInt(42), ConstInt(41)]),
  686. ]
  687. if not self.avoid_instances:
  688. all.extend([
  689. (rop.GUARD_NONNULL, [nullbox]),
  690. (rop.GUARD_ISNULL, [t_box])])
  691. if self.cpu.supports_floats:
  692. all.append((rop.GUARD_VALUE, [boxfloat(-1.0), constfloat(1.0)]))
  693. for opname, args in all:
  694. assert self.execute_operation(opname, args, 'void') == None
  695. assert self.guard_failed
  696. def test_failing_guard_class(self):
  697. t_box, T_box = self.alloc_instance(self.T)
  698. u_box, U_box = self.alloc_instance(self.U)
  699. null_box = self.null_instance()
  700. for opname, args in [(rop.GUARD_CLASS, [t_box, U_box]),
  701. (rop.GUARD_CLASS, [u_box, T_box]),
  702. (rop.GUARD_NONNULL_CLASS, [t_box, U_box]),
  703. (rop.GUARD_NONNULL_CLASS, [u_box, T_box]),
  704. (rop.GUARD_NONNULL_CLASS, [null_box, T_box]),
  705. ]:
  706. assert self.execute_operation(opname, args, 'void') == None
  707. assert self.guard_failed
  708. def test_ooops(self):
  709. u1_box, U_box = self.alloc_instance(self.U)
  710. u2_box, U_box = self.alloc_instance(self.U)
  711. r = self.execute_operation(rop.PTR_EQ, [u1_box,
  712. u1_box.clonebox()], 'int')
  713. assert r.value == 1
  714. r = self.execute_operation(rop.PTR_NE, [u2_box,
  715. u2_box.clonebox()], 'int')
  716. assert r.value == 0
  717. r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int')
  718. assert r.value == 0
  719. r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int')
  720. assert r.value == 1
  721. #
  722. null_box = self.null_instance()
  723. r = self.execute_operation(rop.PTR_EQ, [null_box,
  724. null_box.clonebox()], 'int')
  725. assert r.value == 1
  726. r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int')
  727. assert r.value == 0
  728. r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int')
  729. assert r.value == 0
  730. r = self.execute_operation(rop.PTR_NE, [null_box,
  731. null_box.clonebox()], 'int')
  732. assert r.value == 0
  733. r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int')
  734. assert r.value == 1
  735. r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int')
  736. assert r.value == 1
  737. def test_array_basic(self):
  738. a_box, A = self.alloc_array_of(rffi.SHORT, 342)
  739. arraydescr = self.cpu.arraydescrof(A)
  740. assert not arraydescr.is_array_of_pointers()
  741. #
  742. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  743. 'int', descr=arraydescr)
  744. assert r.value == 342
  745. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
  746. BoxInt(744)],
  747. 'void', descr=arraydescr)
  748. assert r is None
  749. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
  750. 'int', descr=arraydescr)
  751. assert r.value == 744
  752. a_box, A = self.alloc_array_of(lltype.Signed, 342)
  753. arraydescr = self.cpu.arraydescrof(A)
  754. assert not arraydescr.is_array_of_pointers()
  755. #
  756. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  757. 'int', descr=arraydescr)
  758. assert r.value == 342
  759. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
  760. BoxInt(7441)],
  761. 'void', descr=arraydescr)
  762. assert r is None
  763. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
  764. 'int', descr=arraydescr)
  765. assert r.value == 7441
  766. #
  767. a_box, A = self.alloc_array_of(lltype.Char, 11)
  768. arraydescr = self.cpu.arraydescrof(A)
  769. assert not arraydescr.is_array_of_pointers()
  770. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  771. 'int', descr=arraydescr)
  772. assert r.value == 11
  773. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(4),
  774. BoxInt(150)],
  775. 'void', descr=arraydescr)
  776. assert r is None
  777. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(3),
  778. BoxInt(160)],
  779. 'void', descr=arraydescr)
  780. assert r is None
  781. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(4)],
  782. 'int', descr=arraydescr)
  783. assert r.value == 150
  784. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(3)],
  785. 'int', descr=arraydescr)
  786. assert r.value == 160
  787. #
  788. if isinstance(A, lltype.GcArray):
  789. A = lltype.Ptr(A)
  790. b_box, B = self.alloc_array_of(A, 3)
  791. arraydescr = self.cpu.arraydescrof(B)
  792. assert arraydescr.is_array_of_pointers()
  793. r = self.execute_operation(rop.ARRAYLEN_GC, [b_box],
  794. 'int', descr=arraydescr)
  795. assert r.value == 3
  796. r = self.execute_operation(rop.SETARRAYITEM_GC, [b_box, BoxInt(1),
  797. a_box],
  798. 'void', descr=arraydescr)
  799. assert r is None
  800. r = self.execute_operation(rop.GETARRAYITEM_GC, [b_box, BoxInt(1)],
  801. 'ref', descr=arraydescr)
  802. assert r.value == a_box.value
  803. #
  804. # Unsigned should work the same as Signed
  805. a_box, A = self.alloc_array_of(lltype.Unsigned, 342)
  806. arraydescr = self.cpu.arraydescrof(A)
  807. assert not arraydescr.is_array_of_pointers()
  808. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  809. 'int', descr=arraydescr)
  810. assert r.value == 342
  811. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
  812. BoxInt(7441)],
  813. 'void', descr=arraydescr)
  814. assert r is None
  815. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
  816. 'int', descr=arraydescr)
  817. assert r.value == 7441
  818. #
  819. # Bool should work the same as Char
  820. a_box, A = self.alloc_array_of(lltype.Bool, 311)
  821. arraydescr = self.cpu.arraydescrof(A)
  822. assert not arraydescr.is_array_of_pointers()
  823. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  824. 'int', descr=arraydescr)
  825. assert r.value == 311
  826. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(304),
  827. BoxInt(1)],
  828. 'void', descr=arraydescr)
  829. assert r is None
  830. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(303),
  831. BoxInt(0)],
  832. 'void', descr=arraydescr)
  833. assert r is None
  834. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(302),
  835. BoxInt(1)],
  836. 'void', descr=arraydescr)
  837. assert r is None
  838. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(304)],
  839. 'int', descr=arraydescr)
  840. assert r.value == 1
  841. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(303)],
  842. 'int', descr=arraydescr)
  843. assert r.value == 0
  844. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(302)],
  845. 'int', descr=arraydescr)
  846. assert r.value == 1
  847. if self.cpu.supports_floats:
  848. a_box, A = self.alloc_array_of(lltype.Float, 31)
  849. arraydescr = self.cpu.arraydescrof(A)
  850. self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(1),
  851. boxfloat(3.5)],
  852. 'void', descr=arraydescr)
  853. self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(2),
  854. constfloat(4.5)],
  855. 'void', descr=arraydescr)
  856. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(1)],
  857. 'float', descr=arraydescr)
  858. assert r.getfloat() == 3.5
  859. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(2)],
  860. 'float', descr=arraydescr)
  861. assert r.getfloat() == 4.5
  862. # For platforms where sizeof(INT) != sizeof(Signed) (ie, x86-64)
  863. a_box, A = self.alloc_array_of(rffi.INT, 342)
  864. arraydescr = self.cpu.arraydescrof(A)
  865. assert not arraydescr.is_array_of_pointers()
  866. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  867. 'int', descr=arraydescr)
  868. assert r.value == 342
  869. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
  870. BoxInt(7441)],
  871. 'void', descr=arraydescr)
  872. assert r is None
  873. r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
  874. 'int', descr=arraydescr)
  875. assert r.value == 7441
  876. def test_array_of_structs(self):
  877. TP = lltype.GcStruct('x')
  878. ITEM = lltype.Struct('x',
  879. ('vs', lltype.Signed),
  880. ('vu', lltype.Unsigned),
  881. ('vsc', rffi.SIGNEDCHAR),
  882. ('vuc', rffi.UCHAR),
  883. ('vss', rffi.SHORT),
  884. ('vus', rffi.USHORT),
  885. ('vsi', rffi.INT),
  886. ('vui', rffi.UINT),
  887. ('k', lltype.Float),
  888. ('p', lltype.Ptr(TP)))
  889. a_box, A = self.alloc_array_of(ITEM, 15)
  890. s_box, S = self.alloc_instance(TP)
  891. kdescr = self.cpu.interiorfielddescrof(A, 'k')
  892. pdescr = self.cpu.interiorfielddescrof(A, 'p')
  893. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
  894. boxfloat(1.5)],
  895. 'void', descr=kdescr)
  896. f = self.cpu.bh_getinteriorfield_gc_f(a_box.getref_base(), 3, kdescr)
  897. assert longlong.getrealfloat(f) == 1.5
  898. self.cpu.bh_setinteriorfield_gc_f(a_box.getref_base(), 3, kdescr, longlong.getfloatstorage(2.5))
  899. r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
  900. 'float', descr=kdescr)
  901. assert r.getfloat() == 2.5
  902. #
  903. NUMBER_FIELDS = [('vs', lltype.Signed),
  904. ('vu', lltype.Unsigned),
  905. ('vsc', rffi.SIGNEDCHAR),
  906. ('vuc', rffi.UCHAR),
  907. ('vss', rffi.SHORT),
  908. ('vus', rffi.USHORT),
  909. ('vsi', rffi.INT),
  910. ('vui', rffi.UINT)]
  911. for name, TYPE in NUMBER_FIELDS[::-1]:
  912. vdescr = self.cpu.interiorfielddescrof(A, name)
  913. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
  914. BoxInt(-15)],
  915. 'void', descr=vdescr)
  916. for name, TYPE in NUMBER_FIELDS:
  917. vdescr = self.cpu.interiorfielddescrof(A, name)
  918. i = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 3,
  919. vdescr)
  920. assert i == rffi.cast(lltype.Signed, rffi.cast(TYPE, -15))
  921. for name, TYPE in NUMBER_FIELDS[::-1]:
  922. vdescr = self.cpu.interiorfielddescrof(A, name)
  923. self.cpu.bh_setinteriorfield_gc_i(a_box.getref_base(), 3,
  924. vdescr, -25)
  925. for name, TYPE in NUMBER_FIELDS:
  926. vdescr = self.cpu.interiorfielddescrof(A, name)
  927. r = self.execute_operation(rop.GETINTERIORFIELD_GC,
  928. [a_box, BoxInt(3)],
  929. 'int', descr=vdescr)
  930. assert r.getint() == rffi.cast(lltype.Signed, rffi.cast(TYPE, -25))
  931. #
  932. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(4),
  933. s_box],
  934. 'void', descr=pdescr)
  935. r = self.cpu.bh_getinteriorfield_gc_r(a_box.getref_base(), 4, pdescr)
  936. assert r == s_box.getref_base()
  937. self.cpu.bh_setinteriorfield_gc_r(a_box.getref_base(), 3, pdescr,
  938. s_box.getref_base())
  939. r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
  940. 'ref', descr=pdescr)
  941. assert r.getref_base() == s_box.getref_base()
  942. def test_string_basic(self):
  943. s_box = self.alloc_string("hello\xfe")
  944. r = self.execute_operation(rop.STRLEN, [s_box], 'int')
  945. assert r.value == 6
  946. r = self.execute_operation(rop.STRGETITEM, [s_box, BoxInt(5)], 'int')
  947. assert r.value == 254
  948. r = self.execute_operation(rop.STRSETITEM, [s_box, BoxInt(4),
  949. BoxInt(153)], 'void')
  950. assert r is None
  951. r = self.execute_operation(rop.STRGETITEM, [s_box, BoxInt(5)], 'int')
  952. assert r.value == 254
  953. r = self.execute_operation(rop.STRGETITEM, [s_box, BoxInt(4)], 'int')
  954. assert r.value == 153
  955. def test_copystrcontent(self):
  956. s_box = self.alloc_string("abcdef")
  957. for s_box in [s_box, s_box.constbox()]:
  958. for srcstart_box in [BoxInt(2), ConstInt(2)]:
  959. for dststart_box in [BoxInt(3), ConstInt(3)]:
  960. for length_box in [BoxInt(4), ConstInt(4)]:
  961. for r_box_is_const in [False, True]:
  962. r_box = self.alloc_string("!???????!")
  963. if r_box_is_const:
  964. r_box = r_box.constbox()
  965. self.execute_operation(rop.COPYSTRCONTENT,
  966. [s_box, r_box,
  967. srcstart_box,
  968. dststart_box,
  969. length_box], 'void')
  970. assert self.look_string(r_box) == "!??cdef?!"
  971. def test_copyunicodecontent(self):
  972. s_box = self.alloc_unicode(u"abcdef")
  973. for s_box in [s_box, s_box.constbox()]:
  974. for srcstart_box in [BoxInt(2), ConstInt(2)]:
  975. for dststart_box in [BoxInt(3), ConstInt(3)]:
  976. for length_box in [BoxInt(4), ConstInt(4)]:
  977. for r_box_is_const in [False, True]:
  978. r_box = self.alloc_unicode(u"!???????!")
  979. if r_box_is_const:
  980. r_box = r_box.constbox()
  981. self.execute_operation(rop.COPYUNICODECONTENT,
  982. [s_box, r_box,
  983. srcstart_box,
  984. dststart_box,
  985. length_box], 'void')
  986. assert self.look_unicode(r_box) == u"!??cdef?!"
  987. def test_do_unicode_basic(self):
  988. u = self.cpu.bh_newunicode(5)
  989. self.cpu.bh_unicodesetitem(u, 4, 123)
  990. r = self.cpu.bh_unicodegetitem(u, 4)
  991. assert r == 123
  992. def test_unicode_basic(self):
  993. u_box = self.alloc_unicode(u"hello\u1234")
  994. r = self.execute_operation(rop.UNICODELEN, [u_box], 'int')
  995. assert r.value == 6
  996. r = self.execute_operation(rop.UNICODEGETITEM, [u_box, BoxInt(5)],
  997. 'int')
  998. assert r.value == 0x1234
  999. r = self.execute_operation(rop.UNICODESETITEM, [u_box, BoxInt(4),
  1000. BoxInt(31313)], 'void')
  1001. assert r is None
  1002. r = self.execute_operation(rop.UNICODEGETITEM, [u_box, BoxInt(5)],
  1003. 'int')
  1004. assert r.value == 0x1234
  1005. r = self.execute_operation(rop.UNICODEGETITEM, [u_box, BoxInt(4)],
  1006. 'int')
  1007. assert r.value == 31313
  1008. def test_same_as(self):
  1009. r = self.execute_operation(rop.SAME_AS, [ConstInt(5)], 'int')
  1010. assert r.value == 5
  1011. r = self.execute_operation(rop.SAME_AS, [BoxInt(5)], 'int')
  1012. assert r.value == 5
  1013. u_box = self.alloc_unicode(u"hello\u1234")
  1014. r = self.execute_operation(rop.SAME_AS, [u_box.constbox()], 'ref')
  1015. assert r.value == u_box.value
  1016. r = self.execute_operation(rop.SAME_AS, [u_box], 'ref')
  1017. assert r.value == u_box.value
  1018. if self.cpu.supports_floats:
  1019. r = self.execute_operation(rop.SAME_AS, [constfloat(5.5)], 'float')
  1020. assert r.getfloat() == 5.5
  1021. r = self.execute_operation(rop.SAME_AS, [boxfloat(5.5)], 'float')
  1022. assert r.getfloat() == 5.5
  1023. def test_virtual_ref(self):
  1024. pass # VIRTUAL_REF must not reach the backend nowadays
  1025. def test_virtual_ref_finish(self):
  1026. pass # VIRTUAL_REF_FINISH must not reach the backend nowadays
  1027. def test_jump(self):
  1028. # this test generates small loops where the JUMP passes many
  1029. # arguments of various types, shuffling them around.
  1030. if self.cpu.supports_floats:
  1031. numkinds = 3
  1032. else:
  1033. numkinds = 2
  1034. seed = random.randrange(0, 10000)
  1035. print 'Seed is', seed # or choose it by changing the previous line
  1036. r = random.Random()
  1037. r.seed(seed)
  1038. for nb_args in range(50):
  1039. print 'Passing %d arguments around...' % nb_args
  1040. #
  1041. inputargs = []
  1042. for k in range(nb_args):
  1043. kind = r.randrange(0, numkinds)
  1044. if kind == 0:
  1045. inputargs.append(BoxInt())
  1046. elif kind == 1:
  1047. inputargs.append(BoxPtr())
  1048. else:
  1049. inputargs.append(BoxFloat())
  1050. jumpargs = []
  1051. remixing = []
  1052. for srcbox in inputargs:
  1053. n = r.randrange(0, len(inputargs))
  1054. otherbox = inputargs[n]
  1055. if otherbox.type == srcbox.type:
  1056. remixing.append((srcbox, otherbox))
  1057. else:
  1058. otherbox = srcbox
  1059. jumpargs.append(otherbox)
  1060. #
  1061. index_counter = r.randrange(0, len(inputargs)+1)
  1062. i0 = BoxInt()
  1063. i1 = BoxInt()
  1064. i2 = BoxInt()
  1065. inputargs.insert(index_counter, i0)
  1066. jumpargs.insert(index_counter, i1)
  1067. #
  1068. looptoken = JitCellToken()
  1069. targettoken = TargetToken()
  1070. faildescr = BasicFailDescr(15)
  1071. operations = [
  1072. ResOperation(rop.LABEL, inputargs, None, descr=targettoken),
  1073. ResOperation(rop.INT_SUB, [i0, ConstInt(1)], i1),
  1074. ResOperation(rop.INT_GE, [i1, ConstInt(0)], i2),
  1075. ResOperation(rop.GUARD_TRUE, [i2], None),
  1076. ResOperation(rop.JUMP, jumpargs, None, descr=targettoken),
  1077. ]
  1078. operations[3].setfailargs(inputargs[:])
  1079. operations[3].setdescr(faildescr)
  1080. #
  1081. self.cpu.compile_loop(inputargs, operations, looptoken)
  1082. #
  1083. values = []
  1084. S = lltype.GcStruct('S')
  1085. for box in inputargs:
  1086. if isinstance(box, BoxInt):
  1087. values.append(r.randrange(-10000, 10000))
  1088. elif isinstance(box, BoxPtr):
  1089. p = lltype.malloc(S)
  1090. values.append(lltype.cast_opaque_ptr(llmemory.GCREF, p))
  1091. elif isinstance(box, BoxFloat):
  1092. values.append(longlong.getfloatstorage(r.random()))
  1093. else:
  1094. assert 0
  1095. values[index_counter] = 11
  1096. #
  1097. fail = self.cpu.execute_token(looptoken, *values)
  1098. assert fail.identifier == 15
  1099. #
  1100. dstvalues = values[:]
  1101. for _ in range(11):
  1102. expected = dstvalues[:]
  1103. for tgtbox, srcbox in remixing:
  1104. v = dstvalues[inputargs.index(srcbox)]
  1105. expected[inputargs.index(tgtbox)] = v
  1106. dstvalues = expected
  1107. #
  1108. assert dstvalues[index_counter] == 11
  1109. dstvalues[index_counter] = 0
  1110. for i, (box, val) in enumerate(zip(inputargs, dstvalues)):
  1111. if isinstance(box, BoxInt):
  1112. got = self.cpu.get_latest_value_int(i)
  1113. elif isinstance(box, BoxPtr):
  1114. got = self.cpu.get_latest_value_ref(i)
  1115. elif isinstance(box, BoxFloat):
  1116. got = self.cpu.get_latest_value_float(i)
  1117. else:
  1118. assert 0
  1119. assert type(got) == type(val)
  1120. assert got == val
  1121. def test_compile_bridge_float(self):
  1122. if not self.cpu.supports_floats:
  1123. py.test.skip("requires floats")
  1124. fboxes = [BoxFloat() for i in range(12)]
  1125. i2 = BoxInt()
  1126. targettoken = TargetToken()
  1127. faildescr1 = BasicFailDescr(1)
  1128. faildescr2 = BasicFailDescr(2)
  1129. operations = [
  1130. ResOperation(rop.LABEL, fboxes, None, descr=targettoken),
  1131. ResOperation(rop.FLOAT_LE, [fboxes[0], constfloat(9.2)], i2),
  1132. ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
  1133. ResOperation(rop.FINISH, fboxes, None, descr=faildescr2),
  1134. ]
  1135. operations[-2].setfailargs(fboxes)
  1136. looptoken = JitCellToken()
  1137. self.cpu.compile_loop(fboxes, operations, looptoken)
  1138. fboxes2 = [BoxFloat() for i in range(12)]
  1139. f3 = BoxFloat()
  1140. bridge = [
  1141. ResOperation(rop.FLOAT_SUB, [fboxes2[0], constfloat(1.0)], f3),
  1142. ResOperation(rop.JUMP, [f3]+fboxes2[1:], None, descr=targettoken),
  1143. ]
  1144. self.cpu.compile_bridge(faildescr1, fboxes2, bridge, looptoken)
  1145. args = []
  1146. for i in range(len(fboxes)):
  1147. x = 13.5 + 6.73 * i
  1148. args.append(longlong.getfloatstorage(x))
  1149. fail = self.cpu.execute_token(looptoken, *args)
  1150. assert fail.identifier == 2
  1151. res = self.cpu.get_latest_value_float(0)
  1152. assert longlong.getrealfloat(res) == 8.5
  1153. for i in range(1, len(fboxes)):
  1154. got = longlong.getrealfloat(self.cpu.get_latest_value_float(i))
  1155. assert got == 13.5 + 6.73 * i
  1156. def test_integers_and_guards(self):
  1157. for opname, compare in [
  1158. (rop.INT_LT, lambda x, y: x < y),
  1159. (rop.INT_LE, lambda x, y: x <= y),
  1160. (rop.INT_EQ, lambda x, y: x == y),
  1161. (rop.INT_NE, lambda x, y: x != y),
  1162. (rop.INT_GT, lambda x, y: x > y),
  1163. (rop.INT_GE, lambda x, y: x >= y),
  1164. ]:
  1165. for opguard, guard_case in [
  1166. (rop.GUARD_FALSE, False),
  1167. (rop.GUARD_TRUE, True),
  1168. ]:
  1169. for combinaison in ["bb", "bc", "cb"]:
  1170. #
  1171. if combinaison[0] == 'b':
  1172. ibox1 = BoxInt()
  1173. else:
  1174. ibox1 = ConstInt(-42)
  1175. if combinaison[1] == 'b':
  1176. ibox2 = BoxInt()
  1177. else:
  1178. ibox2 = ConstInt(-42)
  1179. b1 = BoxInt()
  1180. faildescr1 = BasicFailDescr(1)
  1181. faildescr2 = BasicFailDescr(2)
  1182. inputargs = [ib for ib in [ibox1, ibox2]
  1183. if isinstance(ib, BoxInt)]
  1184. operations = [
  1185. ResOperation(opname, [ibox1, ibox2], b1),
  1186. ResOperation(opguard, [b1], None, descr=faildescr1),
  1187. ResOperation(rop.FINISH, [], None, descr=faildescr2),
  1188. ]
  1189. operations[-2].setfailargs([])
  1190. looptoken = JitCellToken()
  1191. self.cpu.compile_loop(inputargs, operations, looptoken)
  1192. #
  1193. cpu = self.cpu
  1194. for test1 in [-65, -42, -11]:
  1195. if test1 == -42 or combinaison[0] == 'b':
  1196. for test2 in [-65, -42, -11]:
  1197. if test2 == -42 or combinaison[1] == 'b':
  1198. args = []
  1199. if combinaison[0] == 'b':
  1200. args.append(test1)
  1201. if combinaison[1] == 'b':
  1202. args.append(test2)
  1203. fail = cpu.execute_token(looptoken, *args)
  1204. #
  1205. expected = compare(test1, test2)
  1206. expected ^= guard_case
  1207. assert fail.identifier == 2 - expected
  1208. def test_floats_and_guards(self):
  1209. if not self.cpu.supports_floats:
  1210. py.test.skip("requires floats")
  1211. for opname, compare in [
  1212. (rop.FLOAT_LT, lambda x, y: x < y),
  1213. (rop.FLOAT_LE, lambda x, y: x <= y),
  1214. (rop.FLOAT_EQ, lambda x, y: x == y),
  1215. (rop.FLOAT_NE, lambda x, y: x != y),
  1216. (rop.FLOAT_GT, lambda x, y: x > y),
  1217. (rop.FLOAT_GE, lambda x, y: x >= y),
  1218. ]:
  1219. for opguard, guard_case in [
  1220. (rop.GUARD_FALSE, False),
  1221. (rop.GUARD_TRUE, True),
  1222. ]:
  1223. for combinaison in ["bb", "bc", "cb"]:
  1224. #
  1225. if combinaison[0] == 'b':
  1226. fbox1 = BoxFloat()
  1227. else:
  1228. fbox1 = constfloat(-4.5)
  1229. if combinaison[1] == 'b':
  1230. fbox2 = BoxFloat()
  1231. else:
  1232. fbox2 = constfloat(-4.5)
  1233. b1 = BoxInt()
  1234. faildescr1 = BasicFailDescr(1)
  1235. faildescr2 = BasicFailDescr(2)
  1236. inputargs = [fb for fb in [fbox1, fbox2]
  1237. if isinstance(fb, BoxFloat)]
  1238. operations = [
  1239. ResOperation(opname, [fbox1, fbox2], b1),
  1240. ResOperation(opguard, [b1], None, descr=faildescr1),
  1241. ResOperation(rop.FINISH, [], None, descr=faildescr2),
  1242. ]
  1243. operations[-2].setfailargs([])
  1244. looptoken = JitCellToken()
  1245. self.cpu.compile_loop(inputargs, operations, looptoken)
  1246. #
  1247. cpu = self.cpu
  1248. nan = 1e200 * 1e200
  1249. nan /= nan
  1250. for test1 in [-6.5, -4.5, -2.5, nan]:
  1251. if test1 == -4.5 or combinaison[0] == 'b':
  1252. for test2 in [-6.5, -4.5, -2.5, nan]:
  1253. if test2 == -4.5 or combinaison[1] == 'b':
  1254. args = []
  1255. if combinaison[0] == 'b':
  1256. args.append(
  1257. longlong.getfloatstorage(test1))
  1258. if combinaison[1] == 'b':
  1259. args.append(
  1260. longlong.getfloatstorage(test2))
  1261. fail = cpu.execute_token(looptoken, *args)
  1262. #
  1263. expected = compare(test1, test2)
  1264. expected ^= guard_case
  1265. assert fail.identifier == 2 - expected
  1266. def test_unused_result_int(self):
  1267. # test pure operations on integers whose result is not used
  1268. from pypy.jit.metainterp.test.test_executor import get_int_tests
  1269. int_tests = list(get_int_tests())
  1270. int_tests = [(opnum, boxargs, 'int', retvalue)
  1271. for opnum, boxargs, retvalue in int_tests]
  1272. self._test_unused_result(int_tests)
  1273. def test_unused_result_float(self):
  1274. # same as test_unused_result_int, for float operations
  1275. from pypy.jit.metainterp.test.test_executor import get_float_tests
  1276. float_tests = list(get_float_tests(self.cpu))
  1277. self._test_unused_result(float_tests)
  1278. def _test_unused_result(self, tests):
  1279. while len(tests) > 50: # only up to 50 tests at once
  1280. self._test_unused_result(tests[:50])
  1281. tests = tests[50:]
  1282. inputargs = []
  1283. operations = []
  1284. for opnum, boxargs, rettype, retvalue in tests:
  1285. inputargs += [box for box in boxargs if isinstance(box, Box)]
  1286. if rettype == 'int':
  1287. boxres = BoxInt()
  1288. elif rettype == 'float':
  1289. boxres = BoxFloat()
  1290. else:
  1291. assert 0
  1292. operations.append(ResOperation(opnum, boxargs, boxres))
  1293. # Unique-ify inputargs
  1294. inputargs = list(set(inputargs))
  1295. faildescr = BasicFailDescr(1)
  1296. operations.append(ResOperation(rop.FINISH, [], None,
  1297. descr=faildescr))
  1298. looptoken = JitCellToken()
  1299. #
  1300. self.cpu.compile_loop(inputargs, operations, looptoken)
  1301. #
  1302. args = []
  1303. for box in inputargs:
  1304. if isinstance(box, BoxInt):
  1305. args.append(box.getint())
  1306. elif isinstance(box, BoxFloat):
  1307. args.append(box.getfloatstorage())
  1308. else:
  1309. assert 0
  1310. #
  1311. fail = self.cpu.execute_token(looptoken, *args)
  1312. assert fail.identifier == 1
  1313. def test_nan_and_infinity(self):
  1314. if not self.cpu.supports_floats:
  1315. py.test.skip("requires floats")
  1316. from pypy.rlib.rfloat import INFINITY, NAN, isinf, isnan
  1317. from pypy.jit.metainterp.resoperation import opname
  1318. fzer = boxfloat(0.0)
  1319. fone = boxfloat(1.0)
  1320. fmqr = boxfloat(-0.25)
  1321. finf = boxfloat(INFINITY)
  1322. fmnf = boxfloat(-INFINITY)
  1323. fnan = boxfloat(NAN)
  1324. all_cases_unary = [(a,) for a in [fzer,fone,fmqr,finf,fmnf,fnan]]
  1325. all_cases_binary = [(a, b) for a in [fzer,fone,fmqr,finf,fmnf,fnan]
  1326. for b in [fzer,fone,fmqr,finf,fmnf,fnan]]
  1327. no_zero_divison = [(a, b) for a in [fzer,fone,fmqr,finf,fmnf,fnan]
  1328. for b in [ fone,fmqr,finf,fmnf,fnan]]
  1329. def nan_and_infinity(opnum, realoperation, testcases):
  1330. for testcase in testcases:
  1331. realvalues = [b.getfloat() for b in testcase]
  1332. expected = realoperation(*realvalues)
  1333. if isinstance(expected, float):
  1334. expectedtype = 'float'
  1335. else:
  1336. expectedtype = 'int'
  1337. got = self.execute_operation(opnum, list(testcase),
  1338. expectedtype)
  1339. if isnan(expected):
  1340. ok = isnan(got.getfloat())
  1341. elif isinf(expected):
  1342. ok = isinf(got.getfloat())
  1343. elif isinstance(got, BoxFloat):
  1344. ok = (got.getfloat() == expected)
  1345. else:
  1346. ok = got.value == expected
  1347. if not ok:
  1348. raise AssertionError("%s(%s): got %r, expected %r" % (
  1349. opname[opnum], ', '.join(map(repr, realvalues)),
  1350. got.getfloat(), expected))
  1351. # if we expect a boolean, also check the combination with
  1352. # a GUARD_TRUE or GUARD_FALSE
  1353. if isinstance(expected, bool):
  1354. for guard_opnum, expected_id in [(rop.GUARD_TRUE, 1),
  1355. (rop.GUARD_FALSE, 0)]:
  1356. box = BoxInt()
  1357. operations = [
  1358. ResOperation(opnum, list(testcase), box),
  1359. ResOperation(guard_opnum, [box], None,
  1360. descr=BasicFailDescr(4)),
  1361. ResOperation(rop.FINISH, [], None,
  1362. descr=BasicFailDescr(5))]
  1363. operations[1].setfailargs([])
  1364. looptoken = JitCellToken()
  1365. # Use "set" to unique-ify inputargs
  1366. unique_testcase_list = list(set(testcase))
  1367. self.cpu.compile_loop(unique_testcase_list, operations,
  1368. looptoken)
  1369. args = [box.getfloatstorage()
  1370. for box in unique_testcase_list]
  1371. fail = self.cpu.execute_token(looptoken, *args)
  1372. if fail.identifier != 5 - (expected_id^expected):
  1373. if fail.identifier == 4:
  1374. msg = "was taken"
  1375. else:
  1376. msg = "was not taken"
  1377. raise AssertionError(
  1378. "%s(%s)/%s took the wrong path: "
  1379. "the failure path of the guard %s" % (
  1380. opname[opnum],
  1381. ', '.join(map(repr, realvalues)),
  1382. opname[guard_opnum], msg))
  1383. yield nan_and_infinity, rop.FLOAT_ADD, operator.add, all_cases_binary
  1384. yield nan_and_infinity, rop.FLOAT_SUB, operator.sub, all_cases_binary
  1385. yield nan_and_infinity, rop.FLOAT_MUL, operator.mul, all_cases_binary
  1386. yield nan_and_infinity, rop.FLOAT_TRUEDIV, \
  1387. operator.truediv, no_zero_divison
  1388. yield nan_and_infinity, rop.FLOAT_NEG, operator.neg, all_cases_unary
  1389. yield nan_and_infinity, rop.FLOAT_ABS, abs, all_cases_unary
  1390. yield nan_and_infinity, rop.FLOAT_LT, operator.lt, all_cases_binary
  1391. yield nan_and_infinity, rop.FLOAT_LE, operator.le, all_cases_binary
  1392. yield nan_and_infinity, rop.FLOAT_EQ, operator.eq, all_cases_binary
  1393. yield nan_and_infinity, rop.FLOAT_NE, operator.ne, all_cases_binary
  1394. yield nan_and_infinity, rop.FLOAT_GT, operator.gt, all_cases_binary
  1395. yield nan_and_infinity, rop.FLOAT_GE, operator.ge, all_cases_binary
  1396. def test_noops(self):
  1397. c_box = self.alloc_string("hi there").constbox()
  1398. c_nest = ConstInt(0)
  1399. c_id = ConstInt(0)
  1400. self.execute_operation(rop.DEBUG_MERGE_POINT, [c_box, c_nest, c_id], 'void')
  1401. self.execute_operation(rop.JIT_DEBUG, [c_box, c_nest, c_nest,
  1402. c_nest, c_nest], 'void')
  1403. def test_read_timestamp(self):
  1404. if sys.platform == 'win32':
  1405. # windows quite often is very inexact (like the old Intel 8259 PIC),
  1406. # so we stretch the time a little bit.
  1407. # On my virtual Parallels machine in a 2GHz Core i7 Mac Mini,
  1408. # the test starts working at delay == 21670 and stops at 20600000.
  1409. # We take the geometric mean value.
  1410. from math import log, exp
  1411. delay_min = 21670
  1412. delay_max = 20600000
  1413. delay = int(exp((log(delay_min)+log(delay_max))/2))
  1414. def wait_a_bit():
  1415. for i in xrange(delay): pass
  1416. else:
  1417. def wait_a_bit():
  1418. pass
  1419. if longlong.is_64_bit:
  1420. got1 = self.execute_operation(rop.READ_TIMESTAMP, [], 'int')
  1421. wait_a_bit()
  1422. got2 = self.execute_operation(rop.READ_TIMESTAMP, [], 'int')
  1423. res1 = got1.getint()
  1424. res2 = got2.getint()
  1425. else:
  1426. got1 = self.execute_operation(rop.READ_TIMESTAMP, [], 'float')
  1427. wait_a_bit()
  1428. got2 = self.execute_operation(rop.READ_TIMESTAMP, [], 'float')
  1429. res1 = got1.getlonglong()
  1430. res2 = got2.getlonglong()
  1431. assert res1 < res2 < res1 + 2**32
  1432. class LLtypeBackendTest(BaseBackendTest):
  1433. type_system = 'lltype'
  1434. Ptr = lltype.Ptr
  1435. FuncType = lltype.FuncType
  1436. malloc = staticmethod(lltype.malloc)
  1437. nullptr = staticmethod(lltype.nullptr)
  1438. @classmethod
  1439. def get_funcbox(cls, cpu, func_ptr):
  1440. addr = llmemory.cast_ptr_to_adr(func_ptr)
  1441. return ConstInt(heaptracker.adr2int(addr))
  1442. MY_VTABLE = rclass.OBJECT_VTABLE # for tests only
  1443. S = lltype.GcForwardReference()
  1444. S.become(lltype.GcStruct('S', ('parent', rclass.OBJECT),
  1445. ('value', lltype.Signed),
  1446. ('chr1', lltype.Char),
  1447. ('chr2', lltype.Char),
  1448. ('short', rffi.SHORT),
  1449. ('next', lltype.Ptr(S)),
  1450. ('float', lltype.Float)))
  1451. T = lltype.GcStruct('T', ('parent', S),
  1452. ('next', lltype.Ptr(S)))
  1453. U = lltype.GcStruct('U', ('parent', T),
  1454. ('next', lltype.Ptr(S)))
  1455. def alloc_instance(self, T):
  1456. vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True)
  1457. vtable_for_T_addr = llmemory.cast_ptr_to_adr(vtable_for_T)
  1458. cpu = self.cpu
  1459. if not hasattr(cpu, '_cache_gcstruct2vtable'):
  1460. cpu._cache_gcstruct2vtable = {}
  1461. cpu._cache_gcstruct2vtable.update({T: vtable_for_T})
  1462. t = lltype.malloc(T)
  1463. if T == self.T:
  1464. t.parent.parent.typeptr = vtable_for_T
  1465. elif T == self.U:
  1466. t.parent.parent.parent.typeptr = vtable_for_T
  1467. t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t))
  1468. T_box = ConstInt(heaptracker.adr2int(vtable_for_T_addr))
  1469. return t_box, T_box
  1470. def null_instance(self):
  1471. return BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
  1472. def alloc_array_of(self, ITEM, length):
  1473. A = lltype.GcArray(ITEM)
  1474. a = lltype.malloc(A, length)
  1475. a_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a))
  1476. return a_box, A
  1477. def alloc_string(self, string):
  1478. s = rstr.mallocstr(len(string))
  1479. for i in range(len(string)):
  1480. s.chars[i] = string[i]
  1481. s_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))
  1482. return s_box
  1483. def look_string(self, string_box):
  1484. s = string_box.getref(lltype.Ptr(rstr.STR))
  1485. return ''.join(s.chars)
  1486. def alloc_unicode(self, unicode):
  1487. u = rstr.mallocunicode(len(unicode))
  1488. for i in range(len(unicode)):
  1489. u.chars[i] = unicode[i]
  1490. u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u))
  1491. return u_box
  1492. def look_unicode(self, unicode_box):
  1493. u = unicode_box.getref(lltype.Ptr(rstr.UNICODE))
  1494. return u''.join(u.chars)
  1495. def test_cast_int_to_ptr(self):
  1496. res = self.execute_operation(rop.CAST_INT_TO_PTR,
  1497. [BoxInt(-17)], 'ref').value
  1498. assert lltype.cast_ptr_to_int(res) == -17
  1499. def test_cast_ptr_to_int(self):
  1500. x = lltype.cast_int_to_ptr(llmemory.GCREF, -19)
  1501. res = self.execute_operation(rop.CAST_PTR_TO_INT,
  1502. [BoxPtr(x)], 'int').value
  1503. assert res == -19
  1504. def test_convert_float_bytes(self):
  1505. t = 'int' if longlong.is_64_bit else 'float'
  1506. res = self.execute_operation(rop.CONVERT_FLOAT_BYTES_TO_LONGLONG,
  1507. [boxfloat(2.5)], t).value
  1508. assert res == longlong2float.float2longlong(2.5)
  1509. bytes = longlong2float.float2longlong(2.5)
  1510. res = self.execute_operation(rop.CONVERT_LONGLONG_BYTES_TO_FLOAT,
  1511. [boxlonglong(res)], 'float').value
  1512. assert longlong.getrealfloat(res) == 2.5
  1513. def test_ooops_non_gc(self):
  1514. x = lltype.malloc(lltype.Struct('x'), flavor='raw')
  1515. v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x))
  1516. r = self.execute_operation(rop.PTR_EQ, [BoxInt(v), BoxInt(v)], 'int')
  1517. assert r.value == 1
  1518. r = self.execute_operation(rop.PTR_NE, [BoxInt(v), BoxInt(v)], 'int')
  1519. assert r.value == 0
  1520. lltype.free(x, flavor='raw')
  1521. def test_new_plain_struct(self):
  1522. cpu = self.cpu
  1523. S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Char))
  1524. sizedescr = cpu.sizeof(S)
  1525. r1 = self.execute_operation(rop.NEW, [], 'ref', descr=sizedescr)
  1526. r2 = self.execute_operation(rop.NEW, [], 'ref', descr=sizedescr)
  1527. assert r1.value != r2.value
  1528. xdescr = cpu.fielddescrof(S, 'x')
  1529. ydescr = cpu.fielddescrof(S, 'y')
  1530. self.execute_operation(rop.SETFIELD_GC, [r1, BoxInt(150)],
  1531. 'void', descr=ydescr)
  1532. self.execute_operation(rop.SETFIELD_GC, [r1, BoxInt(190)],
  1533. 'void', descr=xdescr)
  1534. s = lltype.cast_opaque_ptr(lltype.Ptr(S), r1.value)
  1535. assert s.x == chr(190)
  1536. assert s.y == chr(150)
  1537. def test_fielddescrof_dynamic(self):
  1538. S = lltype.Struct('S',
  1539. ('x', lltype.Signed),
  1540. ('y', lltype.Signed),
  1541. )
  1542. longsize = rffi.sizeof(lltype.Signed)
  1543. y_ofs = longsize
  1544. s = lltype.malloc(S, flavor='raw')
  1545. sa = llmemory.cast_ptr_to_adr(s)
  1546. s_box = BoxInt(heaptracker.adr2int(sa))
  1547. #
  1548. field = self.cpu.fielddescrof(S, 'y')
  1549. field_dyn = self.cpu.fielddescrof_dynamic(offset=y_ofs,
  1550. fieldsize=longsize,
  1551. is_pointer=False,
  1552. is_float=False,
  1553. is_signed=True)
  1554. assert field.is_pointer_field() == field_dyn.is_pointer_field()
  1555. assert field.is_float_field() == field_dyn.is_float_field()
  1556. if 'llgraph' not in str(self.cpu):
  1557. assert field.is_field_signed() == field_dyn.is_field_signed()
  1558. #
  1559. for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW),
  1560. (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)):
  1561. for descr in (field, field_dyn):
  1562. self.execute_operation(set_op, [s_box, BoxInt(32)], 'void',
  1563. descr=descr)
  1564. res = self.execute_operation(get_op, [s_box], 'int', descr=descr)
  1565. assert res.getint() == 32
  1566. lltype.free(s, flavor='raw')
  1567. def test_new_with_vtable(self):
  1568. cpu = self.cpu
  1569. t_box, T_box = self.alloc_instance(self.T)
  1570. vtable = llmemory.cast_adr_to_ptr(
  1571. llmemory.cast_int_to_adr(T_box.value), heaptracker.VTABLETYPE)
  1572. heaptracker.register_known_gctype(cpu, vtable, self.T)
  1573. r1 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref')
  1574. r2 = self.execute_operation(rop.NEW_WITH_VTABLE, [T_box], 'ref')
  1575. assert r1.value != r2.value
  1576. descr1 = cpu.fielddescrof(self.S, 'chr1')
  1577. descr2 = cpu.fielddescrof(self.S, 'chr2')
  1578. descrshort = cpu.fielddescrof(self.S, 'short')
  1579. self.execute_operation(rop.SETFIELD_GC, [r1, BoxInt(150)],
  1580. 'void', descr=descr2)
  1581. self.execute_operation(rop.SETFIELD_GC, [r1, BoxInt(190)],
  1582. 'void', descr=descr1)
  1583. self.execute_operation(rop.SETFIELD_GC, [r1, BoxInt(1313)],
  1584. 'void', descr=descrshort)
  1585. s = lltype.cast_opaque_ptr(lltype.Ptr(self.T), r1.value)
  1586. assert s.parent.chr1 == chr(190)
  1587. assert s.parent.chr2 == chr(150)
  1588. r = self.cpu.bh_getfield_gc_i(r1.value, descrshort)
  1589. assert r == 1313
  1590. self.cpu.bh_setfield_gc_i(r1.value, descrshort, 1333)
  1591. r = self.cpu.bh_getfield_gc_i(r1.value, descrshort)
  1592. assert r == 1333
  1593. r = self.execute_operation(rop.GETFIELD_GC, [r1], 'int',
  1594. descr=descrshort)
  1595. assert r.value == 1333
  1596. t = lltype.cast_opaque_ptr(lltype.Ptr(self.T), t_box.value)
  1597. assert s.parent.parent.typeptr == t.parent.parent.typeptr
  1598. def test_new_array(self):
  1599. A = lltype.GcArray(lltype.Signed)
  1600. arraydescr = self.cpu.arraydescrof(A)
  1601. r1 = self.execute_operation(rop.NEW_ARRAY, [BoxInt(342)],
  1602. 'ref', descr=arraydescr)
  1603. r2 = self.execute_operation(rop.NEW_ARRAY, [BoxInt(342)],
  1604. 'ref', descr=arraydescr)
  1605. assert r1.value != r2.value
  1606. a = lltype.cast_opaque_ptr(lltype.Ptr(A), r1.value)
  1607. assert a[0] == 0
  1608. assert len(a) == 342
  1609. def test_new_string(self):
  1610. r1 = self.execute_operation(rop.NEWSTR, [BoxInt(342)], 'ref')
  1611. r2 = self.execute_operation(rop.NEWSTR, [BoxInt(342)], 'ref')
  1612. assert r1.value != r2.value
  1613. a = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), r1.value)
  1614. assert len(a.chars) == 342
  1615. def test_new_unicode(self):
  1616. r1 = self.execute_operation(rop.NEWUNICODE, [BoxInt(342)], 'ref')
  1617. r2 = self.execute_operation(rop.NEWUNICODE, [BoxInt(342)], 'ref')
  1618. assert r1.value != r2.value
  1619. a = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), r1.value)
  1620. assert len(a.chars) == 342
  1621. def test_exceptions(self):
  1622. exc_tp = None
  1623. exc_ptr = None
  1624. def func(i):
  1625. if i:
  1626. raise LLException(exc_tp, exc_ptr)
  1627. ops = '''
  1628. [i0]
  1629. i1 = same_as(1)
  1630. call(ConstClass(fptr), i0, descr=calldescr)
  1631. p0 = guard_exception(ConstClass(xtp)) [i1]
  1632. finish(0, p0)
  1633. '''
  1634. FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void))
  1635. fptr = llhelper(FPTR, func)
  1636. calldescr = self.cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
  1637. EffectInfo.MOST_GENERAL)
  1638. xtp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
  1639. xtp.subclassrange_min = 1
  1640. xtp.subclassrange_max = 3
  1641. X = lltype.GcStruct('X', ('parent', rclass.OBJECT),
  1642. hints={'vtable': xtp._obj})
  1643. xptr = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(X))
  1644. exc_tp = xtp
  1645. exc_ptr = xptr
  1646. loop = parse(ops, self.cpu, namespace=locals())
  1647. looptoken = JitCellToken()
  1648. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  1649. self.cpu.execute_token(looptoken, 1)
  1650. assert self.cpu.get_latest_value_int(0) == 0
  1651. assert self.cpu.get_latest_value_ref(1) == xptr
  1652. excvalue = self.cpu.grab_exc_value()
  1653. assert not excvalue
  1654. self.cpu.execute_token(looptoken, 0)
  1655. assert self.cpu.get_latest_value_int(0) == 1
  1656. excvalue = self.cpu.grab_exc_value()
  1657. assert not excvalue
  1658. ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
  1659. ytp.subclassrange_min = 2
  1660. ytp.subclassrange_max = 2
  1661. assert rclass.ll_issubclass(ytp, xtp)
  1662. Y = lltype.GcStruct('Y', ('parent', rclass.OBJECT),
  1663. hints={'vtable': ytp._obj})
  1664. yptr = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(Y))
  1665. # guard_exception uses an exact match
  1666. exc_tp = ytp
  1667. exc_ptr = yptr
  1668. loop = parse(ops, self.cpu, namespace=locals())
  1669. looptoken = JitCellToken()
  1670. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  1671. self.cpu.execute_token(looptoken, 1)
  1672. assert self.cpu.get_latest_value_int(0) == 1
  1673. excvalue = self.cpu.grab_exc_value()
  1674. assert excvalue == yptr
  1675. assert not self.cpu.grab_exc_value() # cleared
  1676. exc_tp = xtp
  1677. exc_ptr = xptr
  1678. ops = '''
  1679. [i0]
  1680. i1 = same_as(1)
  1681. call(ConstClass(fptr), i0, descr=calldescr)
  1682. guard_no_exception() [i1]
  1683. finish(0)
  1684. '''
  1685. loop = parse(ops, self.cpu, namespace=locals())
  1686. looptoken = JitCellToken()
  1687. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  1688. self.cpu.execute_token(looptoken, 1)
  1689. assert self.cpu.get_latest_value_int(0) == 1
  1690. excvalue = self.cpu.grab_exc_value()
  1691. assert excvalue == xptr
  1692. self.cpu.execute_token(looptoken, 0)
  1693. assert self.cpu.get_latest_value_int(0) == 0
  1694. excvalue = self.cpu.grab_exc_value()
  1695. assert not excvalue
  1696. def test_cond_call_gc_wb(self):
  1697. def func_void(a, b):
  1698. record.append((a, b))
  1699. record = []
  1700. #
  1701. S = lltype.GcStruct('S', ('tid', lltype.Signed))
  1702. FUNC = self.FuncType([lltype.Ptr(S), lltype.Ptr(S)], lltype.Void)
  1703. func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
  1704. funcbox = self.get_funcbox(self.cpu, func_ptr)
  1705. class WriteBarrierDescr(AbstractDescr):
  1706. jit_wb_if_flag = 4096
  1707. jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10')
  1708. jit_wb_if_flag_singlebyte = 0x10
  1709. def get_write_barrier_fn(self, cpu):
  1710. return funcbox.getint()
  1711. #
  1712. for cond in [False, True]:
  1713. value = random.randrange(-sys.maxint, sys.maxint)
  1714. if cond:
  1715. value |= 4096
  1716. else:
  1717. value &= ~4096
  1718. s = lltype.malloc(S)
  1719. s.tid = value
  1720. sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
  1721. t = lltype.malloc(S)
  1722. tgcref = lltype.cast_opaque_ptr(llmemory.GCREF, t)
  1723. del record[:]
  1724. self.execute_operation(rop.COND_CALL_GC_WB,
  1725. [BoxPtr(sgcref), ConstPtr(tgcref)],
  1726. 'void', descr=WriteBarrierDescr())
  1727. if cond:
  1728. assert record == [(s, t)]
  1729. else:
  1730. assert record == []
  1731. def test_cond_call_gc_wb_array(self):
  1732. def func_void(a, b, c):
  1733. record.append((a, b, c))
  1734. record = []
  1735. #
  1736. S = lltype.GcStruct('S', ('tid', lltype.Signed))
  1737. FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)],
  1738. lltype.Void)
  1739. func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
  1740. funcbox = self.get_funcbox(self.cpu, func_ptr)
  1741. class WriteBarrierDescr(AbstractDescr):
  1742. jit_wb_if_flag = 4096
  1743. jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10')
  1744. jit_wb_if_flag_singlebyte = 0x10
  1745. jit_wb_cards_set = 0
  1746. def get_write_barrier_from_array_fn(self, cpu):
  1747. return funcbox.getint()
  1748. #
  1749. for cond in [False, True]:
  1750. value = random.randrange(-sys.maxint, sys.maxint)
  1751. if cond:
  1752. value |= 4096
  1753. else:
  1754. value &= ~4096
  1755. s = lltype.malloc(S)
  1756. s.tid = value
  1757. sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
  1758. del record[:]
  1759. self.execute_operation(rop.COND_CALL_GC_WB_ARRAY,
  1760. [BoxPtr(sgcref), ConstInt(123), BoxPtr(sgcref)],
  1761. 'void', descr=WriteBarrierDescr())
  1762. if cond:
  1763. assert record == [(s, 123, s)]
  1764. else:
  1765. assert record == []
  1766. def test_cond_call_gc_wb_array_card_marking_fast_path(self):
  1767. def func_void(a, b, c):
  1768. record.append((a, b, c))
  1769. record = []
  1770. #
  1771. S = lltype.Struct('S', ('tid', lltype.Signed))
  1772. S_WITH_CARDS = lltype.Struct('S_WITH_CARDS',
  1773. ('card0', lltype.Char),
  1774. ('card1', lltype.Char),
  1775. ('card2', lltype.Char),
  1776. ('card3', lltype.Char),
  1777. ('card4', lltype.Char),
  1778. ('card5', lltype.Char),
  1779. ('card6', lltype.Char),
  1780. ('card7', lltype.Char),
  1781. ('data', S))
  1782. FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)],
  1783. lltype.Void)
  1784. func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
  1785. funcbox = self.get_funcbox(self.cpu, func_ptr)
  1786. class WriteBarrierDescr(AbstractDescr):
  1787. jit_wb_if_flag = 4096
  1788. jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10')
  1789. jit_wb_if_flag_singlebyte = 0x10
  1790. jit_wb_cards_set = 8192
  1791. jit_wb_cards_set_byteofs = struct.pack("i", 8192).index('\x20')
  1792. jit_wb_cards_set_singlebyte = 0x20
  1793. jit_wb_card_page_shift = 7
  1794. def get_write_barrier_from_array_fn(self, cpu):
  1795. return funcbox.getint()
  1796. #
  1797. for BoxIndexCls in [BoxInt, ConstInt]:
  1798. for cond in [False, True]:
  1799. print
  1800. print '_'*79
  1801. print 'BoxIndexCls =', BoxIndexCls
  1802. print 'JIT_WB_CARDS_SET =', cond
  1803. print
  1804. value = random.randrange(-sys.maxint, sys.maxint)
  1805. value |= 4096
  1806. if cond:
  1807. value |= 8192
  1808. else:
  1809. value &= ~8192
  1810. s = lltype.malloc(S_WITH_CARDS, immortal=True, zero=True)
  1811. s.data.tid = value
  1812. sgcref = rffi.cast(llmemory.GCREF, s.data)
  1813. del record[:]
  1814. box_index = BoxIndexCls((9<<7) + 17)
  1815. self.execute_operation(rop.COND_CALL_GC_WB_ARRAY,
  1816. [BoxPtr(sgcref), box_index, BoxPtr(sgcref)],
  1817. 'void', descr=WriteBarrierDescr())
  1818. if cond:
  1819. assert record == []
  1820. assert s.card6 == '\x02'
  1821. else:
  1822. assert record == [(s.data, (9<<7) + 17, s.data)]
  1823. assert s.card6 == '\x00'
  1824. assert s.card0 == '\x00'
  1825. assert s.card1 == '\x00'
  1826. assert s.card2 == '\x00'
  1827. assert s.card3 == '\x00'
  1828. assert s.card4 == '\x00'
  1829. assert s.card5 == '\x00'
  1830. assert s.card7 == '\x00'
  1831. def test_force_operations_returning_void(self):
  1832. values = []
  1833. def maybe_force(token, flag):
  1834. if flag:
  1835. descr = self.cpu.force(token)
  1836. values.append(descr)
  1837. values.append(self.cpu.get_latest_value_int(0))
  1838. values.append(self.cpu.get_latest_value_int(1))
  1839. values.append(token)
  1840. FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Void)
  1841. func_ptr = llhelper(lltype.Ptr(FUNC), maybe_force)
  1842. funcbox = self.get_funcbox(self.cpu, func_ptr).constbox()
  1843. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  1844. EffectInfo.MOST_GENERAL)
  1845. cpu = self.cpu
  1846. i0 = BoxInt()
  1847. i1 = BoxInt()
  1848. tok = BoxInt()
  1849. faildescr = BasicFailDescr(1)
  1850. ops = [
  1851. ResOperation(rop.FORCE_TOKEN, [], tok),
  1852. ResOperation(rop.CALL_MAY_FORCE, [funcbox, tok, i1], None,
  1853. descr=calldescr),
  1854. ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
  1855. ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(0))
  1856. ]
  1857. ops[2].setfailargs([i1, i0])
  1858. looptoken = JitCellToken()
  1859. self.cpu.compile_loop([i0, i1], ops, looptoken)
  1860. fail = self.cpu.execute_token(looptoken, 20, 0)
  1861. assert fail.identifier == 0
  1862. assert self.cpu.get_latest_value_int(0) == 20
  1863. assert values == []
  1864. fail = self.cpu.execute_token(looptoken, 10, 1)
  1865. assert fail.identifier == 1
  1866. assert self.cpu.get_latest_value_int(0) == 1
  1867. assert self.cpu.get_latest_value_int(1) == 10
  1868. token = self.cpu.get_latest_force_token()
  1869. assert values == [faildescr, 1, 10, token]
  1870. def test_force_operations_returning_int(self):
  1871. values = []
  1872. def maybe_force(token, flag):
  1873. if flag:
  1874. self.cpu.force(token)
  1875. values.append(self.cpu.get_latest_value_int(0))
  1876. values.append(self.cpu.get_latest_value_int(2))
  1877. values.append(token)
  1878. return 42
  1879. FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
  1880. func_ptr = llhelper(lltype.Ptr(FUNC), maybe_force)
  1881. funcbox = self.get_funcbox(self.cpu, func_ptr).constbox()
  1882. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  1883. EffectInfo.MOST_GENERAL)
  1884. cpu = self.cpu
  1885. i0 = BoxInt()
  1886. i1 = BoxInt()
  1887. i2 = BoxInt()
  1888. tok = BoxInt()
  1889. faildescr = BasicFailDescr(1)
  1890. ops = [
  1891. ResOperation(rop.FORCE_TOKEN, [], tok),
  1892. ResOperation(rop.CALL_MAY_FORCE, [funcbox, tok, i1], i2,
  1893. descr=calldescr),
  1894. ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
  1895. ResOperation(rop.FINISH, [i2], None, descr=BasicFailDescr(0))
  1896. ]
  1897. ops[2].setfailargs([i1, i2, i0])
  1898. looptoken = JitCellToken()
  1899. self.cpu.compile_loop([i0, i1], ops, looptoken)
  1900. fail = self.cpu.execute_token(looptoken, 20, 0)
  1901. assert fail.identifier == 0
  1902. assert self.cpu.get_latest_value_int(0) == 42
  1903. assert values == []
  1904. fail = self.cpu.execute_token(looptoken, 10, 1)
  1905. assert fail.identifier == 1
  1906. assert self.cpu.get_latest_value_int(0) == 1
  1907. assert self.cpu.get_latest_value_int(1) == 42
  1908. assert self.cpu.get_latest_value_int(2) == 10
  1909. token = self.cpu.get_latest_force_token()
  1910. assert values == [1, 10, token]
  1911. def test_force_operations_returning_float(self):
  1912. values = []
  1913. def maybe_force(token, flag):
  1914. if flag:
  1915. self.cpu.force(token)
  1916. values.append(self.cpu.get_latest_value_int(0))
  1917. values.append(self.cpu.get_latest_value_int(2))
  1918. values.append(token)
  1919. return 42.5
  1920. FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Float)
  1921. func_ptr = llhelper(lltype.Ptr(FUNC), maybe_force)
  1922. funcbox = self.get_funcbox(self.cpu, func_ptr).constbox()
  1923. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  1924. EffectInfo.MOST_GENERAL)
  1925. cpu = self.cpu
  1926. i0 = BoxInt()
  1927. i1 = BoxInt()
  1928. f2 = BoxFloat()
  1929. tok = BoxInt()
  1930. faildescr = BasicFailDescr(1)
  1931. ops = [
  1932. ResOperation(rop.FORCE_TOKEN, [], tok),
  1933. ResOperation(rop.CALL_MAY_FORCE, [funcbox, tok, i1], f2,
  1934. descr=calldescr),
  1935. ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
  1936. ResOperation(rop.FINISH, [f2], None, descr=BasicFailDescr(0))
  1937. ]
  1938. ops[2].setfailargs([i1, f2, i0])
  1939. looptoken = JitCellToken()
  1940. self.cpu.compile_loop([i0, i1], ops, looptoken)
  1941. fail = self.cpu.execute_token(looptoken, 20, 0)
  1942. assert fail.identifier == 0
  1943. x = self.cpu.get_latest_value_float(0)
  1944. assert longlong.getrealfloat(x) == 42.5
  1945. assert values == []
  1946. fail = self.cpu.execute_token(looptoken, 10, 1)
  1947. assert fail.identifier == 1
  1948. assert self.cpu.get_latest_value_int(0) == 1
  1949. x = self.cpu.get_latest_value_float(1)
  1950. assert longlong.getrealfloat(x) == 42.5
  1951. assert self.cpu.get_latest_value_int(2) == 10
  1952. token = self.cpu.get_latest_force_token()
  1953. assert values == [1, 10, token]
  1954. def test_call_to_c_function(self):
  1955. from pypy.rlib.libffi import CDLL, types, ArgChain, FUNCFLAG_CDECL
  1956. from pypy.rpython.lltypesystem.ll2ctypes import libc_name
  1957. libc = CDLL(libc_name)
  1958. c_tolower = libc.getpointer('tolower', [types.uchar], types.sint)
  1959. argchain = ArgChain().arg(ord('A'))
  1960. assert c_tolower.call(argchain, rffi.INT) == ord('a')
  1961. cpu = self.cpu
  1962. func_adr = llmemory.cast_ptr_to_adr(c_tolower.funcsym)
  1963. funcbox = ConstInt(heaptracker.adr2int(func_adr))
  1964. calldescr = cpu.calldescrof_dynamic([types.uchar], types.sint,
  1965. EffectInfo.MOST_GENERAL,
  1966. ffi_flags=FUNCFLAG_CDECL)
  1967. i1 = BoxInt()
  1968. i2 = BoxInt()
  1969. tok = BoxInt()
  1970. faildescr = BasicFailDescr(1)
  1971. ops = [
  1972. ResOperation(rop.CALL_RELEASE_GIL, [funcbox, i1], i2,
  1973. descr=calldescr),
  1974. ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
  1975. ResOperation(rop.FINISH, [i2], None, descr=BasicFailDescr(0))
  1976. ]
  1977. ops[1].setfailargs([i1, i2])
  1978. looptoken = JitCellToken()
  1979. self.cpu.compile_loop([i1], ops, looptoken)
  1980. fail = self.cpu.execute_token(looptoken, ord('G'))
  1981. assert fail.identifier == 0
  1982. assert self.cpu.get_latest_value_int(0) == ord('g')
  1983. def test_call_to_c_function_with_callback(self):
  1984. from pypy.rlib.libffi import CDLL, types, ArgChain, clibffi
  1985. from pypy.rpython.lltypesystem.ll2ctypes import libc_name
  1986. libc = CDLL(libc_name)
  1987. types_size_t = clibffi.cast_type_to_ffitype(rffi.SIZE_T)
  1988. c_qsort = libc.getpointer('qsort', [types.pointer, types_size_t,
  1989. types_size_t, types.pointer],
  1990. types.void)
  1991. class Glob(object):
  1992. pass
  1993. glob = Glob()
  1994. class X(object):
  1995. pass
  1996. #
  1997. def callback(p1, p2):
  1998. glob.lst.append(X())
  1999. return rffi.cast(rffi.INT, 1)
  2000. CALLBACK = lltype.Ptr(lltype.FuncType([lltype.Signed,
  2001. lltype.Signed], rffi.INT))
  2002. fn = llhelper(CALLBACK, callback)
  2003. S = lltype.Struct('S', ('x', rffi.INT), ('y', rffi.INT))
  2004. raw = lltype.malloc(S, flavor='raw')
  2005. argchain = ArgChain()
  2006. argchain = argchain.arg(rffi.cast(lltype.Signed, raw))
  2007. argchain = argchain.arg(rffi.cast(rffi.SIZE_T, 2))
  2008. argchain = argchain.arg(rffi.cast(rffi.SIZE_T, 4))
  2009. argchain = argchain.arg(rffi.cast(lltype.Signed, fn))
  2010. glob.lst = []
  2011. c_qsort.call(argchain, lltype.Void)
  2012. assert len(glob.lst) > 0
  2013. del glob.lst[:]
  2014. cpu = self.cpu
  2015. func_adr = llmemory.cast_ptr_to_adr(c_qsort.funcsym)
  2016. funcbox = ConstInt(heaptracker.adr2int(func_adr))
  2017. calldescr = cpu.calldescrof_dynamic([types.pointer, types_size_t,
  2018. types_size_t, types.pointer],
  2019. types.void,
  2020. EffectInfo.MOST_GENERAL,
  2021. ffi_flags=clibffi.FUNCFLAG_CDECL)
  2022. i0 = BoxInt()
  2023. i1 = BoxInt()
  2024. i2 = BoxInt()
  2025. i3 = BoxInt()
  2026. tok = BoxInt()
  2027. faildescr = BasicFailDescr(1)
  2028. ops = [
  2029. ResOperation(rop.CALL_RELEASE_GIL, [funcbox, i0, i1, i2, i3], None,
  2030. descr=calldescr),
  2031. ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
  2032. ResOperation(rop.FINISH, [], None, descr=BasicFailDescr(0))
  2033. ]
  2034. ops[1].setfailargs([])
  2035. looptoken = JitCellToken()
  2036. self.cpu.compile_loop([i0, i1, i2, i3], ops, looptoken)
  2037. args = [rffi.cast(lltype.Signed, raw),
  2038. 2,
  2039. 4,
  2040. rffi.cast(lltype.Signed, fn)]
  2041. assert glob.lst == []
  2042. fail = self.cpu.execute_token(looptoken, *args)
  2043. assert fail.identifier == 0
  2044. assert len(glob.lst) > 0
  2045. lltype.free(raw, flavor='raw')
  2046. def test_call_to_winapi_function(self):
  2047. from pypy.rlib.clibffi import _WIN32, FUNCFLAG_STDCALL
  2048. if not _WIN32:
  2049. py.test.skip("Windows test only")
  2050. from pypy.rlib.libffi import CDLL, types, ArgChain
  2051. from pypy.rlib.rwin32 import DWORD
  2052. libc = CDLL('KERNEL32')
  2053. c_GetCurrentDir = libc.getpointer('GetCurrentDirectoryA',
  2054. [types.ulong, types.pointer],
  2055. types.ulong)
  2056. cwd = os.getcwd()
  2057. buflen = len(cwd) + 10
  2058. buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
  2059. argchain = ArgChain().arg(rffi.cast(DWORD, buflen)).arg(buffer)
  2060. res = c_GetCurrentDir.call(argchain, DWORD)
  2061. assert rffi.cast(lltype.Signed, res) == len(cwd)
  2062. assert rffi.charp2strn(buffer, buflen) == cwd
  2063. lltype.free(buffer, flavor='raw')
  2064. cpu = self.cpu
  2065. func_adr = llmemory.cast_ptr_to_adr(c_GetCurrentDir.funcsym)
  2066. funcbox = ConstInt(heaptracker.adr2int(func_adr))
  2067. calldescr = cpu.calldescrof_dynamic([types.ulong, types.pointer],
  2068. types.ulong,
  2069. EffectInfo.MOST_GENERAL,
  2070. ffi_flags=FUNCFLAG_STDCALL)
  2071. i1 = BoxInt()
  2072. i2 = BoxInt()
  2073. faildescr = BasicFailDescr(1)
  2074. # if the stdcall convention is ignored, then ESP is wrong after the
  2075. # call: 8 bytes too much. If we repeat the call often enough, crash.
  2076. ops = []
  2077. for i in range(50):
  2078. i3 = BoxInt()
  2079. ops += [
  2080. ResOperation(rop.CALL_RELEASE_GIL, [funcbox, i1, i2], i3,
  2081. descr=calldescr),
  2082. ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
  2083. ]
  2084. ops[-1].setfailargs([])
  2085. ops += [
  2086. ResOperation(rop.FINISH, [i3], None, descr=BasicFailDescr(0))
  2087. ]
  2088. looptoken = JitCellToken()
  2089. self.cpu.compile_loop([i1, i2], ops, looptoken)
  2090. buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
  2091. args = [buflen, rffi.cast(lltype.Signed, buffer)]
  2092. fail = self.cpu.execute_token(looptoken, *args)
  2093. assert fail.identifier == 0
  2094. assert self.cpu.get_latest_value_int(0) == len(cwd)
  2095. assert rffi.charp2strn(buffer, buflen) == cwd
  2096. lltype.free(buffer, flavor='raw')
  2097. def test_guard_not_invalidated(self):
  2098. cpu = self.cpu
  2099. i0 = BoxInt()
  2100. i1 = BoxInt()
  2101. faildescr = BasicFailDescr(1)
  2102. ops = [
  2103. ResOperation(rop.GUARD_NOT_INVALIDATED, [], None, descr=faildescr),
  2104. ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(0))
  2105. ]
  2106. ops[0].setfailargs([i1])
  2107. looptoken = JitCellToken()
  2108. self.cpu.compile_loop([i0, i1], ops, looptoken)
  2109. fail = self.cpu.execute_token(looptoken, -42, 9)
  2110. assert fail.identifier == 0
  2111. assert self.cpu.get_latest_value_int(0) == -42
  2112. print 'step 1 ok'
  2113. print '-'*79
  2114. # mark as failing
  2115. self.cpu.invalidate_loop(looptoken)
  2116. fail = self.cpu.execute_token(looptoken, -42, 9)
  2117. assert fail is faildescr
  2118. assert self.cpu.get_latest_value_int(0) == 9
  2119. print 'step 2 ok'
  2120. print '-'*79
  2121. # attach a bridge
  2122. i2 = BoxInt()
  2123. faildescr2 = BasicFailDescr(2)
  2124. ops = [
  2125. ResOperation(rop.GUARD_NOT_INVALIDATED, [],None, descr=faildescr2),
  2126. ResOperation(rop.FINISH, [i2], None, descr=BasicFailDescr(3))
  2127. ]
  2128. ops[0].setfailargs([])
  2129. self.cpu.compile_bridge(faildescr, [i2], ops, looptoken)
  2130. fail = self.cpu.execute_token(looptoken, -42, 9)
  2131. assert fail.identifier == 3
  2132. assert self.cpu.get_latest_value_int(0) == 9
  2133. print 'step 3 ok'
  2134. print '-'*79
  2135. # mark as failing again
  2136. self.cpu.invalidate_loop(looptoken)
  2137. fail = self.cpu.execute_token(looptoken, -42, 9)
  2138. assert fail is faildescr2
  2139. print 'step 4 ok'
  2140. print '-'*79
  2141. def test_guard_not_invalidated_and_label(self):
  2142. # test that the guard_not_invalidated reserves enough room before
  2143. # the label. If it doesn't, then in this example after we invalidate
  2144. # the guard, jumping to the label will hit the invalidation code too
  2145. cpu = self.cpu
  2146. i0 = BoxInt()
  2147. faildescr = BasicFailDescr(1)
  2148. labeldescr = TargetToken()
  2149. ops = [
  2150. ResOperation(rop.GUARD_NOT_INVALIDATED, [], None, descr=faildescr),
  2151. ResOperation(rop.LABEL, [i0], None, descr=labeldescr),
  2152. ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(3)),
  2153. ]
  2154. ops[0].setfailargs([])
  2155. looptoken = JitCellToken()
  2156. self.cpu.compile_loop([i0], ops, looptoken)
  2157. # mark as failing
  2158. self.cpu.invalidate_loop(looptoken)
  2159. # attach a bridge
  2160. i2 = BoxInt()
  2161. ops = [
  2162. ResOperation(rop.JUMP, [ConstInt(333)], None, descr=labeldescr),
  2163. ]
  2164. self.cpu.compile_bridge(faildescr, [], ops, looptoken)
  2165. # run: must not be caught in an infinite loop
  2166. fail = self.cpu.execute_token(looptoken, 16)
  2167. assert fail.identifier == 3
  2168. assert self.cpu.get_latest_value_int(0) == 333
  2169. # pure do_ / descr features
  2170. def test_do_operations(self):
  2171. cpu = self.cpu
  2172. #
  2173. A = lltype.GcArray(lltype.Char)
  2174. descr_A = cpu.arraydescrof(A)
  2175. a = lltype.malloc(A, 5)
  2176. x = cpu.bh_arraylen_gc(descr_A,
  2177. lltype.cast_opaque_ptr(llmemory.GCREF, a))
  2178. assert x == 5
  2179. #
  2180. a[2] = 'Y'
  2181. x = cpu.bh_getarrayitem_gc_i(
  2182. descr_A, lltype.cast_opaque_ptr(llmemory.GCREF, a), 2)
  2183. assert x == ord('Y')
  2184. #
  2185. B = lltype.GcArray(lltype.Ptr(A))
  2186. descr_B = cpu.arraydescrof(B)
  2187. b = lltype.malloc(B, 4)
  2188. b[3] = a
  2189. x = cpu.bh_getarrayitem_gc_r(
  2190. descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 3)
  2191. assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a
  2192. if self.cpu.supports_floats:
  2193. C = lltype.GcArray(lltype.Float)
  2194. c = lltype.malloc(C, 6)
  2195. c[3] = 3.5
  2196. descr_C = cpu.arraydescrof(C)
  2197. x = cpu.bh_getarrayitem_gc_f(
  2198. descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 3)
  2199. assert longlong.getrealfloat(x) == 3.5
  2200. cpu.bh_setarrayitem_gc_f(
  2201. descr_C, lltype.cast_opaque_ptr(llmemory.GCREF, c), 4,
  2202. longlong.getfloatstorage(4.5))
  2203. assert c[4] == 4.5
  2204. s = rstr.mallocstr(6)
  2205. x = cpu.bh_strlen(lltype.cast_opaque_ptr(llmemory.GCREF, s))
  2206. assert x == 6
  2207. #
  2208. s.chars[3] = 'X'
  2209. x = cpu.bh_strgetitem(lltype.cast_opaque_ptr(llmemory.GCREF, s), 3)
  2210. assert x == ord('X')
  2211. #
  2212. S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A)),
  2213. ('z', lltype.Float))
  2214. descrfld_x = cpu.fielddescrof(S, 'x')
  2215. s = lltype.malloc(S)
  2216. s.x = 'Z'
  2217. x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2218. descrfld_x)
  2219. assert x == ord('Z')
  2220. #
  2221. cpu.bh_setfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2222. descrfld_x,
  2223. ord('4'))
  2224. assert s.x == '4'
  2225. #
  2226. descrfld_y = cpu.fielddescrof(S, 'y')
  2227. s.y = a
  2228. x = cpu.bh_getfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2229. descrfld_y)
  2230. assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a
  2231. #
  2232. s.y = lltype.nullptr(A)
  2233. cpu.bh_setfield_gc_r(lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2234. descrfld_y, x)
  2235. assert s.y == a
  2236. #
  2237. RS = lltype.Struct('S', ('x', lltype.Char)) #, ('y', lltype.Ptr(A)))
  2238. descrfld_rx = cpu.fielddescrof(RS, 'x')
  2239. rs = lltype.malloc(RS, immortal=True)
  2240. rs.x = '?'
  2241. x = cpu.bh_getfield_raw_i(
  2242. heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)),
  2243. descrfld_rx)
  2244. assert x == ord('?')
  2245. #
  2246. cpu.bh_setfield_raw_i(
  2247. heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)),
  2248. descrfld_rx, ord('!'))
  2249. assert rs.x == '!'
  2250. #
  2251. if self.cpu.supports_floats:
  2252. descrfld_z = cpu.fielddescrof(S, 'z')
  2253. cpu.bh_setfield_gc_f(
  2254. lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2255. descrfld_z, longlong.getfloatstorage(3.5))
  2256. assert s.z == 3.5
  2257. s.z = 3.2
  2258. x = cpu.bh_getfield_gc_f(
  2259. lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2260. descrfld_z)
  2261. assert longlong.getrealfloat(x) == 3.2
  2262. ### we don't support in the JIT for now GC pointers
  2263. ### stored inside non-GC structs.
  2264. #descrfld_ry = cpu.fielddescrof(RS, 'y')
  2265. #rs.y = a
  2266. #x = cpu.do_getfield_raw(
  2267. # BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))),
  2268. # descrfld_ry)
  2269. #assert isinstance(x, BoxPtr)
  2270. #assert x.getref(lltype.Ptr(A)) == a
  2271. #
  2272. #rs.y = lltype.nullptr(A)
  2273. #cpu.do_setfield_raw(
  2274. # BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), x,
  2275. # descrfld_ry)
  2276. #assert rs.y == a
  2277. #
  2278. descrsize = cpu.sizeof(S)
  2279. x = cpu.bh_new(descrsize)
  2280. lltype.cast_opaque_ptr(lltype.Ptr(S), x) # type check
  2281. #
  2282. descrsize2 = cpu.sizeof(rclass.OBJECT)
  2283. vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
  2284. vtable2_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable2))
  2285. heaptracker.register_known_gctype(cpu, vtable2, rclass.OBJECT)
  2286. x = cpu.bh_new_with_vtable(descrsize2, vtable2_int)
  2287. lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), x) # type check
  2288. # well...
  2289. #assert x.getref(rclass.OBJECTPTR).typeptr == vtable2
  2290. #
  2291. arraydescr = cpu.arraydescrof(A)
  2292. x = cpu.bh_new_array(arraydescr, 7)
  2293. array = lltype.cast_opaque_ptr(lltype.Ptr(A), x)
  2294. assert len(array) == 7
  2295. #
  2296. cpu.bh_setarrayitem_gc_i(descr_A, x, 5, ord('*'))
  2297. assert array[5] == '*'
  2298. #
  2299. cpu.bh_setarrayitem_gc_r(
  2300. descr_B, lltype.cast_opaque_ptr(llmemory.GCREF, b), 1, x)
  2301. assert b[1] == array
  2302. #
  2303. x = cpu.bh_newstr(5)
  2304. str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), x)
  2305. assert len(str.chars) == 5
  2306. #
  2307. cpu.bh_strsetitem(x, 4, ord('/'))
  2308. assert str.chars[4] == '/'
  2309. def test_sorting_of_fields(self):
  2310. S = self.S
  2311. value = self.cpu.fielddescrof(S, 'value').sort_key()
  2312. chr1 = self.cpu.fielddescrof(S, 'chr1').sort_key()
  2313. chr2 = self.cpu.fielddescrof(S, 'chr2').sort_key()
  2314. assert (sorted([chr2, chr1, value]) ==
  2315. [value, chr1, chr2])
  2316. assert len(dict.fromkeys([value, chr1, chr2]).keys()) == 3
  2317. def test_guards_nongc(self):
  2318. x = lltype.malloc(lltype.Struct('x'), flavor='raw')
  2319. v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x))
  2320. vbox = BoxInt(v)
  2321. ops = [
  2322. (rop.GUARD_NONNULL, vbox, False),
  2323. (rop.GUARD_ISNULL, vbox, True),
  2324. (rop.GUARD_NONNULL, BoxInt(0), True),
  2325. (rop.GUARD_ISNULL, BoxInt(0), False),
  2326. ]
  2327. for opname, arg, res in ops:
  2328. self.execute_operation(opname, [arg], 'void')
  2329. assert self.guard_failed == res
  2330. lltype.free(x, flavor='raw')
  2331. def test_assembler_call(self):
  2332. called = []
  2333. def assembler_helper(failindex, virtualizable):
  2334. assert self.cpu.get_latest_value_int(0) == 97
  2335. called.append(failindex)
  2336. return 4 + 9
  2337. FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
  2338. lltype.Signed))
  2339. class FakeJitDriverSD:
  2340. index_of_virtualizable = -1
  2341. _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
  2342. assembler_helper_adr = llmemory.cast_ptr_to_adr(
  2343. _assembler_helper_ptr)
  2344. ops = '''
  2345. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  2346. i10 = int_add(i0, i1)
  2347. i11 = int_add(i10, i2)
  2348. i12 = int_add(i11, i3)
  2349. i13 = int_add(i12, i4)
  2350. i14 = int_add(i13, i5)
  2351. i15 = int_add(i14, i6)
  2352. i16 = int_add(i15, i7)
  2353. i17 = int_add(i16, i8)
  2354. i18 = int_add(i17, i9)
  2355. finish(i18)'''
  2356. loop = parse(ops)
  2357. looptoken = JitCellToken()
  2358. looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
  2359. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  2360. ARGS = [lltype.Signed] * 10
  2361. RES = lltype.Signed
  2362. FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
  2363. lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
  2364. EffectInfo.MOST_GENERAL)
  2365. args = [i+1 for i in range(10)]
  2366. res = self.cpu.execute_token(looptoken, *args)
  2367. assert self.cpu.get_latest_value_int(0) == 55
  2368. ops = '''
  2369. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  2370. i10 = int_add(i0, 42)
  2371. i11 = call_assembler(i10, i1, i2, i3, i4, i5, i6, i7, i8, i9, descr=looptoken)
  2372. guard_not_forced()[]
  2373. finish(i11)
  2374. '''
  2375. loop = parse(ops, namespace=locals())
  2376. othertoken = JitCellToken()
  2377. self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
  2378. args = [i+1 for i in range(10)]
  2379. res = self.cpu.execute_token(othertoken, *args)
  2380. assert self.cpu.get_latest_value_int(0) == 13
  2381. assert called
  2382. def test_assembler_call_float(self):
  2383. called = []
  2384. def assembler_helper(failindex, virtualizable):
  2385. x = self.cpu.get_latest_value_float(0)
  2386. assert longlong.getrealfloat(x) == 1.2 + 3.2
  2387. called.append(failindex)
  2388. return 13.5
  2389. FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
  2390. lltype.Float))
  2391. class FakeJitDriverSD:
  2392. index_of_virtualizable = -1
  2393. _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
  2394. assembler_helper_adr = llmemory.cast_ptr_to_adr(
  2395. _assembler_helper_ptr)
  2396. ARGS = [lltype.Float, lltype.Float]
  2397. RES = lltype.Float
  2398. FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
  2399. lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
  2400. EffectInfo.MOST_GENERAL)
  2401. ops = '''
  2402. [f0, f1]
  2403. f2 = float_add(f0, f1)
  2404. finish(f2)'''
  2405. loop = parse(ops)
  2406. done_number = self.cpu.get_fail_descr_number(loop.operations[-1].getdescr())
  2407. looptoken = JitCellToken()
  2408. looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
  2409. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  2410. args = [longlong.getfloatstorage(1.2),
  2411. longlong.getfloatstorage(2.3)]
  2412. res = self.cpu.execute_token(looptoken, *args)
  2413. x = self.cpu.get_latest_value_float(0)
  2414. assert longlong.getrealfloat(x) == 1.2 + 2.3
  2415. ops = '''
  2416. [f4, f5]
  2417. f3 = call_assembler(f4, f5, descr=looptoken)
  2418. guard_not_forced()[]
  2419. finish(f3)
  2420. '''
  2421. loop = parse(ops, namespace=locals())
  2422. othertoken = JitCellToken()
  2423. self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
  2424. args = [longlong.getfloatstorage(1.2),
  2425. longlong.getfloatstorage(3.2)]
  2426. res = self.cpu.execute_token(othertoken, *args)
  2427. x = self.cpu.get_latest_value_float(0)
  2428. assert longlong.getrealfloat(x) == 13.5
  2429. assert called
  2430. # test the fast path, which should not call assembler_helper()
  2431. del called[:]
  2432. self.cpu.done_with_this_frame_float_v = done_number
  2433. try:
  2434. othertoken = JitCellToken()
  2435. self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
  2436. args = [longlong.getfloatstorage(1.2),
  2437. longlong.getfloatstorage(3.2)]
  2438. res = self.cpu.execute_token(othertoken, *args)
  2439. x = self.cpu.get_latest_value_float(0)
  2440. assert longlong.getrealfloat(x) == 1.2 + 3.2
  2441. assert not called
  2442. finally:
  2443. del self.cpu.done_with_this_frame_float_v
  2444. def test_raw_malloced_getarrayitem(self):
  2445. ARRAY = rffi.CArray(lltype.Signed)
  2446. descr = self.cpu.arraydescrof(ARRAY)
  2447. a = lltype.malloc(ARRAY, 10, flavor='raw')
  2448. a[7] = -4242
  2449. addr = llmemory.cast_ptr_to_adr(a)
  2450. abox = BoxInt(heaptracker.adr2int(addr))
  2451. r1 = self.execute_operation(rop.GETARRAYITEM_RAW, [abox, BoxInt(7)],
  2452. 'int', descr=descr)
  2453. assert r1.getint() == -4242
  2454. lltype.free(a, flavor='raw')
  2455. def test_raw_malloced_setarrayitem(self):
  2456. ARRAY = rffi.CArray(lltype.Signed)
  2457. descr = self.cpu.arraydescrof(ARRAY)
  2458. a = lltype.malloc(ARRAY, 10, flavor='raw')
  2459. addr = llmemory.cast_ptr_to_adr(a)
  2460. abox = BoxInt(heaptracker.adr2int(addr))
  2461. self.execute_operation(rop.SETARRAYITEM_RAW, [abox, BoxInt(5),
  2462. BoxInt(12345)],
  2463. 'void', descr=descr)
  2464. assert a[5] == 12345
  2465. lltype.free(a, flavor='raw')
  2466. def test_redirect_call_assembler(self):
  2467. called = []
  2468. def assembler_helper(failindex, virtualizable):
  2469. x = self.cpu.get_latest_value_float(0)
  2470. assert longlong.getrealfloat(x) == 1.25 + 3.25
  2471. called.append(failindex)
  2472. return 13.5
  2473. FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
  2474. lltype.Float))
  2475. class FakeJitDriverSD:
  2476. index_of_virtualizable = -1
  2477. _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
  2478. assembler_helper_adr = llmemory.cast_ptr_to_adr(
  2479. _assembler_helper_ptr)
  2480. ARGS = [lltype.Float, lltype.Float]
  2481. RES = lltype.Float
  2482. FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
  2483. lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
  2484. EffectInfo.MOST_GENERAL)
  2485. ops = '''
  2486. [f0, f1]
  2487. f2 = float_add(f0, f1)
  2488. finish(f2)'''
  2489. loop = parse(ops)
  2490. looptoken = JitCellToken()
  2491. looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
  2492. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  2493. args = [longlong.getfloatstorage(1.25),
  2494. longlong.getfloatstorage(2.35)]
  2495. res = self.cpu.execute_token(looptoken, *args)
  2496. x = self.cpu.get_latest_value_float(0)
  2497. assert longlong.getrealfloat(x) == 1.25 + 2.35
  2498. assert not called
  2499. ops = '''
  2500. [f4, f5]
  2501. f3 = call_assembler(f4, f5, descr=looptoken)
  2502. guard_not_forced()[]
  2503. finish(f3)
  2504. '''
  2505. loop = parse(ops, namespace=locals())
  2506. othertoken = JitCellToken()
  2507. self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
  2508. # normal call_assembler: goes to looptoken
  2509. args = [longlong.getfloatstorage(1.25),
  2510. longlong.getfloatstorage(3.25)]
  2511. res = self.cpu.execute_token(othertoken, *args)
  2512. x = self.cpu.get_latest_value_float(0)
  2513. assert longlong.getrealfloat(x) == 13.5
  2514. assert called
  2515. del called[:]
  2516. # compile a replacement
  2517. ops = '''
  2518. [f0, f1]
  2519. f2 = float_sub(f0, f1)
  2520. finish(f2)'''
  2521. loop = parse(ops)
  2522. looptoken2 = JitCellToken()
  2523. looptoken2.outermost_jitdriver_sd = FakeJitDriverSD()
  2524. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken2)
  2525. # install it
  2526. self.cpu.redirect_call_assembler(looptoken, looptoken2)
  2527. # now, our call_assembler should go to looptoken2
  2528. args = [longlong.getfloatstorage(6.0),
  2529. longlong.getfloatstorage(1.5)] # 6.0-1.5 == 1.25+3.25
  2530. res = self.cpu.execute_token(othertoken, *args)
  2531. x = self.cpu.get_latest_value_float(0)
  2532. assert longlong.getrealfloat(x) == 13.5
  2533. assert called
  2534. def test_short_result_of_getfield_direct(self):
  2535. # Test that a getfield that returns a CHAR, SHORT or INT, signed
  2536. # or unsigned, properly gets zero-extended or sign-extended.
  2537. # Direct bh_xxx test.
  2538. cpu = self.cpu
  2539. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2540. rffi.SHORT, rffi.USHORT,
  2541. rffi.INT, rffi.UINT,
  2542. rffi.LONG, rffi.ULONG]:
  2543. S = lltype.GcStruct('S', ('x', RESTYPE))
  2544. descrfld_x = cpu.fielddescrof(S, 'x')
  2545. s = lltype.malloc(S)
  2546. value = intmask(0xFFEEDDCCBBAA9988)
  2547. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
  2548. s.x = rffi.cast(RESTYPE, value)
  2549. x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s),
  2550. descrfld_x)
  2551. assert x == expected, (
  2552. "%r: got %r, expected %r" % (RESTYPE, x, expected))
  2553. def test_short_result_of_getfield_compiled(self):
  2554. # Test that a getfield that returns a CHAR, SHORT or INT, signed
  2555. # or unsigned, properly gets zero-extended or sign-extended.
  2556. # Machine code compilation test.
  2557. cpu = self.cpu
  2558. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2559. rffi.SHORT, rffi.USHORT,
  2560. rffi.INT, rffi.UINT,
  2561. rffi.LONG, rffi.ULONG]:
  2562. S = lltype.GcStruct('S', ('x', RESTYPE))
  2563. descrfld_x = cpu.fielddescrof(S, 'x')
  2564. s = lltype.malloc(S)
  2565. value = intmask(0xFFEEDDCCBBAA9988)
  2566. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
  2567. s.x = rffi.cast(RESTYPE, value)
  2568. s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
  2569. res = self.execute_operation(rop.GETFIELD_GC, [BoxPtr(s_gcref)],
  2570. 'int', descr=descrfld_x)
  2571. assert res.value == expected, (
  2572. "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
  2573. def test_short_result_of_getarrayitem_direct(self):
  2574. # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
  2575. # or unsigned, properly gets zero-extended or sign-extended.
  2576. # Direct bh_xxx test.
  2577. cpu = self.cpu
  2578. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2579. rffi.SHORT, rffi.USHORT,
  2580. rffi.INT, rffi.UINT,
  2581. rffi.LONG, rffi.ULONG]:
  2582. A = lltype.GcArray(RESTYPE)
  2583. descrarray = cpu.arraydescrof(A)
  2584. a = lltype.malloc(A, 5)
  2585. value = intmask(0xFFEEDDCCBBAA9988)
  2586. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
  2587. a[3] = rffi.cast(RESTYPE, value)
  2588. x = cpu.bh_getarrayitem_gc_i(
  2589. descrarray, lltype.cast_opaque_ptr(llmemory.GCREF, a), 3)
  2590. assert x == expected, (
  2591. "%r: got %r, expected %r" % (RESTYPE, x, expected))
  2592. def test_short_result_of_getarrayitem_compiled(self):
  2593. # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
  2594. # or unsigned, properly gets zero-extended or sign-extended.
  2595. # Machine code compilation test.
  2596. cpu = self.cpu
  2597. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2598. rffi.SHORT, rffi.USHORT,
  2599. rffi.INT, rffi.UINT,
  2600. rffi.LONG, rffi.ULONG]:
  2601. A = lltype.GcArray(RESTYPE)
  2602. descrarray = cpu.arraydescrof(A)
  2603. a = lltype.malloc(A, 5)
  2604. value = intmask(0xFFEEDDCCBBAA9988)
  2605. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
  2606. a[3] = rffi.cast(RESTYPE, value)
  2607. a_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, a)
  2608. res = self.execute_operation(rop.GETARRAYITEM_GC,
  2609. [BoxPtr(a_gcref), BoxInt(3)],
  2610. 'int', descr=descrarray)
  2611. assert res.value == expected, (
  2612. "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
  2613. def test_short_result_of_getarrayitem_raw_direct(self):
  2614. # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
  2615. # or unsigned, properly gets zero-extended or sign-extended.
  2616. # Direct bh_xxx test.
  2617. cpu = self.cpu
  2618. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2619. rffi.SHORT, rffi.USHORT,
  2620. rffi.INT, rffi.UINT,
  2621. rffi.LONG, rffi.ULONG]:
  2622. A = rffi.CArray(RESTYPE)
  2623. descrarray = cpu.arraydescrof(A)
  2624. a = lltype.malloc(A, 5, flavor='raw')
  2625. value = intmask(0xFFEEDDCCBBAA9988)
  2626. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
  2627. a[3] = rffi.cast(RESTYPE, value)
  2628. a_rawint = heaptracker.adr2int(llmemory.cast_ptr_to_adr(a))
  2629. x = cpu.bh_getarrayitem_raw_i(descrarray, a_rawint, 3)
  2630. assert x == expected, (
  2631. "%r: got %r, expected %r" % (RESTYPE, x, expected))
  2632. lltype.free(a, flavor='raw')
  2633. def test_short_result_of_getarrayitem_raw_compiled(self):
  2634. # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
  2635. # or unsigned, properly gets zero-extended or sign-extended.
  2636. # Machine code compilation test.
  2637. cpu = self.cpu
  2638. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2639. rffi.SHORT, rffi.USHORT,
  2640. rffi.INT, rffi.UINT,
  2641. rffi.LONG, rffi.ULONG]:
  2642. A = rffi.CArray(RESTYPE)
  2643. descrarray = cpu.arraydescrof(A)
  2644. a = lltype.malloc(A, 5, flavor='raw')
  2645. value = intmask(0xFFEEDDCCBBAA9988)
  2646. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
  2647. a[3] = rffi.cast(RESTYPE, value)
  2648. a_rawint = heaptracker.adr2int(llmemory.cast_ptr_to_adr(a))
  2649. res = self.execute_operation(rop.GETARRAYITEM_RAW,
  2650. [BoxInt(a_rawint), BoxInt(3)],
  2651. 'int', descr=descrarray)
  2652. assert res.value == expected, (
  2653. "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
  2654. lltype.free(a, flavor='raw')
  2655. def test_short_result_of_call_direct(self):
  2656. # Test that calling a function that returns a CHAR, SHORT or INT,
  2657. # signed or unsigned, properly gets zero-extended or sign-extended.
  2658. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  2659. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2660. rffi.SHORT, rffi.USHORT,
  2661. rffi.INT, rffi.UINT,
  2662. rffi.LONG, rffi.ULONG]:
  2663. # Tested with a function that intentionally does not cast the
  2664. # result to RESTYPE, but makes sure that we return the whole
  2665. # value in eax or rax.
  2666. eci = ExternalCompilationInfo(
  2667. separate_module_sources=["""
  2668. long fn_test_result_of_call(long x)
  2669. {
  2670. return x + 1;
  2671. }
  2672. """],
  2673. export_symbols=['fn_test_result_of_call'])
  2674. f = rffi.llexternal('fn_test_result_of_call', [lltype.Signed],
  2675. RESTYPE, compilation_info=eci, _nowrapper=True)
  2676. value = intmask(0xFFEEDDCCBBAA9988)
  2677. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value + 1))
  2678. assert intmask(f(value)) == expected
  2679. #
  2680. FUNC = self.FuncType([lltype.Signed], RESTYPE)
  2681. FPTR = self.Ptr(FUNC)
  2682. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  2683. EffectInfo.MOST_GENERAL)
  2684. x = self.cpu.bh_call_i(self.get_funcbox(self.cpu, f).value,
  2685. calldescr, [value], None, None)
  2686. assert x == expected, (
  2687. "%r: got %r, expected %r" % (RESTYPE, x, expected))
  2688. def test_short_result_of_call_compiled(self):
  2689. # Test that calling a function that returns a CHAR, SHORT or INT,
  2690. # signed or unsigned, properly gets zero-extended or sign-extended.
  2691. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  2692. for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
  2693. rffi.SHORT, rffi.USHORT,
  2694. rffi.INT, rffi.UINT,
  2695. rffi.LONG, rffi.ULONG]:
  2696. # Tested with a function that intentionally does not cast the
  2697. # result to RESTYPE, but makes sure that we return the whole
  2698. # value in eax or rax.
  2699. eci = ExternalCompilationInfo(
  2700. separate_module_sources=["""
  2701. long fn_test_result_of_call(long x)
  2702. {
  2703. return x + 1;
  2704. }
  2705. """],
  2706. export_symbols=['fn_test_result_of_call'])
  2707. f = rffi.llexternal('fn_test_result_of_call', [lltype.Signed],
  2708. RESTYPE, compilation_info=eci, _nowrapper=True)
  2709. value = intmask(0xFFEEDDCCBBAA9988)
  2710. expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value + 1))
  2711. assert intmask(f(value)) == expected
  2712. #
  2713. FUNC = self.FuncType([lltype.Signed], RESTYPE)
  2714. FPTR = self.Ptr(FUNC)
  2715. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  2716. EffectInfo.MOST_GENERAL)
  2717. funcbox = self.get_funcbox(self.cpu, f)
  2718. res = self.execute_operation(rop.CALL, [funcbox, BoxInt(value)],
  2719. 'int', descr=calldescr)
  2720. assert res.value == expected, (
  2721. "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
  2722. def test_supports_longlong(self):
  2723. if sys.maxint > 2147483647:
  2724. assert not self.cpu.supports_longlong, (
  2725. "supports_longlong should be False on 64-bit platforms")
  2726. def test_longlong_result_of_call_direct(self):
  2727. if not self.cpu.supports_longlong:
  2728. py.test.skip("longlong test")
  2729. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  2730. from pypy.rlib.rarithmetic import r_longlong
  2731. eci = ExternalCompilationInfo(
  2732. separate_module_sources=["""
  2733. long long fn_test_result_of_call(long long x)
  2734. {
  2735. return x - 100000000000000;
  2736. }
  2737. """],
  2738. export_symbols=['fn_test_result_of_call'])
  2739. f = rffi.llexternal('fn_test_result_of_call', [lltype.SignedLongLong],
  2740. lltype.SignedLongLong,
  2741. compilation_info=eci, _nowrapper=True)
  2742. value = r_longlong(0x7ff05af3307a3fff)
  2743. expected = r_longlong(0x7ff000001fffffff)
  2744. assert f(value) == expected
  2745. #
  2746. FUNC = self.FuncType([lltype.SignedLongLong], lltype.SignedLongLong)
  2747. FPTR = self.Ptr(FUNC)
  2748. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  2749. EffectInfo.MOST_GENERAL)
  2750. x = self.cpu.bh_call_f(self.get_funcbox(self.cpu, f).value,
  2751. calldescr, None, None, [value])
  2752. assert x == expected
  2753. def test_longlong_result_of_call_compiled(self):
  2754. if not self.cpu.supports_longlong:
  2755. py.test.skip("test of longlong result")
  2756. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  2757. from pypy.rlib.rarithmetic import r_longlong
  2758. eci = ExternalCompilationInfo(
  2759. separate_module_sources=["""
  2760. long long fn_test_result_of_call(long long x)
  2761. {
  2762. return x - 100000000000000;
  2763. }
  2764. """],
  2765. export_symbols=['fn_test_result_of_call'])
  2766. f = rffi.llexternal('fn_test_result_of_call', [lltype.SignedLongLong],
  2767. lltype.SignedLongLong,
  2768. compilation_info=eci, _nowrapper=True)
  2769. value = r_longlong(0x7ff05af3307a3fff)
  2770. expected = r_longlong(0x7ff000001fffffff)
  2771. assert f(value) == expected
  2772. #
  2773. FUNC = self.FuncType([lltype.SignedLongLong], lltype.SignedLongLong)
  2774. FPTR = self.Ptr(FUNC)
  2775. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  2776. EffectInfo.MOST_GENERAL)
  2777. funcbox = self.get_funcbox(self.cpu, f)
  2778. res = self.execute_operation(rop.CALL, [funcbox, BoxFloat(value)],
  2779. 'float', descr=calldescr)
  2780. assert res.getfloatstorage() == expected
  2781. def test_singlefloat_result_of_call_direct(self):
  2782. if not self.cpu.supports_singlefloats:
  2783. py.test.skip("singlefloat test")
  2784. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  2785. from pypy.rlib.rarithmetic import r_singlefloat
  2786. eci = ExternalCompilationInfo(
  2787. separate_module_sources=["""
  2788. float fn_test_result_of_call(float x)
  2789. {
  2790. return x / 2.0f;
  2791. }
  2792. """],
  2793. export_symbols=['fn_test_result_of_call'])
  2794. f = rffi.llexternal('fn_test_result_of_call', [lltype.SingleFloat],
  2795. lltype.SingleFloat,
  2796. compilation_info=eci, _nowrapper=True)
  2797. value = r_singlefloat(-42.5)
  2798. expected = r_singlefloat(-21.25)
  2799. assert f(value) == expected
  2800. #
  2801. FUNC = self.FuncType([lltype.SingleFloat], lltype.SingleFloat)
  2802. FPTR = self.Ptr(FUNC)
  2803. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  2804. EffectInfo.MOST_GENERAL)
  2805. ivalue = longlong.singlefloat2int(value)
  2806. iexpected = longlong.singlefloat2int(expected)
  2807. x = self.cpu.bh_call_i(self.get_funcbox(self.cpu, f).value,
  2808. calldescr, [ivalue], None, None)
  2809. assert x == iexpected
  2810. def test_singlefloat_result_of_call_compiled(self):
  2811. if not self.cpu.supports_singlefloats:
  2812. py.test.skip("test of singlefloat result")
  2813. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  2814. from pypy.rlib.rarithmetic import r_singlefloat
  2815. eci = ExternalCompilationInfo(
  2816. separate_module_sources=["""
  2817. float fn_test_result_of_call(float x)
  2818. {
  2819. return x / 2.0f;
  2820. }
  2821. """],
  2822. export_symbols=['fn_test_result_of_call'])
  2823. f = rffi.llexternal('fn_test_result_of_call', [lltype.SingleFloat],
  2824. lltype.SingleFloat,
  2825. compilation_info=eci, _nowrapper=True)
  2826. value = r_singlefloat(-42.5)
  2827. expected = r_singlefloat(-21.25)
  2828. assert f(value) == expected
  2829. #
  2830. FUNC = self.FuncType([lltype.SingleFloat], lltype.SingleFloat)
  2831. FPTR = self.Ptr(FUNC)
  2832. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  2833. EffectInfo.MOST_GENERAL)
  2834. funcbox = self.get_funcbox(self.cpu, f)
  2835. ivalue = longlong.singlefloat2int(value)
  2836. iexpected = longlong.singlefloat2int(expected)
  2837. res = self.execute_operation(rop.CALL, [funcbox, BoxInt(ivalue)],
  2838. 'int', descr=calldescr)
  2839. assert res.value == iexpected
  2840. def test_free_loop_and_bridges(self):
  2841. from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
  2842. if not isinstance(self.cpu, AbstractLLCPU):
  2843. py.test.skip("not a subclass of llmodel.AbstractLLCPU")
  2844. if hasattr(self.cpu, 'setup_once'):
  2845. self.cpu.setup_once()
  2846. mem0 = self.cpu.asmmemmgr.total_mallocs
  2847. looptoken = self.test_compile_bridge()
  2848. mem1 = self.cpu.asmmemmgr.total_mallocs
  2849. self.cpu.free_loop_and_bridges(looptoken.compiled_loop_token)
  2850. mem2 = self.cpu.asmmemmgr.total_mallocs
  2851. assert mem2 < mem1
  2852. assert mem2 == mem0
  2853. def test_memoryerror(self):
  2854. excdescr = BasicFailDescr(666)
  2855. self.cpu.propagate_exception_v = self.cpu.get_fail_descr_number(
  2856. excdescr)
  2857. self.cpu.setup_once() # xxx redo it, because we added
  2858. # propagate_exception_v
  2859. i0 = BoxInt()
  2860. p0 = BoxPtr()
  2861. operations = [
  2862. ResOperation(rop.NEWUNICODE, [i0], p0),
  2863. ResOperation(rop.FINISH, [p0], None, descr=BasicFailDescr(1))
  2864. ]
  2865. inputargs = [i0]
  2866. looptoken = JitCellToken()
  2867. self.cpu.compile_loop(inputargs, operations, looptoken)
  2868. # overflowing value:
  2869. fail = self.cpu.execute_token(looptoken, sys.maxint // 4 + 1)
  2870. assert fail.identifier == excdescr.identifier
  2871. exc = self.cpu.grab_exc_value()
  2872. assert exc == "memoryerror!"
  2873. def test_compile_loop_with_target(self):
  2874. i0 = BoxInt()
  2875. i1 = BoxInt()
  2876. i2 = BoxInt()
  2877. i3 = BoxInt()
  2878. looptoken = JitCellToken()
  2879. targettoken1 = TargetToken()
  2880. targettoken2 = TargetToken()
  2881. faildescr = BasicFailDescr(2)
  2882. operations = [
  2883. ResOperation(rop.LABEL, [i0], None, descr=targettoken1),
  2884. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  2885. ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
  2886. ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr),
  2887. ResOperation(rop.LABEL, [i1], None, descr=targettoken2),
  2888. ResOperation(rop.INT_GE, [i1, ConstInt(0)], i3),
  2889. ResOperation(rop.GUARD_TRUE, [i3], None, descr=BasicFailDescr(3)),
  2890. ResOperation(rop.JUMP, [i1], None, descr=targettoken1),
  2891. ]
  2892. inputargs = [i0]
  2893. operations[3].setfailargs([i1])
  2894. operations[6].setfailargs([i1])
  2895. self.cpu.compile_loop(inputargs, operations, looptoken)
  2896. fail = self.cpu.execute_token(looptoken, 2)
  2897. assert fail.identifier == 2
  2898. res = self.cpu.get_latest_value_int(0)
  2899. assert res == 10
  2900. inputargs = [i0]
  2901. operations = [
  2902. ResOperation(rop.INT_SUB, [i0, ConstInt(20)], i2),
  2903. ResOperation(rop.JUMP, [i2], None, descr=targettoken2),
  2904. ]
  2905. self.cpu.compile_bridge(faildescr, inputargs, operations, looptoken)
  2906. fail = self.cpu.execute_token(looptoken, 2)
  2907. assert fail.identifier == 3
  2908. res = self.cpu.get_latest_value_int(0)
  2909. assert res == -10
  2910. def test_compile_asmlen(self):
  2911. from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
  2912. if not isinstance(self.cpu, AbstractLLCPU):
  2913. py.test.skip("pointless test on non-asm")
  2914. from pypy.jit.backend.x86.tool.viewcode import machine_code_dump
  2915. import ctypes
  2916. ops = """
  2917. [i2]
  2918. i0 = same_as(i2) # but forced to be in a register
  2919. label(i0, descr=1)
  2920. i1 = int_add(i0, i0)
  2921. guard_true(i1, descr=faildesr) [i1]
  2922. jump(i1, descr=1)
  2923. """
  2924. faildescr = BasicFailDescr(2)
  2925. loop = parse(ops, self.cpu, namespace=locals())
  2926. faildescr = loop.operations[-2].getdescr()
  2927. jumpdescr = loop.operations[-1].getdescr()
  2928. bridge_ops = """
  2929. [i0]
  2930. jump(i0, descr=jumpdescr)
  2931. """
  2932. bridge = parse(bridge_ops, self.cpu, namespace=locals())
  2933. looptoken = JitCellToken()
  2934. self.cpu.assembler.set_debug(False)
  2935. info = self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  2936. bridge_info = self.cpu.compile_bridge(faildescr, bridge.inputargs,
  2937. bridge.operations,
  2938. looptoken)
  2939. self.cpu.assembler.set_debug(True) # always on untranslated
  2940. assert info.asmlen != 0
  2941. cpuname = autodetect_main_model_and_size()
  2942. # XXX we have to check the precise assembler, otherwise
  2943. # we don't quite know if borders are correct
  2944. def checkops(mc, ops):
  2945. assert len(mc) == len(ops)
  2946. for i in range(len(mc)):
  2947. assert mc[i].split("\t")[-1].startswith(ops[i])
  2948. data = ctypes.string_at(info.asmaddr, info.asmlen)
  2949. mc = list(machine_code_dump(data, info.asmaddr, cpuname))
  2950. lines = [line for line in mc if line.count('\t') == 2]
  2951. checkops(lines, self.add_loop_instructions)
  2952. data = ctypes.string_at(bridge_info.asmaddr, bridge_info.asmlen)
  2953. mc = list(machine_code_dump(data, bridge_info.asmaddr, cpuname))
  2954. lines = [line for line in mc if line.count('\t') == 2]
  2955. checkops(lines, self.bridge_loop_instructions)
  2956. def test_compile_bridge_with_target(self):
  2957. # This test creates a loopy piece of code in a bridge, and builds another
  2958. # unrelated loop that ends in a jump directly to this loopy bit of code.
  2959. # It catches a case in which we underestimate the needed frame_depth across
  2960. # the cross-loop JUMP, because we estimate it based on the frame_depth stored
  2961. # in the original loop.
  2962. i0 = BoxInt()
  2963. i1 = BoxInt()
  2964. looptoken1 = JitCellToken()
  2965. targettoken1 = TargetToken()
  2966. faildescr1 = BasicFailDescr(2)
  2967. inputargs = [i0]
  2968. operations = [
  2969. ResOperation(rop.INT_LE, [i0, ConstInt(1)], i1),
  2970. ResOperation(rop.GUARD_TRUE, [i1], None, descr=faildescr1),
  2971. ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(1234)),
  2972. ]
  2973. operations[1].setfailargs([i0])
  2974. self.cpu.compile_loop(inputargs, operations, looptoken1)
  2975. def func(a, b, c, d, e, f, g, h, i):
  2976. assert a + 2 == b
  2977. assert a + 4 == c
  2978. assert a + 6 == d
  2979. assert a + 8 == e
  2980. assert a + 10 == f
  2981. assert a + 12 == g
  2982. assert a + 14 == h
  2983. assert a + 16 == i
  2984. FPTR = self.Ptr(self.FuncType([lltype.Signed]*9, lltype.Void))
  2985. func_ptr = llhelper(FPTR, func)
  2986. cpu = self.cpu
  2987. calldescr = cpu.calldescrof(deref(FPTR), (lltype.Signed,)*9, lltype.Void,
  2988. EffectInfo.MOST_GENERAL)
  2989. funcbox = self.get_funcbox(cpu, func_ptr)
  2990. i0 = BoxInt(); i1 = BoxInt(); i2 = BoxInt(); i3 = BoxInt(); i4 = BoxInt()
  2991. i5 = BoxInt(); i6 = BoxInt(); i7 = BoxInt(); i8 = BoxInt(); i9 = BoxInt()
  2992. i10 = BoxInt(); i11 = BoxInt(); i12 = BoxInt(); i13 = BoxInt(); i14 = BoxInt()
  2993. i15 = BoxInt(); i16 = BoxInt(); i17 = BoxInt(); i18 = BoxInt(); i19 = BoxInt()
  2994. i20 = BoxInt()
  2995. inputargs = [i0]
  2996. operations = [
  2997. ResOperation(rop.LABEL, [i0], None, descr=targettoken1),
  2998. ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
  2999. ResOperation(rop.INT_ADD, [i1, ConstInt(1)], i2),
  3000. ResOperation(rop.INT_ADD, [i2, ConstInt(1)], i3),
  3001. ResOperation(rop.INT_ADD, [i3, ConstInt(1)], i4),
  3002. ResOperation(rop.INT_ADD, [i4, ConstInt(1)], i5),
  3003. ResOperation(rop.INT_ADD, [i5, ConstInt(1)], i6),
  3004. ResOperation(rop.INT_ADD, [i6, ConstInt(1)], i7),
  3005. ResOperation(rop.INT_ADD, [i7, ConstInt(1)], i8),
  3006. ResOperation(rop.INT_ADD, [i8, ConstInt(1)], i9),
  3007. ResOperation(rop.INT_ADD, [i9, ConstInt(1)], i10),
  3008. ResOperation(rop.INT_ADD, [i10, ConstInt(1)], i11),
  3009. ResOperation(rop.INT_ADD, [i11, ConstInt(1)], i12),
  3010. ResOperation(rop.INT_ADD, [i12, ConstInt(1)], i13),
  3011. ResOperation(rop.INT_ADD, [i13, ConstInt(1)], i14),
  3012. ResOperation(rop.INT_ADD, [i14, ConstInt(1)], i15),
  3013. ResOperation(rop.INT_ADD, [i15, ConstInt(1)], i16),
  3014. ResOperation(rop.INT_ADD, [i16, ConstInt(1)], i17),
  3015. ResOperation(rop.INT_ADD, [i17, ConstInt(1)], i18),
  3016. ResOperation(rop.INT_ADD, [i18, ConstInt(1)], i19),
  3017. ResOperation(rop.CALL, [funcbox, i2, i4, i6, i8, i10, i12, i14, i16, i18],
  3018. None, descr=calldescr),
  3019. ResOperation(rop.CALL, [funcbox, i2, i4, i6, i8, i10, i12, i14, i16, i18],
  3020. None, descr=calldescr),
  3021. ResOperation(rop.INT_LT, [i19, ConstInt(100)], i20),
  3022. ResOperation(rop.GUARD_TRUE, [i20], None, descr=BasicFailDescr(42)),
  3023. ResOperation(rop.JUMP, [i19], None, descr=targettoken1),
  3024. ]
  3025. operations[-2].setfailargs([])
  3026. self.cpu.compile_bridge(faildescr1, inputargs, operations, looptoken1)
  3027. looptoken2 = JitCellToken()
  3028. inputargs = [BoxInt()]
  3029. operations = [
  3030. ResOperation(rop.JUMP, [ConstInt(0)], None, descr=targettoken1),
  3031. ]
  3032. self.cpu.compile_loop(inputargs, operations, looptoken2)
  3033. fail = self.cpu.execute_token(looptoken2, -9)
  3034. assert fail.identifier == 42
  3035. class OOtypeBackendTest(BaseBackendTest):
  3036. type_system = 'ootype'
  3037. Ptr = staticmethod(lambda x: x)
  3038. FuncType = ootype.StaticMethod
  3039. malloc = staticmethod(ootype.new)
  3040. nullptr = staticmethod(ootype.null)
  3041. def setup_class(cls):
  3042. py.test.skip("ootype tests skipped")
  3043. @classmethod
  3044. def get_funcbox(cls, cpu, func_ptr):
  3045. return BoxObj(ootype.cast_to_object(func_ptr))
  3046. S = ootype.Instance('S', ootype.ROOT, {'value': ootype.Signed,
  3047. 'chr1': ootype.Char,
  3048. 'chr2': ootype.Char})
  3049. S._add_fields({'next': S})
  3050. T = ootype.Instance('T', S)
  3051. U = ootype.Instance('U', T)
  3052. def alloc_instance(self, T):
  3053. t = ootype.new(T)
  3054. cls = ootype.classof(t)
  3055. t_box = BoxObj(ootype.cast_to_object(t))
  3056. T_box = ConstObj(ootype.cast_to_object(cls))
  3057. return t_box, T_box
  3058. def null_instance(self):
  3059. return BoxObj(ootype.NULL)
  3060. def alloc_array_of(self, ITEM, length):
  3061. py.test.skip("implement me")
  3062. def alloc_string(self, string):
  3063. py.test.skip("implement me")
  3064. def alloc_unicode(self, unicode):
  3065. py.test.skip("implement me")