PageRenderTime 49ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py

https://bitbucket.org/pypy/pypy/
Python | 1436 lines | 1389 code | 38 blank | 9 comment | 17 complexity | 7fc9d1aaedc3c0e9c1e7f816024c5a4a MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0

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

  1. from __future__ import with_statement
  2. import py
  3. from rpython.jit.metainterp.optimizeopt.virtualstate import VirtualStateInfo,\
  4. VStructStateInfo, LEVEL_CONSTANT,\
  5. VArrayStateInfo, not_virtual, VirtualState,\
  6. GenerateGuardState, VirtualStatesCantMatch, VArrayStructStateInfo
  7. from rpython.jit.metainterp.history import ConstInt, ConstPtr, TargetToken
  8. from rpython.jit.metainterp.resoperation import InputArgInt, InputArgRef,\
  9. InputArgFloat
  10. from rpython.jit.backend.llgraph.runner import ArrayDescr
  11. from rpython.rtyper.lltypesystem import lltype, llmemory
  12. from rpython.rtyper import rclass
  13. from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin, BaseTest, \
  14. equaloplists
  15. from rpython.jit.metainterp.optimizeopt.intutils import IntBound,\
  16. ConstIntBound, IntLowerBound, IntUpperBound, IntUnbounded
  17. from rpython.jit.metainterp.history import TreeLoop, JitCellToken
  18. from rpython.jit.metainterp.optimizeopt.test.test_optimizeopt import FakeMetaInterpStaticData
  19. from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
  20. from rpython.jit.metainterp.resoperation import ResOperation, rop
  21. from rpython.jit.metainterp import resume, compile
  22. from rpython.jit.metainterp.optimizeopt import info
  23. from rpython.jit.tool import oparser
  24. class FakeOptimizer(Optimizer):
  25. def __init__(self, cpu):
  26. self.cpu = cpu
  27. self.optearlyforce = None
  28. class BaseTestGenerateGuards(BaseTest):
  29. def setup_class(self):
  30. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  31. value = info.InstancePtrInfo(None, classbox)
  32. self.knownclass_info = not_virtual(self.cpu, 'r', value)
  33. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
  34. value = info.InstancePtrInfo(None, classbox)
  35. self.knownclass_info2 = not_virtual(self.cpu, 'r', value)
  36. def guards(self, info1, info2, box, runtime_box, expected, inputargs=None):
  37. if inputargs is None:
  38. inputargs = [box]
  39. info1.position = info2.position = 0
  40. state = GenerateGuardState(FakeOptimizer(self.cpu))
  41. info1.generate_guards(info2, box, runtime_box, state)
  42. self.compare(state.extra_guards, expected, inputargs)
  43. def compare(self, guards, expected, inputargs):
  44. loop = self.parse(expected)
  45. boxmap = {}
  46. assert len(loop.inputargs) == len(inputargs)
  47. for a, b in zip(loop.inputargs, inputargs):
  48. boxmap[a] = b
  49. for op in loop.operations:
  50. if op.is_guard():
  51. op.setdescr(None)
  52. assert equaloplists(guards, loop.operations, False,
  53. boxmap)
  54. def check_no_guards(self, info1, info2, box=None, opinfo=None, state=None):
  55. if info1.position == -1:
  56. info1.position = 0
  57. if info2.position == -1:
  58. info2.position = 0
  59. if state is None:
  60. state = GenerateGuardState(FakeOptimizer(self.cpu))
  61. info1.generate_guards(info2, box, opinfo, state)
  62. assert not state.extra_guards
  63. return state
  64. def check_invalid(self, info1, info2, box=None, opinfo=None, state=None):
  65. if info1.position == -1:
  66. info1.position = 0
  67. if info2.position == -1:
  68. info2.position = 0
  69. if state is None:
  70. state = GenerateGuardState(FakeOptimizer(self.cpu))
  71. with py.test.raises(VirtualStatesCantMatch):
  72. info1.generate_guards(info2, box, opinfo, state)
  73. def test_make_inputargs(self):
  74. optimizer = FakeOptimizer(self.cpu)
  75. args = [InputArgInt()]
  76. info0 = not_virtual(self.cpu, args[0].type, None)
  77. vs = VirtualState([info0])
  78. assert vs.make_inputargs(args, optimizer) == args
  79. info0.level = LEVEL_CONSTANT
  80. vs = VirtualState([info0])
  81. assert vs.make_inputargs(args, optimizer) == []
  82. def test_position_generalization(self):
  83. def postest(info1, info2):
  84. info1.position = 0
  85. self.check_no_guards(info1, info1)
  86. info2.position = 0
  87. self.check_no_guards(info1, info2)
  88. info2.position = 1
  89. state = self.check_no_guards(info1, info2)
  90. assert state.renum == {0:1}
  91. assert self.check_no_guards(info1, info2, state=state)
  92. # feed fake renums
  93. state.renum = {1: 1}
  94. self.check_no_guards(info1, info2, state=state)
  95. state.renum = {0: 0}
  96. self.check_invalid(info1, info2, state=state)
  97. assert info1 in state.bad and info2 in state.bad
  98. for BoxType in (InputArgInt, InputArgFloat, InputArgRef):
  99. info1 = not_virtual(self.cpu, BoxType.type, None)
  100. info2 = not_virtual(self.cpu, BoxType.type, None)
  101. postest(info1, info2)
  102. info1, info2 = VArrayStateInfo(42), VArrayStateInfo(42)
  103. info1.fieldstate = info2.fieldstate = []
  104. postest(info1, info2)
  105. info1, info2 = VStructStateInfo(42, []), VStructStateInfo(42, [])
  106. info1.fieldstate = info2.fieldstate = []
  107. postest(info1, info2)
  108. info1, info2 = VirtualStateInfo(ConstInt(42), []), VirtualStateInfo(ConstInt(42), [])
  109. info1.fieldstate = info2.fieldstate = []
  110. postest(info1, info2)
  111. def test_NotVirtualStateInfo_generalization(self):
  112. def isgeneral(tp1, info1, tp2, info2):
  113. info1 = not_virtual(self.cpu, tp1, info1)
  114. info1.position = 0
  115. info2 = not_virtual(self.cpu, tp2, info2)
  116. info2.position = 0
  117. return VirtualState([info1]).generalization_of(VirtualState([info2]), FakeOptimizer(self.cpu))
  118. assert isgeneral('i', None, 'i', ConstIntBound(7))
  119. assert not isgeneral('i', ConstIntBound(7), 'i', None)
  120. ptr = info.PtrInfo()
  121. nonnull = info.NonNullPtrInfo()
  122. clsbox = self.cpu.ts.cls_of_box(InputArgRef(self.myptr))
  123. knownclass = info.InstancePtrInfo(known_class=clsbox)
  124. const = info.ConstPtrInfo(ConstPtr(self.myptr))
  125. inorder = [ptr, nonnull, knownclass, const]
  126. for i in range(len(inorder)):
  127. for j in range(i, len(inorder)):
  128. assert isgeneral('r', inorder[i], 'r', inorder[j])
  129. if i != j:
  130. assert not isgeneral('r', inorder[j], 'r', inorder[i])
  131. i1 = IntUnbounded()
  132. i2 = IntLowerBound(10)
  133. assert isgeneral('i', i1, 'i', i2)
  134. assert not isgeneral('i', i2, 'i', i1)
  135. assert isgeneral('i', ConstIntBound(7), 'i', ConstIntBound(7))
  136. S = lltype.GcStruct('S', ('parent', rclass.OBJECT))
  137. foo = lltype.malloc(S)
  138. foo_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
  139. foo.parent.typeptr = foo_vtable
  140. fooref = lltype.cast_opaque_ptr(llmemory.GCREF, foo)
  141. assert isgeneral('r', info.ConstPtrInfo(ConstPtr(fooref)),
  142. 'r', info.ConstPtrInfo(ConstPtr(fooref)))
  143. value1 = info.NonNullPtrInfo()
  144. value2 = info.ConstPtrInfo(ConstPtr(self.nullptr))
  145. assert not isgeneral('r', value1, 'r', value2)
  146. def test_field_matching_generalization(self):
  147. const1 = not_virtual(self.cpu, 'i', ConstIntBound(1))
  148. const2 = not_virtual(self.cpu, 'i', ConstIntBound(2))
  149. const1.position = const2.position = 1
  150. self.check_invalid(const1, const2)
  151. self.check_invalid(const2, const1)
  152. def fldtst(info1, info2):
  153. info1.position = info2.position = 0
  154. info1.fieldstate = [const1]
  155. info2.fieldstate = [const2]
  156. self.check_invalid(info1, info2)
  157. self.check_invalid(info2, info1)
  158. self.check_no_guards(info1, info1)
  159. self.check_no_guards(info2, info2)
  160. class FieldDescr:
  161. def get_index(self):
  162. return 0
  163. fielddescr = FieldDescr()
  164. fakedescr = object()
  165. fldtst(VArrayStateInfo(fakedescr), VArrayStateInfo(fakedescr))
  166. fldtst(VStructStateInfo(fakedescr, [fielddescr]), VStructStateInfo(fakedescr, [fielddescr]))
  167. fldtst(VirtualStateInfo(ConstInt(42), [fielddescr]), VirtualStateInfo(ConstInt(42), [fielddescr]))
  168. fldtst(VArrayStructStateInfo(fakedescr, [fielddescr], 1), VArrayStructStateInfo(fakedescr, [fielddescr], 1))
  169. def test_known_class_generalization(self):
  170. knownclass1 = info.InstancePtrInfo(None, ConstPtr(self.myptr))
  171. info1 = not_virtual(self.cpu, 'r', knownclass1)
  172. info1.position = 0
  173. knownclass2 = info.InstancePtrInfo(None, ConstPtr(self.myptr))
  174. info2 = not_virtual(self.cpu, 'r', knownclass2)
  175. info2.position = 0
  176. self.check_no_guards(info1, info2)
  177. self.check_no_guards(info2, info1)
  178. knownclass3 = info.InstancePtrInfo(None, ConstPtr(self.myptr2))
  179. info3 = not_virtual(self.cpu, 'r', knownclass3)
  180. info3.position = 0
  181. self.check_invalid(info1, info3)
  182. self.check_invalid(info2, info3)
  183. self.check_invalid(info3, info2)
  184. self.check_invalid(info3, info1)
  185. def test_circular_generalization(self):
  186. for info in (VArrayStateInfo(42), VStructStateInfo(42, [7]),
  187. VirtualStateInfo(ConstInt(42), [7])):
  188. info.position = 0
  189. info.fieldstate = [info]
  190. self.check_no_guards(info, info)
  191. def test_generate_guards_nonvirtual_all_combinations(self):
  192. # set up infos
  193. #unknown_val = PtrOptValue(self.nodebox)
  194. #unknownnull_val = PtrOptValue(BoxPtr(self.nullptr))
  195. opt = FakeOptimizer(self.cpu)
  196. unknown_info = not_virtual(self.cpu, 'r', None)
  197. nonnull_info = not_virtual(self.cpu, 'r', info.NonNullPtrInfo())
  198. classbox1 = self.cpu.ts.cls_of_box(ConstPtr(self.nodeaddr))
  199. knownclass_info = not_virtual(self.cpu, 'r',
  200. info.InstancePtrInfo(None, classbox1))
  201. classbox2 = self.cpu.ts.cls_of_box(ConstPtr(self.node2addr))
  202. knownclass2_info = not_virtual(self.cpu, 'r',
  203. info.InstancePtrInfo(None, classbox2))
  204. constant_info = not_virtual(self.cpu, 'i',
  205. ConstIntBound(1))
  206. constant_ptr_info = not_virtual(self.cpu, 'r',
  207. info.ConstPtrInfo(ConstPtr(self.nodeaddr)))
  208. constclass_val = info.ConstPtrInfo(ConstPtr(self.nodeaddr))
  209. constclass_info = not_virtual(self.cpu, 'r', constclass_val)
  210. constclass2_info = not_virtual(self.cpu, 'r',
  211. info.ConstPtrInfo(ConstPtr(self.node2addr)))
  212. constantnull_info = not_virtual(self.cpu, 'r',
  213. info.ConstPtrInfo(ConstPtr(self.nullptr)))
  214. # unknown unknown
  215. self.check_no_guards(unknown_info, unknown_info)
  216. self.check_no_guards(unknown_info, unknown_info,
  217. InputArgRef(), info.PtrInfo())
  218. # unknown nonnull
  219. self.check_no_guards(unknown_info, nonnull_info,
  220. InputArgRef(), info.NonNullPtrInfo())
  221. self.check_no_guards(unknown_info, nonnull_info)
  222. # unknown knownclass
  223. self.check_no_guards(unknown_info, knownclass_info,
  224. InputArgRef(), info.InstancePtrInfo(None, classbox1))
  225. self.check_no_guards(unknown_info, knownclass_info)
  226. # unknown constant
  227. unknown_info_int = not_virtual(self.cpu, 'i', None)
  228. self.check_no_guards(unknown_info_int, constant_info,
  229. ConstInt(1), ConstIntBound(1))
  230. self.check_no_guards(unknown_info_int, constant_info)
  231. # nonnull unknown
  232. expected = """
  233. [p0]
  234. guard_nonnull(p0) []
  235. """
  236. nonnullbox = InputArgRef(self.nodeaddr)
  237. nonnullbox2 = InputArgRef(self.node2addr)
  238. knownclassopinfo = info.InstancePtrInfo(None, classbox1)
  239. knownclass2opinfo = info.InstancePtrInfo(None, classbox2)
  240. self.guards(nonnull_info, unknown_info, nonnullbox,
  241. nonnullbox, expected)
  242. self.check_invalid(nonnull_info, unknown_info, InputArgRef(), None)
  243. self.check_invalid(nonnull_info, unknown_info)
  244. self.check_invalid(nonnull_info, unknown_info)
  245. # nonnull nonnull
  246. self.check_no_guards(nonnull_info, nonnull_info, nonnullbox, None)
  247. self.check_no_guards(nonnull_info, nonnull_info, nonnullbox, None)
  248. # nonnull knownclass
  249. self.check_no_guards(nonnull_info, knownclass_info, nonnullbox,
  250. info.InstancePtrInfo(None, classbox1))
  251. self.check_no_guards(nonnull_info, knownclass_info)
  252. # nonnull constant
  253. const_nonnull = ConstPtr(self.nodeaddr)
  254. const_nonnull2 = ConstPtr(self.node2addr)
  255. const_null = ConstPtr(lltype.nullptr(llmemory.GCREF.TO))
  256. self.check_no_guards(nonnull_info, constant_ptr_info, const_nonnull,
  257. info.ConstPtrInfo(const_nonnull))
  258. self.check_invalid(nonnull_info, constantnull_info, const_null,
  259. info.ConstPtrInfo(const_null))
  260. self.check_no_guards(nonnull_info, constant_ptr_info)
  261. self.check_invalid(nonnull_info, constantnull_info)
  262. # knownclass unknown
  263. expected = """
  264. [p0]
  265. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  266. """
  267. self.guards(knownclass_info, unknown_info, InputArgRef(self.nodeaddr),
  268. InputArgRef(self.nodeaddr), expected)
  269. self.check_invalid(knownclass_info, unknown_info, InputArgRef(), None)
  270. self.check_invalid(knownclass_info, unknown_info,
  271. InputArgRef(self.node2addr),
  272. InputArgRef(self.node2addr))
  273. self.check_invalid(knownclass_info, unknown_info)
  274. self.check_invalid(knownclass_info, unknown_info)
  275. self.check_invalid(knownclass_info, unknown_info)
  276. # knownclass nonnull
  277. expected = """
  278. [p0]
  279. guard_class(p0, ConstClass(node_vtable)) []
  280. """
  281. self.guards(knownclass_info, nonnull_info, InputArgRef(self.nodeaddr),
  282. InputArgRef(self.nodeaddr), expected)
  283. self.check_invalid(knownclass_info, nonnull_info,
  284. InputArgRef(self.node2addr), None)
  285. self.check_invalid(knownclass_info, nonnull_info)
  286. self.check_invalid(knownclass_info, nonnull_info)
  287. # knownclass knownclass
  288. self.check_no_guards(knownclass_info, knownclass_info,
  289. nonnullbox, knownclassopinfo)
  290. self.check_invalid(knownclass_info, knownclass2_info,
  291. nonnullbox2, knownclass2opinfo)
  292. self.check_no_guards(knownclass_info, knownclass_info)
  293. self.check_invalid(knownclass_info, knownclass2_info)
  294. # knownclass constant
  295. self.check_invalid(knownclass_info, constantnull_info,
  296. const_null, info.ConstPtrInfo(const_null))
  297. self.check_invalid(knownclass_info, constclass2_info, const_nonnull2,
  298. info.ConstPtrInfo(const_nonnull2))
  299. self.check_invalid(knownclass_info, constantnull_info)
  300. self.check_invalid(knownclass_info, constclass2_info)
  301. # constant unknown
  302. expected = """
  303. [i0]
  304. guard_value(i0, 1) []
  305. """
  306. self.guards(constant_info, unknown_info, InputArgInt(),
  307. InputArgInt(1), expected)
  308. self.check_invalid(constant_info, unknown_info, InputArgRef(), None)
  309. self.check_invalid(constant_info, unknown_info)
  310. self.check_invalid(constant_info, unknown_info)
  311. # constant nonnull
  312. expected = """
  313. [i0]
  314. guard_value(i0, 1) []
  315. """
  316. self.guards(constant_info, nonnull_info, ConstInt(1),
  317. ConstInt(1), expected)
  318. self.check_invalid(constant_info, nonnull_info,
  319. ConstInt(3), ConstInt(3))
  320. self.check_invalid(constant_info, nonnull_info)
  321. self.check_invalid(constant_info, nonnull_info)
  322. # constant knownclass
  323. expected = """
  324. [p0]
  325. guard_value(p0, ConstPtr(nodeaddr)) []
  326. """
  327. self.guards(constant_ptr_info, knownclass_info,
  328. const_nonnull, const_nonnull, expected)
  329. self.check_invalid(constant_info, knownclass_info, InputArgRef())
  330. self.check_invalid(constant_info, knownclass_info)
  331. self.check_invalid(constant_info, knownclass_info)
  332. # constant constant
  333. self.check_no_guards(constant_info, constant_info,
  334. ConstInt(1), ConstIntBound(1))
  335. self.check_invalid(constant_info, constantnull_info,
  336. const_null, info.ConstPtrInfo(const_null))
  337. self.check_no_guards(constant_info, constant_info)
  338. self.check_invalid(constant_info, constantnull_info)
  339. def test_intbounds(self):
  340. value1 = IntUnbounded()
  341. value1.make_ge(IntBound(0, 10))
  342. value1.make_le(IntBound(20, 30))
  343. info1 = not_virtual(self.cpu, 'i', value1)
  344. info2 = not_virtual(self.cpu, 'i', IntUnbounded())
  345. expected = """
  346. [i0]
  347. i1 = int_ge(i0, 0)
  348. guard_true(i1) []
  349. i2 = int_le(i0, 30)
  350. guard_true(i2) []
  351. """
  352. self.guards(info1, info2, InputArgInt(), InputArgInt(15), expected)
  353. self.check_invalid(info1, info2, InputArgInt(50), InputArgInt(50))
  354. def test_intbounds_constant(self):
  355. value1 = IntUnbounded()
  356. value1.make_ge(IntBound(0, 10))
  357. value1.make_le(IntBound(20, 30))
  358. info1 = not_virtual(self.cpu, 'i', value1)
  359. info2 = not_virtual(self.cpu, 'i', ConstIntBound(10000))
  360. self.check_invalid(info1, info2)
  361. info1 = not_virtual(self.cpu, 'i', value1)
  362. info2 = not_virtual(self.cpu, 'i', ConstIntBound(11))
  363. self.check_no_guards(info1, info2)
  364. def test_known_class(self):
  365. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  366. value1 = info.InstancePtrInfo(None, classbox)
  367. info1 = not_virtual(self.cpu, 'r', value1)
  368. info2 = not_virtual(self.cpu, 'r', None)
  369. expected = """
  370. [p0]
  371. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  372. """
  373. self.guards(info1, info2, InputArgRef(),
  374. InputArgRef(self.nodeaddr), expected)
  375. self.check_invalid(info1, info2, InputArgRef())
  376. def test_known_class_value(self):
  377. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  378. value1 = info.InstancePtrInfo(None, classbox)
  379. box = InputArgRef()
  380. guards = []
  381. value1.make_guards(box, guards, FakeOptimizer(self.cpu))
  382. expected = """
  383. [p0]
  384. guard_nonnull(p0) []
  385. guard_is_object(p0) []
  386. guard_class(p0, ConstClass(node_vtable)) []
  387. """
  388. self.compare(guards, expected, [box])
  389. def test_known_value(self):
  390. value1 = ConstIntBound(1)
  391. box = InputArgInt()
  392. guards = []
  393. value1.make_guards(box, guards, FakeOptimizer(self.cpu))
  394. expected = """
  395. [i0]
  396. guard_value(i0, 1) []
  397. """
  398. self.compare(guards, expected, [box])
  399. def test_equal_inputargs(self):
  400. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  401. value = info.InstancePtrInfo(None, classbox)
  402. knownclass_info = not_virtual(self.cpu, 'r', value)
  403. vstate1 = VirtualState([knownclass_info, knownclass_info])
  404. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  405. unknown_info1 = not_virtual(self.cpu, 'r', None)
  406. vstate2 = VirtualState([unknown_info1, unknown_info1])
  407. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  408. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  409. assert vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  410. unknown_info1 = not_virtual(self.cpu, 'r', None)
  411. unknown_info2 = not_virtual(self.cpu, 'r', None)
  412. vstate3 = VirtualState([unknown_info1, unknown_info2])
  413. assert vstate3.generalization_of(vstate2, FakeOptimizer(self.cpu))
  414. assert vstate3.generalization_of(vstate1, FakeOptimizer(self.cpu))
  415. assert not vstate2.generalization_of(vstate3, FakeOptimizer(self.cpu))
  416. assert not vstate1.generalization_of(vstate3, FakeOptimizer(self.cpu))
  417. expected = """
  418. [p0]
  419. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  420. """
  421. box = InputArgRef(self.nodeaddr)
  422. state = vstate1.generate_guards(vstate2, [box, box], [box, box],
  423. FakeOptimizer(self.cpu))
  424. self.compare(state.extra_guards, expected, [box])
  425. with py.test.raises(VirtualStatesCantMatch):
  426. vstate1.generate_guards(vstate3, [box, box], [None, None],
  427. FakeOptimizer(self.cpu))
  428. with py.test.raises(VirtualStatesCantMatch):
  429. vstate2.generate_guards(vstate3, [box, box], [None, None],
  430. FakeOptimizer(self.cpu))
  431. def test_generate_guards_on_virtual_fields_matches_array(self):
  432. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  433. innervalue1 = info.InstancePtrInfo(None, classbox)
  434. innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
  435. innerinfo1.position = 1
  436. innerinfo2 = not_virtual(self.cpu, 'r', None)
  437. innerinfo2.position = 1
  438. descr = ArrayDescr(lltype.GcArray(llmemory.GCREF), self.cpu)
  439. info1 = VArrayStateInfo(descr)
  440. info1.fieldstate = [innerinfo1]
  441. info2 = VArrayStateInfo(descr)
  442. info2.fieldstate = [innerinfo2]
  443. value1 = info.ArrayPtrInfo(descr, size=1, is_virtual=True)
  444. box = InputArgRef(self.nodeaddr)
  445. value1._items[0] = box
  446. expected = """
  447. [p0]
  448. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  449. """
  450. array = lltype.malloc(lltype.GcArray(llmemory.GCREF), 1)
  451. array[0] = self.nodeaddr
  452. arrayaddr = lltype.cast_opaque_ptr(llmemory.GCREF, array)
  453. runtime_box = InputArgRef(arrayaddr)
  454. runtime_box._forwarded = value1
  455. self.guards(info1, info2, runtime_box, runtime_box, expected, [box])
  456. def test_generate_guards_on_virtual_fields_matches_instance(self):
  457. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  458. innervalue1 = info.InstancePtrInfo(None, classbox)
  459. innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
  460. innerinfo1.position = 1
  461. innerinfo2 = not_virtual(self.cpu, 'r', None)
  462. innerinfo2.position = 1
  463. info1 = VirtualStateInfo(ConstInt(42), [self.nextdescr])
  464. info1.fieldstate = [innerinfo1]
  465. info2 = VirtualStateInfo(ConstInt(42), [self.nextdescr])
  466. info2.fieldstate = [innerinfo2]
  467. value1 = info.InstancePtrInfo(self.nodesize, classbox, is_virtual=True)
  468. nodebox = InputArgRef(self.nodeaddr)
  469. node2box = InputArgRef(self.nodeaddr)
  470. value1._fields = [None] * (self.nextdescr.get_index() + 1)
  471. value1._fields[self.nextdescr.get_index()] = node2box
  472. expected = """
  473. [p0]
  474. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  475. """
  476. runtime_box = InputArgRef(self.nodeaddr)
  477. nodebox._forwarded = value1
  478. self.guards(info1, info2, nodebox, runtime_box, expected, [node2box])
  479. def test_generate_guards_on_virtual_fields_matches_struct(self):
  480. constclassbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  481. innervalue1 = info.InstancePtrInfo(None, constclassbox)
  482. innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
  483. innerinfo1.position = 1
  484. innerinfo2 = not_virtual(self.cpu, 'r', None)
  485. innerinfo2.position = 1
  486. structdescr = self.nodesize
  487. info1 = VStructStateInfo(structdescr, [self.nextdescr])
  488. info1.fieldstate = [innerinfo1]
  489. info2 = VStructStateInfo(structdescr, [self.nextdescr])
  490. info2.fieldstate = [innerinfo2]
  491. node2box = InputArgRef(self.nodeaddr)
  492. value1 = info.InstancePtrInfo(structdescr, None, is_virtual=True)
  493. value1._fields = [None] * (self.nextdescr.get_index() + 1)
  494. value1._fields[self.nextdescr.get_index()] = node2box
  495. expected = """
  496. [p0]
  497. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  498. """
  499. nodebox = InputArgRef(self.nodeaddr)
  500. nodebox._forwarded = value1
  501. runtime_box = InputArgRef(self.nodeaddr)
  502. self.guards(info1, info2, nodebox, runtime_box, expected,
  503. [node2box])
  504. def test_generate_guards_on_virtual_fields_matches_arraystruct(self):
  505. constclassbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  506. innervalue1 = info.InstancePtrInfo(None, constclassbox)
  507. innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
  508. innerinfo1.position = 1
  509. innerinfo2 = not_virtual(self.cpu, 'r', None)
  510. innerinfo2.position = 1
  511. NODE = lltype.Struct('NODE', ('x', llmemory.GCREF))
  512. ARRAY = lltype.GcArray(NODE)
  513. descr = self.cpu.fielddescrof(NODE, 'x')
  514. arraydescr = self.cpu.arraydescrof(ARRAY)
  515. info1 = VArrayStructStateInfo(arraydescr, [descr], 1)
  516. info1.fieldstate = [innerinfo1]
  517. info2 = VArrayStructStateInfo(arraydescr, [descr], 1)
  518. info2.fieldstate = [innerinfo2]
  519. node = lltype.malloc(ARRAY, 1)
  520. node[0].x = self.nodeaddr
  521. nodeaddr = lltype.cast_opaque_ptr(llmemory.GCREF, node)
  522. node2box = InputArgRef(self.nodeaddr)
  523. value1 = info.ArrayStructInfo(arraydescr, 1, is_virtual=True)
  524. value1._items = [node2box]
  525. expected = """
  526. [p0]
  527. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  528. """
  529. nodebox = InputArgRef(self.nodeaddr)
  530. nodebox._forwarded = value1
  531. runtime_box = InputArgRef(nodeaddr)
  532. self.guards(info1, info2, nodebox, runtime_box, expected,
  533. [node2box])
  534. # _________________________________________________________________________
  535. # the below tests don't really have anything to do with guard generation
  536. def test_virtuals_with_equal_fields(self):
  537. info1 = VirtualStateInfo(ConstInt(42), [1, 2])
  538. info1.fieldstate = [self.knownclass_info, self.knownclass_info]
  539. vstate1 = VirtualState([info1])
  540. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  541. info2 = VirtualStateInfo(ConstInt(42), [1, 2])
  542. unknown_info1 = not_virtual(self.cpu, 'r',
  543. info.InstancePtrInfo())
  544. info2.fieldstate = [unknown_info1, unknown_info1]
  545. vstate2 = VirtualState([info2])
  546. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  547. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  548. assert vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  549. info3 = VirtualStateInfo(ConstInt(42), [1, 2])
  550. unknown_info1 = not_virtual(self.cpu, 'r',
  551. info.InstancePtrInfo())
  552. unknown_info2 = not_virtual(self.cpu, 'r',
  553. info.InstancePtrInfo())
  554. info3.fieldstate = [unknown_info1, unknown_info2]
  555. vstate3 = VirtualState([info3])
  556. assert vstate3.generalization_of(vstate2, FakeOptimizer(self.cpu))
  557. assert vstate3.generalization_of(vstate1, FakeOptimizer(self.cpu))
  558. assert not vstate2.generalization_of(vstate3, FakeOptimizer(self.cpu))
  559. assert not vstate1.generalization_of(vstate3, FakeOptimizer(self.cpu))
  560. def test_virtuals_with_nonmatching_fields(self):
  561. info1 = VirtualStateInfo(ConstInt(42), [1, 2])
  562. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  563. value = info.InstancePtrInfo(None, classbox)
  564. knownclass_info = not_virtual(self.cpu, 'r', value)
  565. info1.fieldstate = [knownclass_info, knownclass_info]
  566. vstate1 = VirtualState([info1])
  567. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  568. info2 = VirtualStateInfo(ConstInt(42), [1, 2])
  569. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
  570. value = info.InstancePtrInfo(None, classbox)
  571. knownclass_info = not_virtual(self.cpu, 'r', value)
  572. info2.fieldstate = [knownclass_info, knownclass_info]
  573. vstate2 = VirtualState([info2])
  574. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  575. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  576. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  577. def test_virtuals_with_nonmatching_descrs(self):
  578. info1 = VirtualStateInfo(ConstInt(42), [10, 20])
  579. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  580. value = info.InstancePtrInfo(None, classbox)
  581. knownclass_info = not_virtual(self.cpu, 'r', value)
  582. info1.fieldstate = [knownclass_info, knownclass_info]
  583. vstate1 = VirtualState([info1])
  584. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  585. info2 = VirtualStateInfo(ConstInt(42), [1, 2])
  586. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
  587. value = info.InstancePtrInfo(None, classbox)
  588. knownclass_info = not_virtual(self.cpu, 'r', value)
  589. info2.fieldstate = [knownclass_info, knownclass_info]
  590. vstate2 = VirtualState([info2])
  591. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  592. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  593. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  594. def test_virtuals_with_nonmatching_classes(self):
  595. info1 = VirtualStateInfo(ConstInt(42), [1, 2])
  596. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  597. value = info.InstancePtrInfo(None, classbox)
  598. knownclass_info = not_virtual(self.cpu, 'r', value)
  599. info1.fieldstate = [knownclass_info, knownclass_info]
  600. vstate1 = VirtualState([info1])
  601. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  602. info2 = VirtualStateInfo(ConstInt(7), [1, 2])
  603. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
  604. value = info.InstancePtrInfo(None, classbox)
  605. knownclass_info = not_virtual(self.cpu, 'r', value)
  606. info2.fieldstate = [knownclass_info, knownclass_info]
  607. vstate2 = VirtualState([info2])
  608. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  609. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  610. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  611. def test_nonvirtual_is_not_virtual(self):
  612. info1 = VirtualStateInfo(ConstInt(42), [1, 2])
  613. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  614. value = info.InstancePtrInfo(None, classbox)
  615. knownclass_info = not_virtual(self.cpu, 'r', value)
  616. info1.fieldstate = [knownclass_info, knownclass_info]
  617. vstate1 = VirtualState([info1])
  618. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  619. info2 = not_virtual(self.cpu, 'r', value)
  620. vstate2 = VirtualState([info2])
  621. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  622. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  623. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  624. def test_arrays_with_nonmatching_fields(self):
  625. info1 = VArrayStateInfo(42)
  626. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  627. value = info.InstancePtrInfo(None, classbox)
  628. knownclass_info = not_virtual(self.cpu, 'r', value)
  629. info1.fieldstate = [knownclass_info, knownclass_info]
  630. vstate1 = VirtualState([info1])
  631. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  632. info2 = VArrayStateInfo(42)
  633. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
  634. value = info.InstancePtrInfo(None, classbox)
  635. knownclass_info = not_virtual(self.cpu, 'r', value)
  636. info2.fieldstate = [knownclass_info, knownclass_info]
  637. vstate2 = VirtualState([info2])
  638. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  639. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  640. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  641. def test_arrays_of_different_sizes(self):
  642. info1 = VArrayStateInfo(42)
  643. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  644. value = info.InstancePtrInfo(None, classbox)
  645. knownclass_info = not_virtual(self.cpu, 'r', value)
  646. info1.fieldstate = [knownclass_info, knownclass_info]
  647. vstate1 = VirtualState([info1])
  648. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  649. info2 = VArrayStateInfo(42)
  650. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
  651. value = info.InstancePtrInfo(None, classbox)
  652. knownclass_info = not_virtual(self.cpu, 'r', value)
  653. info2.fieldstate = [knownclass_info]
  654. vstate2 = VirtualState([info2])
  655. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  656. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  657. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  658. def test_arrays_with_nonmatching_types(self):
  659. info1 = VArrayStateInfo(42)
  660. info1.fieldstate = [self.knownclass_info, self.knownclass_info]
  661. vstate1 = VirtualState([info1])
  662. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  663. info2 = VArrayStateInfo(7)
  664. info2.fieldstate = [self.knownclass_info2, self.knownclass_info2]
  665. vstate2 = VirtualState([info2])
  666. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  667. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  668. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  669. def test_nonvirtual_is_not_array(self):
  670. info1 = VArrayStateInfo(42)
  671. info1.fieldstate = [self.knownclass_info, self.knownclass_info]
  672. vstate1 = VirtualState([info1])
  673. assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
  674. vstate2 = VirtualState([self.knownclass_info])
  675. assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
  676. assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
  677. assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
  678. def test_crash_varay_clear(self):
  679. classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
  680. innervalue1 = info.InstancePtrInfo(None, classbox)
  681. innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
  682. innerinfo1.position = 1
  683. innerinfo1.position_in_notvirtuals = 0
  684. descr = self.cpu.arraydescrof(lltype.GcArray(llmemory.GCREF))
  685. info1 = VArrayStateInfo(descr)
  686. info1.fieldstate = [innerinfo1]
  687. value1 = info.ArrayPtrInfo(descr,
  688. ConstPtr(lltype.nullptr(llmemory.GCREF.TO)),
  689. 1, True, is_virtual=True)
  690. value1._items[0] = ConstPtr(lltype.nullptr(llmemory.GCREF.TO))
  691. nodebox = InputArgRef()
  692. nodebox._forwarded = value1
  693. info1.enum_forced_boxes([None], nodebox, FakeOptimizer(self.cpu))
  694. class BaseTestBridges(BaseTest):
  695. enable_opts = "intbounds:rewrite:virtualize:string:pure:earlyforce:heap:unroll"
  696. def _do_optimize_bridge(self, bridge, call_pure_results, values):
  697. from rpython.jit.metainterp.optimizeopt import optimize_trace
  698. from rpython.jit.metainterp.optimizeopt.util import args_dict
  699. self.bridge = bridge
  700. bridge.call_pure_results = args_dict()
  701. if call_pure_results is not None:
  702. for k, v in call_pure_results.items():
  703. bridge.call_pure_results[list(k)] = v
  704. metainterp_sd = FakeMetaInterpStaticData(self.cpu)
  705. if hasattr(self, 'vrefinfo'):
  706. metainterp_sd.virtualref_info = self.vrefinfo
  707. if hasattr(self, 'callinfocollection'):
  708. metainterp_sd.callinfocollection = self.callinfocollection
  709. #
  710. trace = oparser.convert_loop_to_trace(bridge, metainterp_sd)
  711. runtime_boxes = self.convert_values(bridge.operations[-1].getarglist(),
  712. values)
  713. data = compile.BridgeCompileData(trace, runtime_boxes,
  714. enable_opts=self.enable_opts, inline_short_preamble=True)
  715. info, newops = optimize_trace(metainterp_sd, None, data)
  716. if info.final():
  717. bridge.operations = newops
  718. bridge.inputargs = info.inputargs
  719. return info
  720. def optimize_bridge(self, loops, bridge, expected, expected_target='Loop',
  721. boxvalues=None):
  722. if isinstance(loops, str):
  723. loops = (loops, )
  724. loops = [self.parse(loop)
  725. for loop in loops]
  726. bridge = self.parse(bridge)
  727. self.add_guard_future_condition(bridge)
  728. token = JitCellToken()
  729. for loop in loops:
  730. info = self.unroll_and_optimize(loop)
  731. loop.preamble = info.preamble
  732. loop.preamble.operations[0].setdescr(TargetToken(token))
  733. preamble = loops[0].preamble
  734. token.target_tokens = [l.operations[0].getdescr() for l in [preamble] + loops]
  735. boxes = {}
  736. for b in bridge.inputargs + [op for op in bridge.operations]:
  737. boxes[str(b)] = b
  738. bridge.operations[-1].setdescr(token)
  739. info = self._do_optimize_bridge(bridge, None, boxvalues)
  740. if not info.final():
  741. assert expected == 'RETRACE'
  742. return
  743. print '\n'.join([str(o) for o in bridge.operations])
  744. expected = self.parse(expected)
  745. self.assert_equal(bridge, expected)
  746. if expected_target == 'Preamble':
  747. assert bridge.operations[-1].getdescr() is preamble.operations[0].getdescr()
  748. elif expected_target == 'Loop':
  749. assert len(loops) == 1
  750. assert bridge.operations[-1].getdescr() is loops[0].operations[0].getdescr()
  751. elif expected_target.startswith('Loop'):
  752. n = int(expected_target[4:])
  753. assert bridge.operations[-1].getdescr() is loops[n].operations[0].getdescr()
  754. else:
  755. assert False
  756. def test_nonnull(self):
  757. loop = """
  758. [p0]
  759. p1 = getfield_gc_r(p0, descr=nextdescr)
  760. jump(p0)
  761. """
  762. bridge = """
  763. [p0]
  764. jump(p0)
  765. """
  766. expected = """
  767. [p0]
  768. guard_nonnull(p0) []
  769. guard_is_object(p0) []
  770. guard_subclass(p0, ConstClass(node_vtable)) []
  771. p1 = getfield_gc_r(p0, descr=nextdescr)
  772. jump(p0)
  773. """
  774. self.optimize_bridge(loop, bridge, expected, 'Loop', [self.myptr])
  775. self.optimize_bridge(loop, expected, expected, 'Loop', [self.myptr])
  776. self.optimize_bridge(loop, expected, expected, 'Loop', [self.nullptr])
  777. self.optimize_bridge(loop, bridge, 'RETRACE', 'Loop', [self.nullptr])
  778. def test_cached_nonnull(self):
  779. loop = """
  780. [p0]
  781. p1 = getfield_gc_r(p0, descr=nextdescr)
  782. guard_nonnull(p1) []
  783. call_n(p1, descr=nonwritedescr)
  784. jump(p0)
  785. """
  786. bridge = """
  787. [p0]
  788. jump(p0)
  789. """
  790. expected = """
  791. [p0]
  792. guard_nonnull(p0) []
  793. guard_is_object(p0) []
  794. guard_subclass(p0, ConstClass(node_vtable)) []
  795. p1 = getfield_gc_r(p0, descr=nextdescr)
  796. guard_nonnull(p1) []
  797. jump(p0, p1)
  798. """
  799. self.optimize_bridge(loop, bridge, expected, boxvalues=[self.myptr])
  800. def test_cached_unused_nonnull(self):
  801. loop = """
  802. [p0]
  803. p1 = getfield_gc_r(p0, descr=nextdescr)
  804. guard_nonnull(p1) []
  805. jump(p0)
  806. """
  807. bridge = """
  808. [p0]
  809. jump(p0)
  810. """
  811. expected = """
  812. [p0]
  813. guard_nonnull(p0) []
  814. guard_is_object(p0) []
  815. guard_subclass(p0, ConstClass(node_vtable)) []
  816. p1 = getfield_gc_r(p0, descr=nextdescr)
  817. guard_nonnull(p1) []
  818. jump(p0)
  819. """
  820. self.optimize_bridge(loop, bridge, expected, boxvalues=[self.myptr])
  821. def test_cached_invalid_nonnull(self):
  822. loop = """
  823. [p0]
  824. p1 = getfield_gc_r(p0, descr=nextdescr)
  825. guard_nonnull(p1) []
  826. jump(p0)
  827. """
  828. bridge = """
  829. [p0]
  830. p1 = getfield_gc_r(p0, descr=nextdescr)
  831. guard_value(p1, ConstPtr(nullptr)) []
  832. jump(p0)
  833. """
  834. self.optimize_bridge(loop, bridge, bridge, 'Preamble',
  835. boxvalues=[self.myptr])
  836. def test_multiple_nonnull(self):
  837. loops = """
  838. [p0]
  839. p1 = getfield_gc_r(p0, descr=nextdescr)
  840. jump(p0)
  841. """, """
  842. [p0]
  843. jump(p0)
  844. """
  845. bridge = """
  846. [p0]
  847. jump(p0)
  848. """
  849. expected = """
  850. [p0]
  851. jump(p0)
  852. """
  853. self.optimize_bridge(loops, bridge, expected, 'Loop1', [self.nullptr])
  854. expected = """
  855. [p0]
  856. guard_nonnull(p0) []
  857. guard_is_object(p0) []
  858. guard_subclass(p0, ConstClass(node_vtable)) []
  859. p1 = getfield_gc_r(p0, descr=nextdescr)
  860. jump(p0)
  861. """
  862. self.optimize_bridge(loops, bridge, expected, 'Loop0', [self.myptr])
  863. def test_constant(self):
  864. loops = """
  865. [i0]
  866. i1 = same_as_i(1)
  867. jump(i1)
  868. """, """
  869. [i0]
  870. i1 = same_as_i(2)
  871. jump(i1)
  872. """, """
  873. [i0]
  874. jump(i0)
  875. """
  876. expected = """
  877. [i0]
  878. jump()
  879. """
  880. self.optimize_bridge(loops, loops[0], expected, 'Loop0')
  881. self.optimize_bridge(loops, loops[1], expected, 'Loop1')
  882. expected = """
  883. [i0]
  884. jump(i0)
  885. """
  886. self.optimize_bridge(loops, loops[2], expected, 'Loop2')
  887. def test_cached_constant(self):
  888. loop = """
  889. [p0]
  890. p1 = getfield_gc_r(p0, descr=nextdescr)
  891. guard_value(p1, ConstPtr(myptr)) []
  892. jump(p0)
  893. """
  894. bridge = """
  895. [p0]
  896. jump(p0)
  897. """
  898. expected = """
  899. [p0]
  900. guard_nonnull(p0) []
  901. guard_is_object(p0) []
  902. guard_subclass(p0, ConstClass(node_vtable)) []
  903. p1 = getfield_gc_r(p0, descr=nextdescr)
  904. guard_value(p1, ConstPtr(myptr)) []
  905. jump(p0)
  906. """
  907. self.optimize_bridge(loop, bridge, expected, 'Loop', [self.myptr])
  908. def test_simple_virtual(self):
  909. loops = """
  910. [p0, p1]
  911. p2 = new_with_vtable(descr=nodesize)
  912. setfield_gc(p2, p1, descr=nextdescr)
  913. setfield_gc(p2, 7, descr=adescr)
  914. setfield_gc(p2, 42, descr=bdescr)
  915. jump(p2, p1)
  916. ""","""
  917. [p0, p1]
  918. p2 = new_with_vtable(descr=nodesize)
  919. setfield_gc(p2, p1, descr=nextdescr)
  920. setfield_gc(p2, 9, descr=adescr)
  921. jump(p2, p1)
  922. """
  923. expected = """
  924. [p0, p1]
  925. jump(p1)
  926. """
  927. ptr0 = lltype.malloc(self.NODE, zero=True)
  928. self.optimize_bridge(loops, loops[0], expected, 'Loop0', [ptr0, None])
  929. self.optimize_bridge(loops, loops[1], expected, 'Loop1', [ptr0, None])
  930. bridge = """
  931. [p0, p1]
  932. p2 = new_with_vtable(descr=nodesize)
  933. setfield_gc(p2, p1, descr=nextdescr)
  934. setfield_gc(p2, 42, descr=adescr)
  935. setfield_gc(p2, 7, descr=bdescr)
  936. jump(p2, p1)
  937. """
  938. self.optimize_bridge(loops, bridge, "RETRACE", None, [ptr0, None])
  939. bridge = """
  940. [p0, p1]
  941. p2 = new_with_vtable(descr=nodesize)
  942. setfield_gc(p2, p1, descr=nextdescr)
  943. setfield_gc(p2, 7, descr=adescr)
  944. jump(p2, p1)
  945. """
  946. self.optimize_bridge(loops, bridge, "RETRACE", None, [ptr0, None])
  947. def test_known_class(self):
  948. loops = """
  949. [p0]
  950. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  951. jump(p0)
  952. ""","""
  953. [p0]
  954. guard_nonnull_class(p0, ConstClass(node_vtable2)) []
  955. jump(p0)
  956. """
  957. bridge = """
  958. [p0]
  959. jump(p0)
  960. """
  961. self.optimize_bridge(loops, bridge, loops[0], 'Loop0', [self.myptr])
  962. self.optimize_bridge(loops, bridge, loops[1], 'Loop1', [self.myptr2])
  963. self.optimize_bridge(loops[0], bridge, 'RETRACE', [self.myptr2])
  964. self.optimize_bridge(loops, loops[0], loops[0], 'Loop0', [self.nullptr])
  965. self.optimize_bridge(loops, loops[1], loops[1], 'Loop1', [self.nullptr])
  966. def test_cached_known_class(self):
  967. loop = """
  968. [p0]
  969. p1 = getfield_gc_r(p0, descr=nextdescr)
  970. guard_class(p1, ConstClass(node_vtable)) []
  971. jump(p0)
  972. """
  973. bridge = """
  974. [p0]
  975. jump(p0)
  976. """
  977. expected = """
  978. [p0]
  979. guard_nonnull(p0) []
  980. guard_is_object(p0) []
  981. guard_subclass(p0, ConstClass(node_vtable)) []
  982. p1 = getfield_gc_r(p0, descr=nextdescr)
  983. guard_nonnull(p1) []
  984. guard_is_object(p1) []
  985. guard_class(p1, ConstClass(node_vtable)) []
  986. jump(p0)
  987. """
  988. self.optimize_bridge(loop, bridge, expected, 'Loop', [self.myptr])
  989. def test_lenbound_array(self):
  990. loop = """
  991. [p0]
  992. i2 = getarrayitem_gc_i(p0, 10, descr=arraydescr)
  993. call_n(i2, descr=nonwritedescr)
  994. jump(p0)
  995. """
  996. expected = """
  997. [p0]
  998. i2 = getarrayitem_gc_i(p0, 10, descr=arraydescr)
  999. call_n(i2, descr=nonwritedescr)
  1000. ifoo = arraylen_gc(p0, descr=arraydescr)
  1001. jump(p0, i2)
  1002. """
  1003. self.optimize_bridge(loop, loop, expected, 'Loop0', [self.myptr])
  1004. bridge = """
  1005. [p0]
  1006. i2 = getarrayitem_gc_i(p0, 15, descr=arraydescr)
  1007. jump(p0)
  1008. """
  1009. expected = """
  1010. [p0]
  1011. i2 = getarrayitem_gc_i(p0, 15, descr=arraydescr)
  1012. ifoo = arraylen_gc(p0, descr=arraydescr)
  1013. i3 = getarrayitem_gc_i(p0, 10, descr=arraydescr)
  1014. jump(p0, i3)
  1015. """
  1016. self.optimize_bridge(loop, bridge, expected, 'Loop0', [self.myptr])
  1017. bridge = """
  1018. [p0]
  1019. i2 = getarrayitem_gc_i(p0, 5, descr=arraydescr)
  1020. jump(p0)
  1021. """
  1022. self.optimize_bridge(loop, bridge, 'RETRACE')
  1023. bridge = """
  1024. [p0]
  1025. jump(p0)
  1026. """
  1027. self.optimize_bridge(loop, bridge, 'RETRACE')
  1028. def test_cached_lenbound_array(self):
  1029. loop = """
  1030. [p0]
  1031. p1 = getfield_gc_r(p0, descr=nextdescr)
  1032. i2 = getarrayitem_gc_i(p1, 10, descr=arraydescr)
  1033. call_n(i2, descr=nonwritedescr)
  1034. jump(p0)
  1035. """
  1036. expected = """
  1037. [p0]
  1038. p1 = getfield_gc_r(p0, descr=nextdescr)
  1039. i2 = getarrayitem_gc_i(p1, 10, descr=arraydescr)
  1040. call_n(i2, descr=nonwritedescr)
  1041. i3 = arraylen_gc(p1, descr=arraydescr) # Should be killed by backend
  1042. jump(p0, p1, i2)
  1043. """
  1044. self.optimize_bridge(loop, loop, expected)
  1045. bridge = """
  1046. [p0]
  1047. p1 = getfield_gc_r(p0, descr=nextdescr)
  1048. i2 = getarrayitem_gc_i(p1, 15, descr=arraydescr)
  1049. jump(p0)
  1050. """
  1051. expected = """
  1052. [p0]
  1053. p1 = getfield_gc_r(p0, descr=nextdescr)
  1054. i2 = getarrayitem_gc_i(p1, 15, descr=arraydescr)
  1055. i3 = arraylen_gc(p1, descr=arraydescr) # Should be killed by backend
  1056. i4 = getarrayitem_gc_i(p1, 10, descr=arraydescr)
  1057. jump(p0, p1, i4)
  1058. """
  1059. self.optimize_bridge(loop, bridge, expected)
  1060. bridge = """
  1061. [p0]
  1062. p1 = getfield_gc_r(p0, descr=nextdescr)
  1063. i2 = getarrayitem_gc_i(p1, 5, descr=arraydescr)
  1064. jump(p0)
  1065. """
  1066. expected = """
  1067. [p0]
  1068. p1 = getfield_gc_r(p0, descr=nextdescr)
  1069. i2 = getarrayitem_gc_i(p1, 5, descr=arraydescr)
  1070. i3 = arraylen_gc(p1, descr=arraydescr) # Should be killed by backend
  1071. i4 = int_ge(i3, 11)
  1072. guard_true(i4) []
  1073. i5 = getarrayitem_gc_i(p1, 10, descr=arraydescr)
  1074. jump(p0, p1, i5)
  1075. """
  1076. self.optimize_bridge(loop, bridge, expected)
  1077. bridge = """
  1078. [p0]
  1079. jump(p0)
  1080. """
  1081. expected = """
  1082. [p0]
  1083. guard_nonnull(p0) []
  1084. guard_is_object(p0) []
  1085. guard_subclass(p0, ConstClass(node_vtable)) []
  1086. p1 = getfield_gc_r(p0, descr=nextdescr)
  1087. guard_nonnull(p1) []
  1088. guard_gc_type(p1, ConstInt(arraydescr_tid)) []
  1089. i3 = arraylen_gc(p1, descr=arraydescr) # Should be killed by backend
  1090. i4 = int_ge(i3, 11)
  1091. guard_true(i4) []
  1092. i5 = getarrayitem_gc_i(p1, 10, descr=arraydescr)
  1093. jump(p0, p1, i5)
  1094. """
  1095. self.optimize_bridge(loop, bridge, expected, 'Loop', [self.myptr])
  1096. def test_cached_setarrayitem_gc(self):
  1097. loop = """
  1098. [p0, p1]
  1099. p2 = getfield_gc_r(p0, descr=nextdescr)
  1100. pp = getarrayitem_gc_r(p2, 0, descr=gcarraydescr)
  1101. call_n(pp, descr=nonwritedescr)
  1102. p3 = getfield_gc_r(p1, descr=nextdescr)
  1103. setarrayitem_gc(p2, 0, p3, descr=gcarraydescr)
  1104. jump(p0, p3)
  1105. """
  1106. bridge = """

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