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

/rpython/jit/backend/test/runner_test.py

https://bitbucket.org/pjenvey/pypy-mq
Python | 5359 lines | 5329 code | 25 blank | 5 comment | 40 complexity | ece127fac68b3b5983688c001d2952ae MD5 | raw file
Possible License(s): Apache-2.0, AGPL-3.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. import py, sys, random, os, struct, operator
  2. from rpython.jit.metainterp.history import (AbstractFailDescr,
  3. AbstractDescr,
  4. BasicFailDescr,
  5. BasicFinalDescr,
  6. JitCellToken, TargetToken,
  7. ConstInt, ConstPtr,
  8. ConstFloat, Const)
  9. from rpython.jit.metainterp.resoperation import ResOperation, rop, InputArgInt,\
  10. InputArgFloat, opname, InputArgRef
  11. from rpython.jit.metainterp.typesystem import deref
  12. from rpython.jit.metainterp.executor import wrap_constant
  13. from rpython.jit.codewriter.effectinfo import EffectInfo
  14. from rpython.jit.tool.oparser import parse
  15. from rpython.rtyper.lltypesystem import lltype, llmemory, rstr, rffi
  16. from rpython.rtyper import rclass
  17. from rpython.rtyper.annlowlevel import llhelper
  18. from rpython.rtyper.llinterp import LLException
  19. from rpython.jit.codewriter import heaptracker, longlong
  20. from rpython.rlib import longlong2float
  21. from rpython.rlib.rarithmetic import intmask, is_valid_int
  22. from rpython.jit.backend.detect_cpu import autodetect
  23. from rpython.jit.backend.llsupport import jitframe
  24. from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
  25. from rpython.jit.backend.llsupport.llmodel import MissingLatestDescrError
  26. from rpython.jit.backend.llsupport.rewrite import GcRewriterAssembler
  27. IS_32_BIT = sys.maxint < 2**32
  28. IS_64_BIT = sys.maxint > 2**32
  29. boxfloat = InputArgFloat.fromfloat
  30. constfloat = ConstFloat.fromfloat
  31. def clone(op):
  32. if op.type == 'i':
  33. return InputArgInt(op.getint())
  34. elif op.type == 'r':
  35. return InputArgRef(op.getref_base())
  36. return InputArgFloat(op.getfloatstorage())
  37. def boxlonglong(ll):
  38. if longlong.is_64_bit:
  39. return InputArgInt(ll)
  40. else:
  41. return InputArgFloat(ll)
  42. STUFF = lltype.GcStruct('STUFF')
  43. random_gcref = lltype.cast_opaque_ptr(llmemory.GCREF,
  44. lltype.malloc(STUFF, immortal=True))
  45. class Runner(object):
  46. add_loop_instructions = ['overload for a specific cpu']
  47. bridge_loop_instructions = ['overload for a specific cpu']
  48. def execute_operation(self, opname, valueboxes, result_type, descr=None):
  49. inputargs, operations = self._get_single_operation_list(opname,
  50. result_type,
  51. valueboxes,
  52. descr)
  53. return self.execute_operations(inputargs, operations, result_type)
  54. def execute_operations(self, inputargs, operations, result_type):
  55. looptoken = JitCellToken()
  56. self.cpu.compile_loop(inputargs, operations, looptoken)
  57. args = []
  58. for box in inputargs:
  59. if box.type == 'i':
  60. args.append(box.getint())
  61. elif box.type == 'r':
  62. args.append(box.getref_base())
  63. elif box.type == 'f':
  64. args.append(box.getfloatstorage())
  65. else:
  66. raise NotImplementedError(box)
  67. deadframe = self.cpu.execute_token(looptoken, *args)
  68. if self.cpu.get_latest_descr(deadframe) is operations[-1].getdescr():
  69. self.guard_failed = False
  70. else:
  71. self.guard_failed = True
  72. if result_type == 'int':
  73. return self.cpu.get_int_value(deadframe, 0)
  74. elif result_type == 'ref':
  75. return self.cpu.get_ref_value(deadframe, 0)
  76. elif result_type == 'float':
  77. return self.cpu.get_float_value(deadframe, 0)
  78. elif result_type == 'void':
  79. return None
  80. else:
  81. assert False
  82. def _get_operation_list(self, operations, result_type):
  83. inputargs = []
  84. blacklist = set()
  85. for op in operations:
  86. for arg in op.getarglist():
  87. if not isinstance(arg, Const) and arg not in inputargs and \
  88. arg not in blacklist:
  89. inputargs.append(arg)
  90. if op.type != 'v':
  91. blacklist.add(op)
  92. if result_type == 'void':
  93. op1 = ResOperation(rop.FINISH, [], descr=BasicFinalDescr(0))
  94. else:
  95. op1 = ResOperation(rop.FINISH, [operations[-1]], descr=BasicFinalDescr(0))
  96. operations.append(op1)
  97. return inputargs, operations
  98. def _get_single_operation_list(self, opnum, result_type, valueboxes,
  99. descr):
  100. op0 = ResOperation(opnum, valueboxes)
  101. if result_type == 'void':
  102. op1 = ResOperation(rop.FINISH, [], descr=BasicFinalDescr(0))
  103. else:
  104. op1 = ResOperation(rop.FINISH, [op0], descr=BasicFinalDescr(0))
  105. operations = [op0, op1]
  106. if operations[0].is_guard():
  107. operations[0].setfailargs([])
  108. if not descr:
  109. descr = BasicFailDescr(1)
  110. if descr is not None:
  111. operations[0].setdescr(descr)
  112. inputargs = []
  113. for box in valueboxes:
  114. if not isinstance(box, Const) and box not in inputargs:
  115. inputargs.append(box)
  116. return inputargs, operations
  117. class BaseBackendTest(Runner):
  118. avoid_instances = False
  119. def setup_method(self, _):
  120. self.cpu = self.get_cpu()
  121. self.cpu.done_with_this_frame_descr_int = None
  122. self.cpu.done_with_this_frame_descr_ref = None
  123. self.cpu.done_with_this_frame_descr_float = None
  124. self.cpu.done_with_this_frame_descr_void = None
  125. def test_compile_linear_loop(self):
  126. loop = parse("""
  127. [i0]
  128. i1 = int_add(i0, 1)
  129. finish(i1, descr=faildescr)
  130. """, namespace={"faildescr": BasicFinalDescr(1)})
  131. looptoken = JitCellToken()
  132. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  133. deadframe = self.cpu.execute_token(looptoken, 2)
  134. fail = self.cpu.get_latest_descr(deadframe)
  135. res = self.cpu.get_int_value(deadframe, 0)
  136. assert res == 3
  137. assert fail.identifier == 1
  138. def test_compile_linear_float_loop(self):
  139. if not self.cpu.supports_floats:
  140. py.test.skip("requires floats")
  141. loop = parse("""
  142. [f0]
  143. f1 = float_add(f0, 2.3)
  144. finish(f1, descr=fdescr)
  145. """, namespace={'fdescr': BasicFinalDescr(1)})
  146. looptoken = JitCellToken()
  147. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  148. deadframe = self.cpu.execute_token(looptoken,
  149. longlong.getfloatstorage(2.8))
  150. fail = self.cpu.get_latest_descr(deadframe)
  151. res = self.cpu.get_float_value(deadframe, 0)
  152. assert longlong.getrealfloat(res) == 5.1
  153. fail = self.cpu.get_latest_descr(deadframe)
  154. assert fail.identifier == 1
  155. def test_compile_loop(self):
  156. looptoken = JitCellToken()
  157. targettoken = TargetToken()
  158. loop = parse("""
  159. [i0]
  160. label(i0, descr=targettoken)
  161. i1 = int_add(i0, 1)
  162. i2 = int_le(i1, 9)
  163. guard_true(i2, descr=fdescr) [i1]
  164. jump(i1, descr=targettoken)
  165. """, namespace={'targettoken': targettoken,
  166. 'fdescr': BasicFailDescr(2)})
  167. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  168. deadframe = self.cpu.execute_token(looptoken, 2)
  169. fail = self.cpu.get_latest_descr(deadframe)
  170. assert fail.identifier == 2
  171. res = self.cpu.get_int_value(deadframe, 0)
  172. assert res == 10
  173. def test_compile_with_holes_in_fail_args(self):
  174. targettoken = TargetToken()
  175. loop = parse("""
  176. [i3]
  177. i0 = int_sub(i3, 42)
  178. label(i0, descr=targettoken)
  179. i1 = int_add(i0, 1)
  180. i2 = int_le(i1, 9)
  181. guard_true(i2, descr=fdescr) []
  182. jump(i1, descr=targettoken)
  183. """, namespace={'targettoken': targettoken,
  184. 'fdescr': BasicFailDescr(2)})
  185. looptoken = JitCellToken()
  186. loop.operations[4].setfailargs([None, None, loop.operations[2], None])
  187. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  188. deadframe = self.cpu.execute_token(looptoken, 44)
  189. fail = self.cpu.get_latest_descr(deadframe)
  190. assert fail.identifier == 2
  191. res = self.cpu.get_int_value(deadframe, 2)
  192. assert res == 10
  193. def test_backends_dont_keep_loops_alive(self):
  194. import weakref, gc
  195. self.cpu.dont_keepalive_stuff = True
  196. targettoken = TargetToken()
  197. loop = parse("""
  198. [i0]
  199. label(i0, descr=targettoken)
  200. i1 = int_add(i0, 1)
  201. i2 = int_le(i1, 9)
  202. guard_true(i2, descr=fdescr) [i1]
  203. jump(i1, descr=targettoken)
  204. """, namespace={'targettoken': targettoken, 'fdescr': BasicFailDescr()})
  205. looptoken = JitCellToken()
  206. wr_i1 = weakref.ref(loop.operations[1])
  207. wr_guard = weakref.ref(loop.operations[3])
  208. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  209. if hasattr(looptoken, '_x86_ops_offset'):
  210. del looptoken._x86_ops_offset # else it's kept alive
  211. if hasattr(looptoken, '_ppc_ops_offset'):
  212. del looptoken._ppc_ops_offset # else it's kept alive
  213. if hasattr(looptoken, '_zarch_ops_offset'):
  214. del looptoken._zarch_ops_offset # else it's kept alive
  215. del loop
  216. gc.collect()
  217. assert not wr_i1() and not wr_guard()
  218. def test_compile_bridge(self):
  219. self.cpu.tracker.total_compiled_loops = 0
  220. self.cpu.tracker.total_compiled_bridges = 0
  221. targettoken = TargetToken()
  222. faildescr1 = BasicFailDescr(1)
  223. faildescr2 = BasicFailDescr(2)
  224. loop = parse("""
  225. [i0]
  226. label(i0, descr=targettoken)
  227. i1 = int_add(i0, 1)
  228. i2 = int_le(i1, 9)
  229. guard_true(i2, descr=faildescr1) [i1]
  230. jump(i1, descr=targettoken)
  231. """, namespace={'targettoken': targettoken,
  232. 'faildescr1': faildescr1})
  233. looptoken = JitCellToken()
  234. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  235. bridge = parse("""
  236. [i1]
  237. i3 = int_le(i1, 19)
  238. guard_true(i3, descr=faildescr2) [i1]
  239. jump(i1, descr=targettoken)
  240. """, namespace={"targettoken": targettoken,
  241. 'faildescr2': faildescr2})
  242. self.cpu.compile_bridge(faildescr1, bridge.inputargs,
  243. bridge.operations, looptoken)
  244. deadframe = self.cpu.execute_token(looptoken, 2)
  245. fail = self.cpu.get_latest_descr(deadframe)
  246. assert fail.identifier == 2
  247. res = self.cpu.get_int_value(deadframe, 0)
  248. assert res == 20
  249. assert self.cpu.tracker.total_compiled_loops == 1
  250. assert self.cpu.tracker.total_compiled_bridges == 1
  251. return looptoken
  252. def test_compile_bridge_with_holes(self):
  253. faildescr1 = BasicFailDescr(1)
  254. faildescr2 = BasicFailDescr(2)
  255. looptoken = JitCellToken()
  256. targettoken = TargetToken()
  257. loop = parse("""
  258. [i3]
  259. i0 = int_sub(i3, 42)
  260. label(i0, descr=targettoken)
  261. i1 = int_add(i0, 1)
  262. i2 = int_le(i1, 9)
  263. guard_true(i2, descr=faildescr1) []
  264. jump(i1, descr=targettoken)
  265. """, namespace={'targettoken': targettoken,
  266. 'faildescr1': faildescr1})
  267. loop.operations[-2].setfailargs([None, loop.operations[2], None])
  268. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  269. bridge = parse("""
  270. [i1]
  271. i3 = int_le(i1, 19)
  272. guard_true(i3, descr=faildescr2) [i1]
  273. jump(i1, descr=targettoken)
  274. """, namespace={'targettoken': targettoken,
  275. 'faildescr2': faildescr2})
  276. self.cpu.compile_bridge(faildescr1, bridge.inputargs,
  277. bridge.operations, looptoken)
  278. deadframe = self.cpu.execute_token(looptoken, 2)
  279. fail = self.cpu.get_latest_descr(deadframe)
  280. assert fail.identifier == 2
  281. res = self.cpu.get_int_value(deadframe, 0)
  282. assert res == 20
  283. def test_compile_big_bridge_out_of_small_loop(self):
  284. faildescr1 = BasicFailDescr(1)
  285. loop = parse("""
  286. [i0]
  287. guard_false(i0, descr=faildescr1) [i0]
  288. finish(descr=finaldescr)
  289. """, namespace={'faildescr1': faildescr1,
  290. 'finaldescr': BasicFinalDescr(2)})
  291. looptoken = JitCellToken()
  292. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  293. bridge = []
  294. i0 = InputArgInt()
  295. iprev = i0
  296. for i in range(150):
  297. iprev = ResOperation(rop.INT_ADD, [iprev, ConstInt(1)])
  298. bridge.append(iprev)
  299. bridge.append(ResOperation(rop.GUARD_FALSE, [i0],
  300. descr=BasicFailDescr(3)))
  301. bridge.append(ResOperation(rop.FINISH, [],
  302. descr=BasicFinalDescr(4)))
  303. bridge[-2].setfailargs(bridge[:-2])
  304. self.cpu.compile_bridge(faildescr1, [i0], bridge, looptoken)
  305. deadframe = self.cpu.execute_token(looptoken, 1)
  306. fail = self.cpu.get_latest_descr(deadframe)
  307. assert fail.identifier == 3
  308. for i in range(150):
  309. res = self.cpu.get_int_value(deadframe, i)
  310. assert res == 2 + i
  311. def test_finish(self):
  312. from rpython.jit.backend.llsupport.llmodel import final_descr_rd_locs
  313. class UntouchableFailDescr(AbstractFailDescr):
  314. final_descr = True
  315. rd_locs = final_descr_rd_locs
  316. def __setattr__(self, name, value):
  317. if (name == 'index' or name == '_carry_around_for_tests'
  318. or name == '_TYPE' or name == '_cpu'):
  319. return AbstractFailDescr.__setattr__(self, name, value)
  320. py.test.fail("finish descrs should not be touched")
  321. faildescr = UntouchableFailDescr() # to check that is not touched
  322. looptoken = JitCellToken()
  323. loop = parse("""
  324. [i0]
  325. finish(i0, descr=faildescr)
  326. """, namespace={'faildescr': faildescr})
  327. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  328. deadframe = self.cpu.execute_token(looptoken, 99)
  329. fail = self.cpu.get_latest_descr(deadframe)
  330. assert fail is faildescr
  331. res = self.cpu.get_int_value(deadframe, 0)
  332. assert res == 99
  333. looptoken = JitCellToken()
  334. operations = [
  335. ResOperation(rop.FINISH, [ConstInt(42)], descr=faildescr)
  336. ]
  337. self.cpu.compile_loop([], operations, looptoken)
  338. deadframe = self.cpu.execute_token(looptoken)
  339. fail = self.cpu.get_latest_descr(deadframe)
  340. assert fail is faildescr
  341. res = self.cpu.get_int_value(deadframe, 0)
  342. assert res == 42
  343. looptoken = JitCellToken()
  344. operations = [
  345. ResOperation(rop.FINISH, [], descr=faildescr)
  346. ]
  347. self.cpu.compile_loop([], operations, looptoken)
  348. deadframe = self.cpu.execute_token(looptoken)
  349. fail = self.cpu.get_latest_descr(deadframe)
  350. assert fail is faildescr
  351. if self.cpu.supports_floats:
  352. looptoken = JitCellToken()
  353. f0 = InputArgFloat()
  354. operations = [
  355. ResOperation(rop.FINISH, [f0], descr=faildescr)
  356. ]
  357. self.cpu.compile_loop([f0], operations, looptoken)
  358. value = longlong.getfloatstorage(-61.25)
  359. deadframe = self.cpu.execute_token(looptoken, value)
  360. fail = self.cpu.get_latest_descr(deadframe)
  361. assert fail is faildescr
  362. res = self.cpu.get_float_value(deadframe, 0)
  363. assert longlong.getrealfloat(res) == -61.25
  364. looptoken = JitCellToken()
  365. operations = [
  366. ResOperation(rop.FINISH, [constfloat(42.5)], descr=faildescr)
  367. ]
  368. self.cpu.compile_loop([], operations, looptoken)
  369. deadframe = self.cpu.execute_token(looptoken)
  370. fail = self.cpu.get_latest_descr(deadframe)
  371. assert fail is faildescr
  372. res = self.cpu.get_float_value(deadframe, 0)
  373. assert longlong.getrealfloat(res) == 42.5
  374. def test_execute_operations_in_env(self):
  375. cpu = self.cpu
  376. targettoken = TargetToken()
  377. loop = parse("""
  378. [i1, i0]
  379. label(i0, i1, descr=targettoken)
  380. i2 = int_add(i1, i0)
  381. i3 = int_sub(i0, 1)
  382. i4 = int_eq(i3, 0)
  383. guard_false(i4, descr=fdescr) [i3, i2]
  384. jump(i3, i2, descr=targettoken)
  385. """, namespace={'targettoken': targettoken,
  386. 'fdescr': BasicFailDescr()})
  387. looptoken = JitCellToken()
  388. cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  389. deadframe = self.cpu.execute_token(looptoken, 0, 10)
  390. assert self.cpu.get_int_value(deadframe, 0) == 0
  391. assert self.cpu.get_int_value(deadframe, 1) == 55
  392. def test_int_operations(self):
  393. from rpython.jit.metainterp.test.test_executor import get_int_tests
  394. for opnum, boxargs, retvalue in get_int_tests():
  395. print opnum
  396. res = self.execute_operation(opnum, boxargs, 'int')
  397. assert res == retvalue
  398. def test_float_operations(self):
  399. from rpython.jit.metainterp.test.test_executor import get_float_tests
  400. from rpython.jit.metainterp.resoperation import opname
  401. for opnum, boxargs, rettype, retvalue in get_float_tests(self.cpu):
  402. print("testing", opname[opnum])
  403. res = self.execute_operation(opnum, boxargs, rettype)
  404. if rettype == 'float':
  405. res = longlong.getrealfloat(res)
  406. assert res == retvalue
  407. def test_ovf_operations(self, reversed=False):
  408. minint = -sys.maxint-1
  409. boom = 'boom'
  410. for opnum, testcases in [
  411. (rop.INT_ADD_OVF, [(10, -2, 8),
  412. (-1, minint, boom),
  413. (sys.maxint//2, sys.maxint//2+2, boom)]),
  414. (rop.INT_SUB_OVF, [(-20, -23, 3),
  415. (-2, sys.maxint, boom),
  416. (sys.maxint//2, -(sys.maxint//2+2), boom)]),
  417. (rop.INT_MUL_OVF, [(minint/2, 2, minint),
  418. (-2, -(minint/2), minint),
  419. (minint/2, -2, boom)]),
  420. ]:
  421. v1 = InputArgInt(testcases[0][0])
  422. v2 = InputArgInt(testcases[0][1])
  423. #
  424. if not reversed:
  425. op0 = ResOperation(opnum, [v1, v2])
  426. op1 = ResOperation(rop.GUARD_NO_OVERFLOW, [],
  427. descr=BasicFailDescr(1))
  428. op2 = ResOperation(rop.FINISH, [op0], descr=BasicFinalDescr(2))
  429. ops = [op0, op1, op2]
  430. op1.setfailargs([])
  431. else:
  432. op0 = ResOperation(opnum, [v1, v2])
  433. op1 = ResOperation(rop.GUARD_OVERFLOW, [],
  434. descr=BasicFailDescr(1))
  435. op2 = ResOperation(rop.FINISH, [], descr=BasicFinalDescr(2))
  436. ops = [op0, op1, op2]
  437. op1.setfailargs([op0])
  438. #
  439. looptoken = JitCellToken()
  440. self.cpu.compile_loop([v1, v2], ops, looptoken)
  441. for x, y, z in testcases:
  442. deadframe = self.cpu.execute_token(looptoken, x, y)
  443. fail = self.cpu.get_latest_descr(deadframe)
  444. if (z == boom) ^ reversed:
  445. assert fail.identifier == 1
  446. else:
  447. assert fail.identifier == 2
  448. if z != boom:
  449. assert self.cpu.get_int_value(deadframe, 0) == z
  450. excvalue = self.cpu.grab_exc_value(deadframe)
  451. assert not excvalue
  452. def test_ovf_operations_reversed(self):
  453. self.test_ovf_operations(reversed=True)
  454. def test_bh_call(self):
  455. cpu = self.cpu
  456. #
  457. def func(c):
  458. return chr(ord(c) + 1)
  459. FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char))
  460. func_ptr = llhelper(FPTR, func)
  461. calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char,
  462. EffectInfo.MOST_GENERAL)
  463. x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value,
  464. [ord('A')], None, None, calldescr)
  465. assert x == ord('B')
  466. if cpu.supports_floats:
  467. def func(f, i):
  468. assert isinstance(f, float)
  469. assert is_valid_int(i)
  470. return f - float(i)
  471. FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed],
  472. lltype.Float))
  473. func_ptr = llhelper(FPTR, func)
  474. FTP = deref(FPTR)
  475. calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT,
  476. EffectInfo.MOST_GENERAL)
  477. x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value,
  478. [42], None, [longlong.getfloatstorage(3.5)],
  479. calldescr)
  480. assert longlong.getrealfloat(x) == 3.5 - 42
  481. def test_call(self):
  482. from rpython.rlib.jit_libffi import types
  483. def func_int(a, b):
  484. return a + b
  485. def func_char(c, c1):
  486. return chr(ord(c) + ord(c1))
  487. functions = [
  488. (func_int, lltype.Signed, types.sint, 655360, 655360),
  489. (func_int, lltype.Signed, types.sint, 655360, -293999429),
  490. (func_int, rffi.SHORT, types.sint16, 1213, 1213),
  491. (func_int, rffi.SHORT, types.sint16, 1213, -12020),
  492. (func_char, lltype.Char, types.uchar, 12, 12),
  493. ]
  494. cpu = self.cpu
  495. for func, TP, ffi_type, num, num1 in functions:
  496. #
  497. FPTR = self.Ptr(self.FuncType([TP, TP], TP))
  498. func_ptr = llhelper(FPTR, func)
  499. FUNC = deref(FPTR)
  500. funcbox = self.get_funcbox(cpu, func_ptr)
  501. # first, try it with the "normal" calldescr
  502. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  503. EffectInfo.MOST_GENERAL)
  504. res = self.execute_operation(rop.CALL_I,
  505. [funcbox, InputArgInt(num),
  506. InputArgInt(num1)],
  507. 'int', descr=calldescr)
  508. assert res == num + num1
  509. # then, try it with the dynamic calldescr
  510. dyn_calldescr = cpu._calldescr_dynamic_for_tests(
  511. [ffi_type, ffi_type], ffi_type)
  512. res = self.execute_operation(rop.CALL_I,
  513. [funcbox, InputArgInt(num),
  514. InputArgInt(num1)],
  515. 'int', descr=dyn_calldescr)
  516. assert res == num + num1
  517. # last, try it with one constant argument
  518. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo.MOST_GENERAL)
  519. res = self.execute_operation(rop.CALL_I,
  520. [funcbox, ConstInt(num),
  521. InputArgInt(num1)],
  522. 'int', descr=calldescr)
  523. assert res == num + num1
  524. if cpu.supports_floats:
  525. def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9):
  526. seen.append((f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9))
  527. return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
  528. seen = []
  529. F = lltype.Float
  530. I = lltype.Signed
  531. FUNC = self.FuncType([F] * 7 + [I] + [F] + [I] + [F]* 2, F)
  532. FPTR = self.Ptr(FUNC)
  533. func_ptr = llhelper(FPTR, func)
  534. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  535. EffectInfo.MOST_GENERAL)
  536. funcbox = self.get_funcbox(cpu, func_ptr)
  537. args = ([boxfloat(.0), boxfloat(.1), boxfloat(.2), boxfloat(.3),
  538. boxfloat(.4), boxfloat(.5), boxfloat(.6),
  539. InputArgInt(1), boxfloat(.7), InputArgInt(2), boxfloat(.8),
  540. boxfloat(.9)])
  541. res = self.execute_operation(rop.CALL_F,
  542. [funcbox] + args,
  543. 'float', descr=calldescr)
  544. assert seen == [(.0, .1, .2, .3, .4, .5, .6, 1, .7, 2, .8, .9)]
  545. assert abs(longlong.getrealfloat(res) - 7.5) < 0.0001
  546. def test_call_many_arguments(self):
  547. # Test calling a function with a large number of arguments (more than
  548. # 6, which will force passing some arguments on the stack on 64-bit)
  549. def func(*args):
  550. assert len(args) == 16
  551. # Try to sum up args in a way that would probably detect a
  552. # transposed argument
  553. return sum(arg * (2**i) for i, arg in enumerate(args))
  554. FUNC = self.FuncType([lltype.Signed]*16, lltype.Signed)
  555. FPTR = self.Ptr(FUNC)
  556. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  557. EffectInfo.MOST_GENERAL)
  558. func_ptr = llhelper(FPTR, func)
  559. args = range(16)
  560. funcbox = self.get_funcbox(self.cpu, func_ptr)
  561. res = self.execute_operation(rop.CALL_I, [funcbox] + map(InputArgInt, args), 'int', descr=calldescr)
  562. assert res == func(*args)
  563. def test_call_box_func(self):
  564. def a(a1, a2):
  565. return a1 + a2
  566. def b(b1, b2):
  567. return b1 * b2
  568. arg1 = 40
  569. arg2 = 2
  570. for f in [a, b]:
  571. TP = lltype.Signed
  572. FPTR = self.Ptr(self.FuncType([TP, TP], TP))
  573. func_ptr = llhelper(FPTR, f)
  574. FUNC = deref(FPTR)
  575. funcconst = self.get_funcbox(self.cpu, func_ptr)
  576. funcbox = InputArgInt(funcconst.getint())
  577. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  578. EffectInfo.MOST_GENERAL)
  579. res = self.execute_operation(rop.CALL_I,
  580. [funcbox, InputArgInt(arg1),
  581. InputArgInt(arg2)],
  582. 'int', descr=calldescr)
  583. assert res == f(arg1, arg2)
  584. def test_call_stack_alignment(self):
  585. # test stack alignment issues, notably for Mac OS/X.
  586. # also test the ordering of the arguments.
  587. def func_ints(*ints):
  588. s = str(ints) + '\n'
  589. os.write(1, s) # don't remove -- crash if the stack is misaligned
  590. return sum([(10+i)*(5+j) for i, j in enumerate(ints)])
  591. for nb_args in range(0, 35):
  592. cpu = self.cpu
  593. TP = lltype.Signed
  594. #
  595. FPTR = self.Ptr(self.FuncType([TP] * nb_args, TP))
  596. func_ptr = llhelper(FPTR, func_ints)
  597. FUNC = deref(FPTR)
  598. calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  599. EffectInfo.MOST_GENERAL)
  600. funcbox = self.get_funcbox(cpu, func_ptr)
  601. args = [280-24*i for i in range(nb_args)]
  602. res = self.execute_operation(rop.CALL_I,
  603. [funcbox] + map(InputArgInt, args),
  604. 'int', descr=calldescr)
  605. assert res == func_ints(*args)
  606. def test_call_with_const_floats(self):
  607. if not self.cpu.supports_floats:
  608. py.test.skip("requires floats")
  609. def func(f1, f2):
  610. return f1 + f2
  611. FUNC = self.FuncType([lltype.Float, lltype.Float], lltype.Float)
  612. FPTR = self.Ptr(FUNC)
  613. calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
  614. EffectInfo.MOST_GENERAL)
  615. func_ptr = llhelper(FPTR, func)
  616. funcbox = self.get_funcbox(self.cpu, func_ptr)
  617. res = self.execute_operation(rop.CALL_F, [funcbox, constfloat(1.5),
  618. constfloat(2.5)], 'float',
  619. descr=calldescr)
  620. assert longlong.getrealfloat(res) == 4.0
  621. def test_field_basic(self):
  622. t_box, T_box, d = self.alloc_instance(self.T)
  623. fielddescr = self.cpu.fielddescrof(self.S, 'value')
  624. assert not fielddescr.is_pointer_field()
  625. #
  626. res = self.execute_operation(rop.SETFIELD_GC, [t_box, InputArgInt(39082)],
  627. 'void', descr=fielddescr)
  628. assert res is None
  629. res = self.execute_operation(rop.GETFIELD_GC_I, [t_box],
  630. 'int', descr=fielddescr)
  631. assert res == 39082
  632. #
  633. fielddescr1 = self.cpu.fielddescrof(self.S, 'chr1')
  634. fielddescr2 = self.cpu.fielddescrof(self.S, 'chr2')
  635. shortdescr = self.cpu.fielddescrof(self.S, 'short')
  636. self.execute_operation(rop.SETFIELD_GC, [t_box, InputArgInt(250)],
  637. 'void', descr=fielddescr2)
  638. self.execute_operation(rop.SETFIELD_GC, [t_box, InputArgInt(133)],
  639. 'void', descr=fielddescr1)
  640. self.execute_operation(rop.SETFIELD_GC, [t_box, InputArgInt(1331)],
  641. 'void', descr=shortdescr)
  642. res = self.execute_operation(rop.GETFIELD_GC_I, [t_box],
  643. 'int', descr=fielddescr2)
  644. assert res == 250
  645. res = self.execute_operation(rop.GETFIELD_GC_I, [t_box],
  646. 'int', descr=fielddescr1)
  647. assert res == 133
  648. res = self.execute_operation(rop.GETFIELD_GC_I, [t_box],
  649. 'int', descr=shortdescr)
  650. assert res == 1331
  651. #
  652. u_box, U_box, d = self.alloc_instance(self.U)
  653. fielddescr2 = self.cpu.fielddescrof(self.S, 'next')
  654. assert fielddescr2.is_pointer_field()
  655. res = self.execute_operation(rop.SETFIELD_GC, [t_box, u_box],
  656. 'void', descr=fielddescr2)
  657. assert res is None
  658. res = self.execute_operation(rop.GETFIELD_GC_R, [t_box],
  659. 'ref', descr=fielddescr2)
  660. assert res == u_box.getref_base()
  661. #
  662. null_const = wrap_constant(self.null_instance().getref_base())
  663. res = self.execute_operation(rop.SETFIELD_GC, [t_box, null_const],
  664. 'void', descr=fielddescr2)
  665. assert res is None
  666. res = self.execute_operation(rop.GETFIELD_GC_R, [t_box],
  667. 'ref', descr=fielddescr2)
  668. assert not res
  669. if self.cpu.supports_floats:
  670. floatdescr = self.cpu.fielddescrof(self.S, 'float')
  671. self.execute_operation(rop.SETFIELD_GC, [t_box, boxfloat(3.4)],
  672. 'void', descr=floatdescr)
  673. res = self.execute_operation(rop.GETFIELD_GC_F, [t_box],
  674. 'float', descr=floatdescr)
  675. assert longlong.getrealfloat(res) == 3.4
  676. #
  677. self.execute_operation(rop.SETFIELD_GC, [t_box, constfloat(-3.6)],
  678. 'void', descr=floatdescr)
  679. res = self.execute_operation(rop.GETFIELD_GC_F, [t_box],
  680. 'float', descr=floatdescr)
  681. assert longlong.getrealfloat(res) == -3.6
  682. def test_passing_guards(self):
  683. t_box, T_box, d = self.alloc_instance(self.T)
  684. nullbox = self.null_instance()
  685. all = [(rop.GUARD_TRUE, [InputArgInt(1)]),
  686. (rop.GUARD_FALSE, [InputArgInt(0)]),
  687. (rop.GUARD_VALUE, [InputArgInt(42), ConstInt(42)]),
  688. ]
  689. if not self.avoid_instances:
  690. all.extend([
  691. (rop.GUARD_NONNULL, [t_box]),
  692. (rop.GUARD_ISNULL, [nullbox])
  693. ])
  694. if self.cpu.supports_floats:
  695. all.append((rop.GUARD_VALUE, [boxfloat(3.5), constfloat(3.5)]))
  696. for (opname, args) in all:
  697. assert self.execute_operation(opname, args, 'void') == None
  698. assert not self.guard_failed
  699. def test_passing_guard_class(self):
  700. t_box, T_box, d = self.alloc_instance(self.T)
  701. #null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T)))
  702. self.execute_operation(rop.GUARD_CLASS, [t_box, T_box], 'void')
  703. assert not self.guard_failed
  704. self.execute_operation(rop.GUARD_NONNULL_CLASS, [t_box, T_box], 'void')
  705. assert not self.guard_failed
  706. def test_failing_guards(self):
  707. t_box, T_box, d = self.alloc_instance(self.T)
  708. nullbox = self.null_instance()
  709. all = [(rop.GUARD_TRUE, [InputArgInt(0)]),
  710. (rop.GUARD_FALSE, [InputArgInt(1)]),
  711. (rop.GUARD_VALUE, [InputArgInt(42), ConstInt(41)]),
  712. ]
  713. if not self.avoid_instances:
  714. all.extend([
  715. (rop.GUARD_NONNULL, [nullbox]),
  716. (rop.GUARD_ISNULL, [t_box])])
  717. if self.cpu.supports_floats:
  718. all.append((rop.GUARD_VALUE, [boxfloat(-1.0), constfloat(1.0)]))
  719. for opname, args in all:
  720. assert self.execute_operation(opname, args, 'void') == None
  721. assert self.guard_failed
  722. def test_failing_guard_class(self):
  723. t_box, T_box, _ = self.alloc_instance(self.T)
  724. u_box, U_box, _ = self.alloc_instance(self.U)
  725. null_box = self.null_instance()
  726. for opname, args in [(rop.GUARD_CLASS, [t_box, U_box]),
  727. (rop.GUARD_CLASS, [u_box, T_box]),
  728. (rop.GUARD_NONNULL_CLASS, [t_box, U_box]),
  729. (rop.GUARD_NONNULL_CLASS, [u_box, T_box]),
  730. (rop.GUARD_NONNULL_CLASS, [null_box, T_box]),
  731. ]:
  732. assert self.execute_operation(opname, args, 'void') == None
  733. assert self.guard_failed
  734. def test_ooops(self):
  735. u1_box, U_box, _ = self.alloc_instance(self.U)
  736. u2_box, U_box, _ = self.alloc_instance(self.U)
  737. r = self.execute_operation(rop.PTR_EQ, [u1_box,
  738. clone(u1_box)], 'int')
  739. assert r == 1
  740. r = self.execute_operation(rop.PTR_NE, [u2_box,
  741. clone(u2_box)], 'int')
  742. assert r == 0
  743. r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int')
  744. assert r == 0
  745. r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int')
  746. assert r == 1
  747. #
  748. null_box = self.null_instance()
  749. r = self.execute_operation(rop.PTR_EQ, [null_box,
  750. clone(null_box)], 'int')
  751. assert r == 1
  752. r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int')
  753. assert r == 0
  754. r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int')
  755. assert r == 0
  756. r = self.execute_operation(rop.PTR_NE, [null_box,
  757. clone(null_box)], 'int')
  758. assert r == 0
  759. r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int')
  760. assert r == 1
  761. r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int')
  762. assert r == 1
  763. # These operations are supposed to be the same as PTR_EQ/PTR_NE
  764. # just checking that the operations are defined in the backend.
  765. r = self.execute_operation(rop.INSTANCE_PTR_EQ, [u1_box, u2_box], 'int')
  766. assert r == 0
  767. r = self.execute_operation(rop.INSTANCE_PTR_NE, [u2_box, u1_box], 'int')
  768. assert r == 1
  769. def test_array_basic(self):
  770. a_box, A = self.alloc_array_of(rffi.SHORT, 342)
  771. arraydescr = self.cpu.arraydescrof(A)
  772. assert not arraydescr.is_array_of_pointers()
  773. #
  774. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  775. 'int', descr=arraydescr)
  776. assert r == 342
  777. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(310),
  778. InputArgInt(744)],
  779. 'void', descr=arraydescr)
  780. assert r is None
  781. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(310)],
  782. 'int', descr=arraydescr)
  783. assert r == 744
  784. a_box, A = self.alloc_array_of(lltype.Signed, 342)
  785. arraydescr = self.cpu.arraydescrof(A)
  786. assert not arraydescr.is_array_of_pointers()
  787. #
  788. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  789. 'int', descr=arraydescr)
  790. assert r == 342
  791. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(310),
  792. InputArgInt(7441)],
  793. 'void', descr=arraydescr)
  794. assert r is None
  795. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(310)],
  796. 'int', descr=arraydescr)
  797. assert r == 7441
  798. #
  799. a_box, A = self.alloc_array_of(lltype.Char, 11)
  800. arraydescr = self.cpu.arraydescrof(A)
  801. assert not arraydescr.is_array_of_pointers()
  802. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  803. 'int', descr=arraydescr)
  804. assert r == 11
  805. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(4),
  806. InputArgInt(150)],
  807. 'void', descr=arraydescr)
  808. assert r is None
  809. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(3),
  810. InputArgInt(160)],
  811. 'void', descr=arraydescr)
  812. assert r is None
  813. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(4)],
  814. 'int', descr=arraydescr)
  815. assert r == 150
  816. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(3)],
  817. 'int', descr=arraydescr)
  818. assert r == 160
  819. #
  820. if isinstance(A, lltype.GcArray):
  821. A = lltype.Ptr(A)
  822. b_box, B = self.alloc_array_of(A, 3)
  823. arraydescr = self.cpu.arraydescrof(B)
  824. assert arraydescr.is_array_of_pointers()
  825. r = self.execute_operation(rop.ARRAYLEN_GC, [b_box],
  826. 'int', descr=arraydescr)
  827. assert r == 3
  828. r = self.execute_operation(rop.SETARRAYITEM_GC, [b_box, InputArgInt(1),
  829. a_box],
  830. 'void', descr=arraydescr)
  831. assert r is None
  832. r = self.execute_operation(rop.GETARRAYITEM_GC_R, [b_box, InputArgInt(1)],
  833. 'ref', descr=arraydescr)
  834. assert r == a_box.getvalue()
  835. #
  836. # Unsigned should work the same as Signed
  837. a_box, A = self.alloc_array_of(lltype.Unsigned, 342)
  838. arraydescr = self.cpu.arraydescrof(A)
  839. assert not arraydescr.is_array_of_pointers()
  840. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  841. 'int', descr=arraydescr)
  842. assert r == 342
  843. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(310),
  844. InputArgInt(7441)],
  845. 'void', descr=arraydescr)
  846. assert r is None
  847. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(310)],
  848. 'int', descr=arraydescr)
  849. assert r == 7441
  850. #
  851. # Bool should work the same as Char
  852. a_box, A = self.alloc_array_of(lltype.Bool, 311)
  853. arraydescr = self.cpu.arraydescrof(A)
  854. assert not arraydescr.is_array_of_pointers()
  855. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  856. 'int', descr=arraydescr)
  857. assert r == 311
  858. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(304),
  859. InputArgInt(1)],
  860. 'void', descr=arraydescr)
  861. assert r is None
  862. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(303),
  863. InputArgInt(0)],
  864. 'void', descr=arraydescr)
  865. assert r is None
  866. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(302),
  867. InputArgInt(1)],
  868. 'void', descr=arraydescr)
  869. assert r is None
  870. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(304)],
  871. 'int', descr=arraydescr)
  872. assert r == 1
  873. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(303)],
  874. 'int', descr=arraydescr)
  875. assert r == 0
  876. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(302)],
  877. 'int', descr=arraydescr)
  878. assert r == 1
  879. if self.cpu.supports_floats:
  880. a_box, A = self.alloc_array_of(lltype.Float, 31)
  881. arraydescr = self.cpu.arraydescrof(A)
  882. self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(1),
  883. boxfloat(3.5)],
  884. 'void', descr=arraydescr)
  885. self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(2),
  886. constfloat(4.5)],
  887. 'void', descr=arraydescr)
  888. r = self.execute_operation(rop.GETARRAYITEM_GC_F, [a_box, InputArgInt(1)],
  889. 'float', descr=arraydescr)
  890. assert longlong.getrealfloat(r) == 3.5
  891. r = self.execute_operation(rop.GETARRAYITEM_GC_F, [a_box, InputArgInt(2)],
  892. 'float', descr=arraydescr)
  893. assert longlong.getrealfloat(r) == 4.5
  894. # For platforms where sizeof(INT) != sizeof(Signed) (ie, x86-64)
  895. a_box, A = self.alloc_array_of(rffi.INT, 342)
  896. arraydescr = self.cpu.arraydescrof(A)
  897. assert not arraydescr.is_array_of_pointers()
  898. r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
  899. 'int', descr=arraydescr)
  900. assert r == 342
  901. r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, InputArgInt(310),
  902. InputArgInt(7441)],
  903. 'void', descr=arraydescr)
  904. assert r is None
  905. r = self.execute_operation(rop.GETARRAYITEM_GC_I, [a_box, InputArgInt(310)],
  906. 'int', descr=arraydescr)
  907. assert r == 7441
  908. def test_array_of_structs(self):
  909. TP = lltype.GcStruct('x')
  910. ITEM = lltype.Struct('x',
  911. ('vs', lltype.Signed),
  912. ('vu', lltype.Unsigned),
  913. ('vsc', rffi.SIGNEDCHAR),
  914. ('vuc', rffi.UCHAR),
  915. ('vss', rffi.SHORT),
  916. ('vus', rffi.USHORT),
  917. ('vsi', rffi.INT),
  918. ('vui', rffi.UINT),
  919. ('k', lltype.Float),
  920. ('p', lltype.Ptr(TP)))
  921. a_box, A = self.alloc_array_of(ITEM, 15)
  922. s_box, S, _ = self.alloc_instance(TP)
  923. vsdescr = self.cpu.interiorfielddescrof(A, 'vs')
  924. kdescr = self.cpu.interiorfielddescrof(A, 'k')
  925. pdescr = self.cpu.interiorfielddescrof(A, 'p')
  926. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, InputArgInt(3),
  927. boxfloat(1.5)],
  928. 'void', descr=kdescr)
  929. f = self.cpu.bh_getinteriorfield_gc_f(a_box.getref_base(), 3, kdescr)
  930. assert longlong.getrealfloat(f) == 1.5
  931. self.cpu.bh_setinteriorfield_gc_f(a_box.getref_base(), 3, longlong.getfloatstorage(2.5), kdescr)
  932. r = self.execute_operation(rop.GETINTERIORFIELD_GC_F, [a_box, InputArgInt(3)],
  933. 'float', descr=kdescr)
  934. assert longlong.getrealfloat(r) == 2.5
  935. #
  936. NUMBER_FIELDS = [('vs', lltype.Signed),
  937. ('vu', lltype.Unsigned),
  938. ('vsc', rffi.SIGNEDCHAR),
  939. ('vuc', rffi.UCHAR),
  940. ('vss', rffi.SHORT),
  941. ('vus', rffi.USHORT),
  942. ('vsi', rffi.INT),
  943. ('vui', rffi.UINT)]
  944. for name, TYPE in NUMBER_FIELDS[::-1]:
  945. vdescr = self.cpu.interiorfielddescrof(A, name)
  946. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, InputArgInt(3),
  947. InputArgInt(-15)],
  948. 'void', descr=vdescr)
  949. for name, TYPE in NUMBER_FIELDS:
  950. vdescr = self.cpu.interiorfielddescrof(A, name)
  951. i = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 3,
  952. vdescr)
  953. assert i == rffi.cast(lltype.Signed, rffi.cast(TYPE, -15))
  954. for name, TYPE in NUMBER_FIELDS[::-1]:
  955. vdescr = self.cpu.interiorfielddescrof(A, name)
  956. self.cpu.bh_setinteriorfield_gc_i(a_box.getref_base(), 3,
  957. -25, vdescr)
  958. for name, TYPE in NUMBER_FIELDS:
  959. vdescr = self.cpu.interiorfielddescrof(A, name)
  960. r = self.execute_operation(rop.GETINTERIORFIELD_GC_I,
  961. [a_box, InputArgInt(3)],
  962. 'int', descr=vdescr)
  963. assert r == rffi.cast(lltype.Signed, rffi.cast(TYPE, -25))
  964. #
  965. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, InputArgInt(4),
  966. s_box],
  967. 'void', descr=pdescr)
  968. r = self.cpu.bh_getinteriorfield_gc_r(a_box.getref_base(), 4, pdescr)
  969. assert r == s_box.getref_base()
  970. self.cpu.bh_setinteriorfield_gc_r(a_box.getref_base(), 3,
  971. s_box.getref_base(), pdescr)
  972. r = self.execute_operation(rop.GETINTERIORFIELD_GC_R, [a_box, InputArgInt(3)],
  973. 'ref', descr=pdescr)
  974. assert r == s_box.getref_base()
  975. #
  976. # test a corner case that used to fail on x86
  977. i4 = InputArgInt(4)
  978. self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, i4, i4],
  979. 'void', descr=vsdescr)
  980. r = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 4, vsdescr)
  981. assert r == 4
  982. def test_array_of_structs_all_sizes(self):
  983. # x86 has special support that can be used for sizes
  984. # 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 40, 64, 72
  985. for length in range(1, 75):
  986. ITEM = lltype.FixedSizeArray(lltype.Char, length)
  987. a_box, A = self.alloc_array_of(ITEM, 5)
  988. a = lltype.cast_opaque_ptr(lltype.Ptr(A), a_box.getref_base())
  989. middle = length // 2
  990. a[3][middle] = chr(65 + length)
  991. fdescr = self.cpu.interiorfielddescrof(A, 'item%d' % middle)
  992. r = self.execute_operation(rop.GETINTERIORFIELD_GC_I,
  993. [a_box, InputArgInt(3)],
  994. 'int', descr=fdescr)
  995. assert r == 65 + length
  996. self.execute_operation(rop.SETINTERIORFIELD_GC,
  997. [a_box, InputArgInt(2), InputArgInt(r + 1)],
  998. 'void', descr=fdescr)
  999. r1 = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 2,
  1000. fdescr)
  1001. assert r1 == r + 1
  1002. def test_string_basic(self):
  1003. s_box = self.alloc_string("hello\xfe")
  1004. r = self.execute_operation(rop.STRLEN, [s_box], 'int')
  1005. assert r == 6
  1006. r = self.execute_operation(rop.STRGETITEM, [s_box, InputArgInt(5)], 'int')
  1007. assert r == 254
  1008. r = self.execute_operation(rop.STRSETITEM, [s_box, InputArgInt(4),
  1009. InputArgInt(153)], 'void')
  1010. assert r is None
  1011. r = self.execute_operation(rop.STRGETITEM, [s_box, InputArgInt(5)], 'int')
  1012. assert r == 254
  1013. r = self.execute_operation(rop.STRGETITEM, [s_box, InputArgInt(4)], 'int')
  1014. assert r == 153
  1015. def test_copystrcontent(self):
  1016. s_box = self.alloc_string("abcdef")
  1017. for s_box in [s_box, wrap_constant(s_box.getref_base())]:
  1018. for srcstart_box in [InputArgInt(2), ConstInt(2)]:
  1019. for dststart_box in [InputArgInt(3), ConstInt(3)]:
  1020. for length_box in [InputArgInt(4), ConstInt(4)]:
  1021. for r_box_is_const in [False, True]:

Large files files are truncated, but you can click here to view the full file