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

/rpython/jit/metainterp/test/test_resume.py

https://bitbucket.org/pypy/pypy/
Python | 1550 lines | 1402 code | 136 blank | 12 comment | 41 complexity | 1d50046a2bdf32dde7342cf9d80a97e3 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. import sys
  4. from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
  5. from rpython.jit.metainterp.resume import ResumeDataVirtualAdder,\
  6. AbstractResumeDataReader, get_VirtualCache_class, ResumeDataBoxReader,\
  7. tag, TagOverflow, untag, tagged_eq, UNASSIGNED, TAGBOX, TAGVIRTUAL,\
  8. tagged_list_eq, AbstractVirtualInfo, TAGCONST, NULLREF,\
  9. ResumeDataDirectReader, TAGINT, REF, VirtualInfo, VStructInfo,\
  10. VArrayInfoNotClear, VStrPlainInfo, VStrConcatInfo, VStrSliceInfo,\
  11. VUniPlainInfo, VUniConcatInfo, VUniSliceInfo,\
  12. capture_resumedata, ResumeDataLoopMemo, UNASSIGNEDVIRTUAL, INT,\
  13. annlowlevel, PENDINGFIELDSP, TAG_CONST_OFFSET
  14. from rpython.jit.metainterp.resumecode import unpack_numbering,\
  15. create_numbering, NULL_NUMBER
  16. from rpython.jit.metainterp.opencoder import Trace, Snapshot, TopSnapshot
  17. from rpython.jit.metainterp.optimizeopt import info
  18. from rpython.jit.metainterp.history import ConstInt, Const, AbstractDescr
  19. from rpython.jit.metainterp.history import ConstPtr, ConstFloat,\
  20. IntFrontendOp, RefFrontendOp
  21. from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
  22. from rpython.jit.metainterp import executor
  23. from rpython.jit.codewriter import heaptracker, longlong
  24. from rpython.jit.metainterp.resoperation import ResOperation, rop
  25. from rpython.rlib.debug import debug_start, debug_stop, debug_print,\
  26. have_debug_prints
  27. from rpython.jit.metainterp.test.strategies import intconsts
  28. from rpython.jit.metainterp import resumecode
  29. from hypothesis import given, strategies
  30. class Storage:
  31. rd_frame_info_list = None
  32. rd_numb = None
  33. rd_consts = []
  34. rd_virtuals = None
  35. rd_pendingfields = None
  36. rd_count = 0
  37. class FakeOptimizer(object):
  38. def __init__(self, trace=None):
  39. self.trace = trace
  40. def get_box_replacement(self, op):
  41. while (op.get_forwarded() is not None and
  42. not isinstance(op.get_forwarded(), info.AbstractInfo)):
  43. op = op.get_forwarded()
  44. return op
  45. def getrawptrinfo(self, op, create=True):
  46. op = self.get_box_replacement(op)
  47. return op.get_forwarded()
  48. def getptrinfo(self, op, create=True):
  49. op = self.get_box_replacement(op)
  50. return op.get_forwarded()
  51. # ____________________________________________________________
  52. def dump_storage(storage, liveboxes):
  53. "For profiling only."
  54. debug_start("jit-resume")
  55. return # XXX refactor if needed
  56. if have_debug_prints():
  57. debug_print('Log storage', compute_unique_id(storage))
  58. frameinfo = storage.rd_frame_info_list
  59. while frameinfo is not None:
  60. try:
  61. jitcodename = frameinfo.jitcode.name
  62. except AttributeError:
  63. jitcodename = str(compute_unique_id(frameinfo.jitcode))
  64. debug_print('\tjitcode/pc', jitcodename,
  65. frameinfo.pc,
  66. 'at', compute_unique_id(frameinfo))
  67. frameinfo = frameinfo.prev
  68. numb = storage.rd_numb
  69. while numb:
  70. debug_print('\tnumb', str([untag(numb.nums[i])
  71. for i in range(len(numb.nums))]),
  72. 'at', compute_unique_id(numb))
  73. numb = numb.prev
  74. for const in storage.rd_consts:
  75. debug_print('\tconst', const.repr_rpython())
  76. for box in liveboxes:
  77. if box is None:
  78. debug_print('\tbox', 'None')
  79. else:
  80. debug_print('\tbox', box.repr_rpython())
  81. if storage.rd_virtuals is not None:
  82. for virtual in storage.rd_virtuals:
  83. if virtual is None:
  84. debug_print('\t\t', 'None')
  85. else:
  86. virtual.debug_prints()
  87. if storage.rd_pendingfields:
  88. debug_print('\tpending setfields')
  89. for i in range(len(storage.rd_pendingfields)):
  90. lldescr = storage.rd_pendingfields[i].lldescr
  91. num = storage.rd_pendingfields[i].num
  92. fieldnum = storage.rd_pendingfields[i].fieldnum
  93. itemindex = storage.rd_pendingfields[i].itemindex
  94. debug_print("\t\t", str(lldescr), str(untag(num)), str(untag(fieldnum)), itemindex)
  95. debug_stop("jit-resume")
  96. def test_tag():
  97. assert tag(3, 1) == rffi.r_short(3<<2|1)
  98. assert tag(-3, 2) == rffi.r_short(-3<<2|2)
  99. assert tag((1<<13)-1, 3) == rffi.r_short(((1<<15)-1)|3)
  100. assert tag(-1<<13, 3) == rffi.r_short((-1<<15)|3)
  101. py.test.raises(AssertionError, tag, 3, 5)
  102. py.test.raises(TagOverflow, tag, 1<<13, 0)
  103. py.test.raises(TagOverflow, tag, (1<<13)+1, 0)
  104. py.test.raises(TagOverflow, tag, (-1<<13)-1, 0)
  105. py.test.raises(TagOverflow, tag, (-1<<13)-5, 0)
  106. def test_untag():
  107. assert untag(tag(3, 1)) == (3, 1)
  108. assert untag(tag(-3, 2)) == (-3, 2)
  109. assert untag(tag((1<<13)-1, 3)) == ((1<<13)-1, 3)
  110. assert untag(tag(-1<<13, 3)) == (-1<<13, 3)
  111. def test_tagged_eq():
  112. assert tagged_eq(UNASSIGNED, UNASSIGNED)
  113. assert not tagged_eq(tag(1, TAGBOX), UNASSIGNED)
  114. def test_tagged_list_eq():
  115. assert tagged_list_eq([UNASSIGNED, tag(1, TAGBOX), tag(-2, TAGVIRTUAL)],
  116. [UNASSIGNED, tag(1, TAGBOX), tag(-2, TAGVIRTUAL)])
  117. assert not tagged_list_eq([tag(1, TAGBOX)], [tag(-2, TAGBOX)])
  118. assert not tagged_list_eq([tag(1, TAGBOX), tag(-2, TAGBOX)], [tag(1, TAGBOX)])
  119. def test_vinfo():
  120. v1 = AbstractVirtualInfo()
  121. v1.set_content([1, 2, 4])
  122. assert v1.equals([1, 2, 4])
  123. assert not v1.equals([1, 2, 6])
  124. def test_reuse_vinfo():
  125. class FakeVInfo(object):
  126. def set_content(self, fieldnums):
  127. self.fieldnums = fieldnums
  128. def equals(self, fieldnums):
  129. return self.fieldnums == fieldnums
  130. class FakeVirtualValue(info.AbstractVirtualPtrInfo):
  131. def visitor_dispatch_virtual_type(self, *args):
  132. return FakeVInfo()
  133. modifier = ResumeDataVirtualAdder(None, None, None, None, None)
  134. v1 = FakeVirtualValue()
  135. vinfo1 = modifier.make_virtual_info(v1, [1, 2, 4])
  136. vinfo2 = modifier.make_virtual_info(v1, [1, 2, 4])
  137. assert vinfo1 is vinfo2
  138. vinfo3 = modifier.make_virtual_info(v1, [1, 2, 6])
  139. assert vinfo3 is not vinfo2
  140. vinfo4 = modifier.make_virtual_info(v1, [1, 2, 6])
  141. assert vinfo3 is vinfo4
  142. def setvalue(op, val):
  143. if op.type == 'i':
  144. op.setint(val)
  145. elif op.type == 'r':
  146. op.setref_base(val)
  147. elif op.type == 'f':
  148. op.setfloatstorage(val)
  149. else:
  150. assert op.type == 'v'
  151. class MyMetaInterp:
  152. _already_allocated_resume_virtuals = None
  153. callinfocollection = None
  154. def __init__(self, cpu=None):
  155. if cpu is None:
  156. cpu = LLtypeMixin.cpu
  157. self.cpu = cpu
  158. self.trace = []
  159. self.framestack = []
  160. def newframe(self, jitcode):
  161. frame = FakeFrame(jitcode, -1)
  162. self.framestack.append(frame)
  163. return frame
  164. def execute_and_record(self, opnum, descr, *argboxes):
  165. resvalue = executor.execute(self.cpu, None, opnum, descr, *argboxes)
  166. if isinstance(resvalue, int):
  167. op = IntFrontendOp(0)
  168. else:
  169. op = RefFrontendOp(0)
  170. setvalue(op, resvalue)
  171. self.trace.append((opnum, list(argboxes), resvalue, descr))
  172. return op
  173. def execute_new_with_vtable(self, descr=None):
  174. return self.execute_and_record(rop.NEW_WITH_VTABLE, descr)
  175. def execute_new(self, typedescr):
  176. return self.execute_and_record(rop.NEW, typedescr)
  177. def execute_new_array(self, itemsizedescr, lengthbox):
  178. return self.execute_and_record(rop.NEW_ARRAY, itemsizedescr,
  179. lengthbox)
  180. def execute_setfield_gc(self, fielddescr, box, valuebox):
  181. self.execute_and_record(rop.SETFIELD_GC, fielddescr, box, valuebox)
  182. def execute_setarrayitem_gc(self, arraydescr, arraybox, indexbox, itembox):
  183. self.execute_and_record(rop.SETARRAYITEM_GC, arraydescr,
  184. arraybox, indexbox, itembox)
  185. def execute_setinteriorfield_gc(self, descr, array, index, value):
  186. self.execute_and_record(rop.SETINTERIORFIELD_GC, descr,
  187. array, index, value)
  188. def execute_raw_store(self, arraydescr, addrbox, offsetbox, valuebox):
  189. self.execute_and_record(rop.RAW_STORE, arraydescr,
  190. addrbox, offsetbox, valuebox)
  191. S = lltype.GcStruct('S')
  192. gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S))
  193. gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S))
  194. gcrefnull = lltype.nullptr(llmemory.GCREF.TO)
  195. class MyCPU:
  196. class ts:
  197. NULLREF = gcrefnull
  198. CONST_NULL = ConstPtr(gcrefnull)
  199. def __init__(self, values):
  200. self.values = values
  201. def get_int_value(self, deadframe, index):
  202. assert deadframe == "deadframe"
  203. return self.values[index]
  204. def get_ref_value(self, deadframe, index):
  205. assert deadframe == "deadframe"
  206. return self.values[index]
  207. def get_float_value(self, deadframe, index):
  208. assert deadframe == "deadframe"
  209. return self.values[index]
  210. class MyBlackholeInterp:
  211. def __init__(self, ARGS):
  212. self.written_i = []
  213. self.written_r = []
  214. self.written_f = []
  215. self.ARGS = ARGS
  216. def get_current_position_info(self):
  217. class MyInfo:
  218. @staticmethod
  219. def enumerate_vars(callback_i, callback_r, callback_f, _, index):
  220. count_i = count_r = count_f = 0
  221. for ARG in self.ARGS:
  222. if ARG == lltype.Signed:
  223. index = callback_i(index, count_i); count_i += 1
  224. elif ARG == llmemory.GCREF:
  225. index = callback_r(index, count_r); count_r += 1
  226. elif ARG == longlong.FLOATSTORAGE:
  227. index = callback_f(index, count_f); count_f += 1
  228. else:
  229. assert 0
  230. return index
  231. return MyInfo()
  232. def setarg_i(self, index, value):
  233. assert index == len(self.written_i)
  234. self.written_i.append(value)
  235. def setarg_r(self, index, value):
  236. assert index == len(self.written_r)
  237. self.written_r.append(value)
  238. def setarg_f(self, index, value):
  239. assert index == len(self.written_f)
  240. self.written_f.append(value)
  241. def _next_section(reader, *expected):
  242. bh = MyBlackholeInterp(map(lltype.typeOf, expected))
  243. reader.consume_one_section(bh)
  244. expected_i = [x for x in expected if lltype.typeOf(x) == lltype.Signed]
  245. expected_r = [x for x in expected if lltype.typeOf(x) == llmemory.GCREF]
  246. expected_f = [x for x in expected if lltype.typeOf(x) ==
  247. longlong.FLOATSTORAGE]
  248. assert bh.written_i == expected_i
  249. assert bh.written_r == expected_r
  250. assert bh.written_f == expected_f
  251. Numbering = create_numbering
  252. def tagconst(i):
  253. return tag(i + TAG_CONST_OFFSET, TAGCONST)
  254. def test_simple_read():
  255. #b1, b2, b3 = [BoxInt(), InputArgRef(), BoxInt()]
  256. c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)]
  257. storage = Storage()
  258. storage.rd_consts = [c1, c2, c3]
  259. numb = Numbering([tag(0, TAGBOX), tagconst(0),
  260. NULLREF, tag(0, TAGBOX), tag(1, TAGBOX)] +
  261. [tagconst(1), tagconst(2)] +
  262. [tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)])
  263. storage.rd_numb = numb
  264. storage.rd_count = 3
  265. #
  266. cpu = MyCPU([42, gcref1, -66])
  267. metainterp = MyMetaInterp(cpu)
  268. reader = ResumeDataDirectReader(metainterp, storage, "deadframe")
  269. _next_section(reader, 42, 111, gcrefnull, 42, gcref1)
  270. _next_section(reader, 222, 333)
  271. _next_section(reader, 42, gcref1, -66)
  272. #
  273. reader = ResumeDataBoxReader(storage, "deadframe", metainterp)
  274. bi, br, bf = [None]*3, [None]*2, [None]*0
  275. info = MyBlackholeInterp([lltype.Signed, lltype.Signed,
  276. llmemory.GCREF, lltype.Signed,
  277. llmemory.GCREF]).get_current_position_info()
  278. reader.consume_boxes(info, bi, br, bf)
  279. b1s = reader.liveboxes[0]
  280. b2s = reader.liveboxes[1]
  281. assert_same(bi, [b1s, ConstInt(111), b1s])
  282. assert_same(br, [ConstPtr(gcrefnull), b2s])
  283. bi, br, bf = [None]*2, [None]*0, [None]*0
  284. info = MyBlackholeInterp([lltype.Signed,
  285. lltype.Signed]).get_current_position_info()
  286. reader.consume_boxes(info, bi, br, bf)
  287. assert_same(bi, [ConstInt(222), ConstInt(333)])
  288. bi, br, bf = [None]*2, [None]*1, [None]*0
  289. info = MyBlackholeInterp([lltype.Signed, llmemory.GCREF,
  290. lltype.Signed]).get_current_position_info()
  291. reader.consume_boxes(info, bi, br, bf)
  292. b3s = reader.liveboxes[2]
  293. assert_same(bi, [b1s, b3s])
  294. assert_same(br, [b2s])
  295. #
  296. def assert_same(list1, list2):
  297. assert len(list1) == len(list2)
  298. for b1, b2 in zip(list1, list2):
  299. assert b1.same_box(b2)
  300. def test_simple_read_tagged_ints():
  301. storage = Storage()
  302. storage.rd_consts = []
  303. numb = Numbering([tag(100, TAGINT)])
  304. storage.rd_numb = numb
  305. #
  306. cpu = MyCPU([])
  307. reader = ResumeDataDirectReader(MyMetaInterp(cpu), storage, "deadframe")
  308. _next_section(reader, 100)
  309. def test_prepare_virtuals():
  310. class FakeVinfo(object):
  311. kind = REF
  312. def allocate(self, decoder, index):
  313. s = "allocated"
  314. decoder.virtuals_cache.set_ptr(index, s)
  315. return s
  316. class FakeStorage(object):
  317. rd_virtuals = [FakeVinfo(), None]
  318. rd_numb = []
  319. rd_consts = []
  320. rd_pendingfields = None
  321. rd_count = 0
  322. class FakeMetainterp(object):
  323. _already_allocated_resume_virtuals = None
  324. cpu = None
  325. reader = ResumeDataDirectReader(MyMetaInterp(None), FakeStorage(),
  326. "deadframe")
  327. cache = reader.force_all_virtuals()
  328. assert cache.virtuals_ptr_cache == ["allocated", reader.virtual_ptr_default]
  329. # ____________________________________________________________
  330. class FakeResumeDataReader(AbstractResumeDataReader):
  331. VirtualCache = get_VirtualCache_class('Fake')
  332. def allocate_with_vtable(self, descr):
  333. return FakeBuiltObject(vtable=descr)
  334. def allocate_struct(self, typedescr):
  335. return FakeBuiltObject(typedescr=typedescr)
  336. def allocate_array(self, length, arraydescr, clear):
  337. assert not clear # the only test uses VArrayInfoNotClear
  338. return FakeBuiltObject(arraydescr=arraydescr, items=[None]*length)
  339. def setfield(self, struct, fieldnum, descr):
  340. setattr(struct, descr, fieldnum)
  341. def setarrayitem_int(self, array, i, fieldnum, arraydescr):
  342. assert 0 <= i < len(array.items)
  343. assert arraydescr is array.arraydescr
  344. array.items[i] = fieldnum
  345. def allocate_string(self, length):
  346. return FakeBuiltObject(string=[None]*length)
  347. def string_setitem(self, string, i, fieldnum):
  348. value, tag = untag(fieldnum)
  349. assert tag == TAGINT
  350. assert 0 <= i < len(string.string)
  351. string.string[i] = value
  352. def concat_strings(self, left, right):
  353. return FakeBuiltObject(strconcat=[left, right])
  354. def slice_string(self, str, start, length):
  355. return FakeBuiltObject(strslice=[str, start, length])
  356. def allocate_unicode(self, length):
  357. return FakeBuiltObject(unistring=[None]*length)
  358. def unicode_setitem(self, unistring, i, fieldnum):
  359. value, tag = untag(fieldnum)
  360. assert tag == TAGINT
  361. assert 0 <= i < len(unistring.unistring)
  362. unistring.unistring[i] = value
  363. def concat_unicodes(self, left, right):
  364. return FakeBuiltObject(uniconcat=[left, right])
  365. def slice_unicode(self, str, start, length):
  366. return FakeBuiltObject(unislice=[str, start, length])
  367. class FakeBuiltObject(object):
  368. def __init__(self, **kwds):
  369. self.__dict__ = kwds
  370. def __eq__(self, other):
  371. return (self.__class__ == other.__class__ and
  372. self.__dict__ == other.__dict__)
  373. def __repr__(self):
  374. return 'FakeBuiltObject(%s)' % (
  375. ', '.join(['%s=%r' % item for item in self.__dict__.items()]))
  376. class FakeArrayDescr(object):
  377. def is_array_of_pointers(self): return False
  378. def is_array_of_floats(self): return False
  379. def test_virtualinfo():
  380. info = VirtualInfo(123, ["fielddescr1"])
  381. info.fieldnums = [tag(456, TAGINT)]
  382. reader = FakeResumeDataReader()
  383. reader._prepare_virtuals([info])
  384. cache = reader.force_all_virtuals()
  385. assert cache.virtuals_ptr_cache == [
  386. FakeBuiltObject(vtable=123, fielddescr1=tag(456, TAGINT))]
  387. def test_vstructinfo():
  388. info = VStructInfo(124, ["fielddescr1"])
  389. info.fieldnums = [tag(456, TAGINT)]
  390. reader = FakeResumeDataReader()
  391. reader._prepare_virtuals([info])
  392. cache = reader.force_all_virtuals()
  393. assert cache.virtuals_ptr_cache == [
  394. FakeBuiltObject(typedescr=124, fielddescr1=tag(456, TAGINT))]
  395. def test_varrayinfo():
  396. arraydescr = FakeArrayDescr()
  397. info = VArrayInfoNotClear(arraydescr)
  398. info.fieldnums = [tag(456, TAGINT)]
  399. reader = FakeResumeDataReader()
  400. reader._prepare_virtuals([info])
  401. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  402. FakeBuiltObject(arraydescr=arraydescr, items=[tag(456, TAGINT)])]
  403. def test_vstrplaininfo():
  404. info = VStrPlainInfo()
  405. info.fieldnums = [tag(60, TAGINT)]
  406. reader = FakeResumeDataReader()
  407. reader._prepare_virtuals([info])
  408. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  409. FakeBuiltObject(string=[60])]
  410. def test_vstrconcatinfo():
  411. info = VStrConcatInfo()
  412. info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX)]
  413. reader = FakeResumeDataReader()
  414. reader._prepare_virtuals([info])
  415. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  416. FakeBuiltObject(strconcat=info.fieldnums)]
  417. def test_vstrsliceinfo():
  418. info = VStrSliceInfo()
  419. info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX), tag(30, TAGBOX)]
  420. reader = FakeResumeDataReader()
  421. reader._prepare_virtuals([info])
  422. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  423. FakeBuiltObject(strslice=info.fieldnums)]
  424. def test_vuniplaininfo():
  425. info = VUniPlainInfo()
  426. info.fieldnums = [tag(60, TAGINT)]
  427. reader = FakeResumeDataReader()
  428. reader._prepare_virtuals([info])
  429. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  430. FakeBuiltObject(unistring=[60])]
  431. def test_vuniconcatinfo():
  432. info = VUniConcatInfo()
  433. info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX)]
  434. reader = FakeResumeDataReader()
  435. reader._prepare_virtuals([info])
  436. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  437. FakeBuiltObject(uniconcat=info.fieldnums)]
  438. def test_vunisliceinfo():
  439. info = VUniSliceInfo()
  440. info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX), tag(30, TAGBOX)]
  441. reader = FakeResumeDataReader()
  442. reader._prepare_virtuals([info])
  443. assert reader.force_all_virtuals().virtuals_ptr_cache == [
  444. FakeBuiltObject(unislice=info.fieldnums)]
  445. # ____________________________________________________________
  446. class FakeFrame(object):
  447. parent_resume_position = -1
  448. def __init__(self, code, pc, *boxes):
  449. self.jitcode = code
  450. self.pc = pc
  451. self._env = list(boxes)
  452. def get_list_of_active_boxes(self, flag):
  453. return self._env
  454. def setup_resume_at_op(self, pc, exception_target, env):
  455. self.__init__(self.jitcode, pc, exception_target, *env)
  456. def __eq__(self, other):
  457. return self.__dict__ == other.__dict__
  458. def __ne__(self, other):
  459. return self.__dict__ != other.__dict__
  460. def __repr__(self):
  461. return "<FF %s %s %s>" % (self.jitcode, self.pc, self._env)
  462. class FakeJitCode(object):
  463. def __init__(self, name, index):
  464. self.name = name
  465. self.index = index
  466. class FakeMetaInterpStaticData:
  467. cpu = LLtypeMixin.cpu
  468. all_descrs = []
  469. class options:
  470. failargs_limit = 100
  471. def test_rebuild_from_resumedata():
  472. py.test.skip("XXX rewrite")
  473. b1, b2, b3 = [BoxInt(), InputArgRef(), BoxInt()]
  474. c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)]
  475. storage = Storage()
  476. fs = [FakeFrame("code0", 0, b1, c1, b2),
  477. FakeFrame("code1", 3, b3, c2, b1),
  478. FakeFrame("code2", 9, c3, b2)]
  479. capture_resumedata(fs, None, [], storage)
  480. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  481. modifier = ResumeDataVirtualAdder(None, storage, storage, memo)
  482. liveboxes = modifier.finish(FakeOptimizer())
  483. metainterp = MyMetaInterp()
  484. b1t, b2t, b3t = [BoxInt(), InputArgRef(), BoxInt()]
  485. newboxes = _resume_remap(liveboxes, [b1, b2, b3], b1t, b2t, b3t)
  486. result = rebuild_from_resumedata(metainterp, storage, False)
  487. assert result == (None, [])
  488. fs2 = [FakeFrame("code0", 0, b1t, c1, b2t),
  489. FakeFrame("code1", 3, b3t, c2, b1t),
  490. FakeFrame("code2", 9, c3, b2t)]
  491. assert metainterp.framestack == fs2
  492. def test_rebuild_from_resumedata_with_virtualizable():
  493. py.test.skip("XXX rewrite")
  494. b1, b2, b3, b4 = [BoxInt(), InputArgRef(), BoxInt(), InputArgRef()]
  495. c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)]
  496. storage = Storage()
  497. fs = [FakeFrame("code0", 0, b1, c1, b2),
  498. FakeFrame("code1", 3, b3, c2, b1),
  499. FakeFrame("code2", 9, c3, b2)]
  500. capture_resumedata(fs, [b4], [], storage)
  501. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  502. modifier = ResumeDataVirtualAdder(None, storage, memo)
  503. liveboxes = modifier.finish(FakeOptimizer({}))
  504. metainterp = MyMetaInterp()
  505. b1t, b2t, b3t, b4t = [BoxInt(), InputArgRef(), BoxInt(), InputArgRef()]
  506. newboxes = _resume_remap(liveboxes, [b1, b2, b3, b4], b1t, b2t, b3t, b4t)
  507. result = rebuild_from_resumedata(metainterp, newboxes, storage,
  508. True)
  509. assert result == ([b4t], [])
  510. fs2 = [FakeFrame("code0", 0, b1t, c1, b2t),
  511. FakeFrame("code1", 3, b3t, c2, b1t),
  512. FakeFrame("code2", 9, c3, b2t)]
  513. assert metainterp.framestack == fs2
  514. def test_rebuild_from_resumedata_two_guards():
  515. py.test.skip("XXX rewrite")
  516. b1, b2, b3, b4 = [BoxInt(), InputArgRef(), BoxInt(), BoxInt()]
  517. c1, c2, c3 = [ConstInt(1), ConstInt(2), ConstInt(3)]
  518. storage = Storage()
  519. fs = [FakeFrame("code0", 0, b1, c1, b2),
  520. FakeFrame("code1", 3, b3, c2, b1),
  521. FakeFrame("code2", 9, c3, b2)]
  522. capture_resumedata(fs, None, [], storage)
  523. storage2 = Storage()
  524. fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)]
  525. capture_resumedata(fs, None, [], storage2)
  526. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  527. modifier = ResumeDataVirtualAdder(None, storage, memo)
  528. liveboxes = modifier.finish(FakeOptimizer({}))
  529. modifier = ResumeDataVirtualAdder(None, storage2, memo)
  530. liveboxes2 = modifier.finish(FakeOptimizer({}))
  531. metainterp = MyMetaInterp()
  532. b1t, b2t, b3t, b4t = [BoxInt(), InputArgRef(), BoxInt(), BoxInt()]
  533. newboxes = _resume_remap(liveboxes, [b1, b2, b3], b1t, b2t, b3t)
  534. result = rebuild_from_resumedata(metainterp, newboxes, storage,
  535. False)
  536. assert result == (None, [])
  537. fs2 = [FakeFrame("code0", 0, b1t, c1, b2t),
  538. FakeFrame("code1", 3, b3t, c2, b1t),
  539. FakeFrame("code2", 9, c3, b2t)]
  540. assert metainterp.framestack == fs2
  541. newboxes = _resume_remap(liveboxes2, [b1, b2, b3, b4], b1t, b2t, b3t, b4t)
  542. metainterp.framestack = []
  543. result = rebuild_from_resumedata(metainterp, newboxes, storage2,
  544. False)
  545. assert result == (None, [])
  546. fs2 = fs2[:-1] + [FakeFrame("code2", 10, c3, b2t, b4t)]
  547. assert metainterp.framestack == fs2
  548. class FakeOptimizer_VirtualValue(object):
  549. class optimizer:
  550. class cpu:
  551. pass
  552. fakeoptimizer = FakeOptimizer_VirtualValue()
  553. def ConstAddr(addr, cpu): # compatibility
  554. return ConstInt(heaptracker.adr2int(addr))
  555. def virtual_value(keybox, value, next):
  556. vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr,
  557. LLtypeMixin.cpu), keybox)
  558. if not isinstance(next, OptValue):
  559. next = OptValue(next)
  560. vv.setfield(LLtypeMixin.valuedescr, OptValue(value))
  561. vv.setfield(LLtypeMixin.nextdescr, next)
  562. return vv
  563. def test_rebuild_from_resumedata_two_guards_w_virtuals():
  564. py.test.skip("XXX rewrite")
  565. b1, b2, b3, b4, b5 = [BoxInt(), InputArgRef(), BoxInt(), BoxInt(), BoxInt()]
  566. c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3),
  567. LLtypeMixin.nodebox.constbox()]
  568. storage = Storage()
  569. fs = [FakeFrame("code0", 0, b1, c1, b2),
  570. FakeFrame("code1", 3, b3, c2, b1),
  571. FakeFrame("code2", 9, c3, b2)]
  572. capture_resumedata(fs, None, [], storage)
  573. storage2 = Storage()
  574. fs = fs[:-1] + [FakeFrame("code2", 10, c3, b2, b4)]
  575. capture_resumedata(fs, None, [], storage2)
  576. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  577. values = {b2: virtual_value(b2, b5, c4)}
  578. modifier = ResumeDataVirtualAdder(storage, memo)
  579. liveboxes = modifier.finish(FakeOptimizer(values))
  580. assert len(storage.rd_virtuals) == 1
  581. assert storage.rd_virtuals[0].fieldnums == [tag(-1, TAGBOX),
  582. tag(0, TAGCONST)]
  583. b6 = InputArgRef()
  584. v6 = virtual_value(b6, c2, None)
  585. v6.setfield(LLtypeMixin.nextdescr, v6)
  586. values = {b2: virtual_value(b2, b4, v6), b6: v6}
  587. memo.clear_box_virtual_numbers()
  588. modifier = ResumeDataVirtualAdder(storage2, memo)
  589. liveboxes2 = modifier.finish(FakeOptimizer(values))
  590. assert len(storage2.rd_virtuals) == 2
  591. assert storage2.rd_virtuals[0].fieldnums == [tag(len(liveboxes2)-1, TAGBOX),
  592. tag(-1, TAGVIRTUAL)]
  593. assert storage2.rd_virtuals[1].fieldnums == [tag(2, TAGINT),
  594. tag(-1, TAGVIRTUAL)]
  595. # now on to resuming
  596. metainterp = MyMetaInterp()
  597. b1t, b3t, b4t, b5t = [BoxInt(), BoxInt(), BoxInt(), BoxInt()]
  598. newboxes = _resume_remap(liveboxes, [b1, b3, b5], b1t, b3t, b5t)
  599. result = rebuild_from_resumedata(metainterp, newboxes, storage,
  600. False)
  601. b2t = metainterp.resboxes[0]
  602. fs2 = [FakeFrame("code0", 0, b1t, c1, b2t),
  603. FakeFrame("code1", 3, b3t, c2, b1t),
  604. FakeFrame("code2", 9, c3, b2t)]
  605. assert metainterp.framestack == fs2
  606. newboxes = _resume_remap(liveboxes2, [b1, b3, b4], b1t, b3t, b4t)
  607. metainterp = MyMetaInterp()
  608. result = rebuild_from_resumedata(metainterp, newboxes, storage2,
  609. False)
  610. b2t = metainterp.resboxes[0]
  611. assert len(metainterp.resboxes) == 2
  612. fs2 = [FakeFrame("code0", 0, b1t, c1, b2t),
  613. FakeFrame("code1", 3, b3t, c2, b1t),
  614. FakeFrame("code2", 10, c3, b2t, b4t)]
  615. assert metainterp.framestack == fs2
  616. def test_rebuild_from_resumedata_two_guards_w_shared_virtuals():
  617. py.test.skip("XXX rewrite")
  618. b1, b2, b3, b4, b5, b6 = [InputArgRef(), InputArgRef(), BoxInt(), InputArgRef(), BoxInt(), BoxInt()]
  619. c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3),
  620. LLtypeMixin.nodebox.constbox()]
  621. storage = Storage()
  622. fs = [FakeFrame("code0", 0, c1, b2, b3)]
  623. capture_resumedata(fs, None, [], storage)
  624. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  625. values = {b2: virtual_value(b2, b5, c4)}
  626. modifier = ResumeDataVirtualAdder(storage, memo)
  627. liveboxes = modifier.finish(FakeOptimizer(values))
  628. assert len(storage.rd_virtuals) == 1
  629. assert storage.rd_virtuals[0].fieldnums == [tag(-1, TAGBOX),
  630. tag(0, TAGCONST)]
  631. storage2 = Storage()
  632. fs = [FakeFrame("code0", 0, b1, b4, b2)]
  633. capture_resumedata(fs, None, [], storage2)
  634. values[b4] = virtual_value(b4, b6, c4)
  635. modifier = ResumeDataVirtualAdder(storage2, memo)
  636. liveboxes = modifier.finish(FakeOptimizer(values))
  637. assert len(storage2.rd_virtuals) == 2
  638. assert storage2.rd_virtuals[1].fieldnums == storage.rd_virtuals[0].fieldnums
  639. assert storage2.rd_virtuals[1] is storage.rd_virtuals[0]
  640. def test_resumedata_top_recursive_virtuals():
  641. py.test.skip("XXX rewrite")
  642. b1, b2, b3 = [InputArgRef(), InputArgRef(), BoxInt()]
  643. storage = Storage()
  644. fs = [FakeFrame("code0", 0, b1, b2)]
  645. capture_resumedata(fs, None, [], storage)
  646. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  647. v1 = virtual_value(b1, b3, None)
  648. v2 = virtual_value(b2, b3, v1)
  649. v1.setfield(LLtypeMixin.nextdescr, v2)
  650. values = {b1: v1, b2: v2}
  651. modifier = ResumeDataVirtualAdder(storage, memo)
  652. liveboxes = modifier.finish(FakeOptimizer(values))
  653. assert liveboxes == [b3]
  654. assert len(storage.rd_virtuals) == 2
  655. assert storage.rd_virtuals[0].fieldnums == [tag(-1, TAGBOX),
  656. tag(1, TAGVIRTUAL)]
  657. assert storage.rd_virtuals[1].fieldnums == [tag(-1, TAGBOX),
  658. tag(0, TAGVIRTUAL)]
  659. # ____________________________________________________________
  660. def test_ResumeDataLoopMemo_ints():
  661. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  662. tagged = memo.getconst(ConstInt(44))
  663. assert untag(tagged) == (44, TAGINT)
  664. tagged = memo.getconst(ConstInt(-3))
  665. assert untag(tagged) == (-3, TAGINT)
  666. const = ConstInt(50000)
  667. tagged = memo.getconst(const)
  668. index, tagbits = untag(tagged)
  669. assert tagbits == TAGCONST
  670. assert memo.consts[index - TAG_CONST_OFFSET] is const
  671. tagged = memo.getconst(ConstInt(50000))
  672. index2, tagbits = untag(tagged)
  673. assert tagbits == TAGCONST
  674. assert index2 == index
  675. demo55 = lltype.malloc(LLtypeMixin.NODE)
  676. demo55o = lltype.cast_opaque_ptr(llmemory.GCREF, demo55)
  677. demo66 = lltype.malloc(LLtypeMixin.NODE)
  678. demo66o = lltype.cast_opaque_ptr(llmemory.GCREF, demo66)
  679. def test_ResumeDataLoopMemo_refs():
  680. cpu = LLtypeMixin.cpu
  681. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  682. const = cpu.ts.ConstRef(demo55o)
  683. tagged = memo.getconst(const)
  684. index, tagbits = untag(tagged)
  685. assert tagbits == TAGCONST
  686. assert memo.consts[index - TAG_CONST_OFFSET] is const
  687. tagged = memo.getconst(cpu.ts.ConstRef(demo55o))
  688. index2, tagbits = untag(tagged)
  689. assert tagbits == TAGCONST
  690. assert index2 == index
  691. tagged = memo.getconst(cpu.ts.ConstRef(demo66o))
  692. index3, tagbits = untag(tagged)
  693. assert tagbits == TAGCONST
  694. assert index3 != index
  695. tagged = memo.getconst(cpu.ts.CONST_NULL)
  696. assert tagged == NULLREF
  697. def test_ResumeDataLoopMemo_other():
  698. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  699. const = ConstFloat(longlong.getfloatstorage(-1.0))
  700. tagged = memo.getconst(const)
  701. index, tagbits = untag(tagged)
  702. assert tagbits == TAGCONST
  703. assert memo.consts[index - TAG_CONST_OFFSET] is const
  704. class Frame(object):
  705. def __init__(self, boxes):
  706. self.boxes = boxes
  707. def get_list_of_active_boxes(self, flag, new_array, encode):
  708. a = new_array(len(self.boxes))
  709. for i, box in enumerate(self.boxes):
  710. a[i] = encode(box)
  711. return a
  712. def test_ResumeDataLoopMemo_number():
  713. b1, b2, b3, b4, b5 = [IntFrontendOp(0), IntFrontendOp(1), IntFrontendOp(2),
  714. RefFrontendOp(3), RefFrontendOp(4)]
  715. c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3), ConstInt(4)]
  716. env = [b1, c1, b2, b1, c2]
  717. metainterp_sd = FakeMetaInterpStaticData()
  718. t = Trace([b1, b2, b3, b4, b5], metainterp_sd)
  719. snap = t.create_snapshot(FakeJitCode("jitcode", 0), 0, Frame(env), False)
  720. env1 = [c3, b3, b1, c1]
  721. t.append(0) # descr index
  722. snap1 = t.create_top_snapshot(FakeJitCode("jitcode", 0), 2, Frame(env1), False,
  723. [], [])
  724. snap1.prev = snap
  725. env2 = [c3, b3, b1, c3]
  726. env3 = [c3, b3, b1, c3]
  727. env4 = [c3, b4, b1, c3]
  728. env5 = [b1, b4, b5]
  729. memo = ResumeDataLoopMemo(metainterp_sd)
  730. iter = t.get_iter()
  731. b1, b2, b3, b4, b5 = iter.inputargs
  732. numb, liveboxes, v = memo.number(FakeOptimizer(), 0, iter)
  733. assert v == 0
  734. assert liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
  735. b3: tag(2, TAGBOX)}
  736. base = [0, 0, tag(0, TAGBOX), tag(1, TAGINT),
  737. tag(1, TAGBOX), tag(0, TAGBOX), tag(2, TAGINT)]
  738. assert unpack_numbering(numb) == [0, 0] + base + [0, 2, tag(3, TAGINT), tag(2, TAGBOX),
  739. tag(0, TAGBOX), tag(1, TAGINT)]
  740. t.append(0)
  741. snap2 = t.create_top_snapshot(FakeJitCode("jitcode", 0), 2, Frame(env2),
  742. False, [], [])
  743. snap2.prev = snap
  744. numb2, liveboxes2, v = memo.number(FakeOptimizer(), 1, iter)
  745. assert v == 0
  746. assert liveboxes2 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
  747. b3: tag(2, TAGBOX)}
  748. assert liveboxes2 is not liveboxes
  749. assert unpack_numbering(numb2) == [0, 0] + base + [0, 2, tag(3, TAGINT), tag(2, TAGBOX),
  750. tag(0, TAGBOX), tag(3, TAGINT)]
  751. t.append(0)
  752. snap3 = t.create_top_snapshot(FakeJitCode("jitcode", 0), 2, Frame([]),
  753. False, [], env3)
  754. snap3.prev = snap
  755. class FakeVirtualInfo(info.AbstractInfo):
  756. def __init__(self, virt):
  757. self.virt = virt
  758. def is_virtual(self):
  759. return self.virt
  760. # renamed
  761. b3.set_forwarded(c4)
  762. numb3, liveboxes3, v = memo.number(FakeOptimizer(), 2, iter)
  763. assert v == 0
  764. assert liveboxes3 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX)}
  765. assert unpack_numbering(numb3) == ([0, 2, tag(3, TAGINT), tag(4, TAGINT),
  766. tag(0, TAGBOX), tag(3, TAGINT)] +
  767. base + [0, 2])
  768. # virtual
  769. t.append(0)
  770. snap4 = t.create_top_snapshot(FakeJitCode("jitcode", 0), 2, Frame([]),
  771. False, [], env4)
  772. snap4.prev = snap
  773. b4.set_forwarded(FakeVirtualInfo(True))
  774. numb4, liveboxes4, v = memo.number(FakeOptimizer(), 3, iter)
  775. assert v == 1
  776. assert liveboxes4 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
  777. b4: tag(0, TAGVIRTUAL)}
  778. assert unpack_numbering(numb4) == [0, 2, tag(3, TAGINT), tag(0, TAGVIRTUAL),
  779. tag(0, TAGBOX), tag(3, TAGINT)] + base + [0, 2]
  780. t.append(0)
  781. snap4 = t.create_snapshot(FakeJitCode("jitcode", 2), 1, Frame(env4), False)
  782. t.append(0)
  783. snap4.prev = snap
  784. snap5 = t.create_top_snapshot(FakeJitCode("jitcode", 0), 0, Frame([]), False,
  785. env5, [])
  786. snap5.prev = snap4
  787. b4.set_forwarded(FakeVirtualInfo(True))
  788. b5.set_forwarded(FakeVirtualInfo(True))
  789. numb5, liveboxes5, v = memo.number(FakeOptimizer(), 4, iter)
  790. assert v == 2
  791. assert liveboxes5 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
  792. b4: tag(0, TAGVIRTUAL), b5: tag(1, TAGVIRTUAL)}
  793. assert unpack_numbering(numb5) == [
  794. 3, tag(0, TAGBOX), tag(0, TAGVIRTUAL), tag(1, TAGVIRTUAL),
  795. 0] + base + [
  796. 2, 1, tag(3, TAGINT), tag(0, TAGVIRTUAL), tag(0, TAGBOX), tag(3, TAGINT)
  797. ] + [0, 0]
  798. @given(strategies.lists(strategies.builds(IntFrontendOp, strategies.just(0)) | intconsts,
  799. min_size=1))
  800. def test_ResumeDataLoopMemo_random(lst):
  801. inpargs = [box for box in lst if not isinstance(box, Const)]
  802. metainterp_sd = FakeMetaInterpStaticData()
  803. t = Trace(inpargs, metainterp_sd)
  804. t.append(0)
  805. i = t.get_iter()
  806. t.create_top_snapshot(FakeJitCode("", 0), 0, Frame(lst), False, [], [])
  807. memo = ResumeDataLoopMemo(metainterp_sd)
  808. num, liveboxes, v = memo.number(FakeOptimizer(), 0, i)
  809. l = unpack_numbering(num)
  810. assert l[0] == 0
  811. assert l[1] == 0
  812. assert l[2] == 0
  813. assert l[3] == 0
  814. mapping = dict(zip(inpargs, i.inputargs))
  815. for i, item in enumerate(lst):
  816. v, tag = untag(l[i + 4])
  817. if tag == TAGBOX:
  818. assert l[i + 4] == liveboxes[mapping[item]]
  819. elif tag == TAGCONST:
  820. assert memo.consts[v].getint() == item.getint()
  821. elif tag == TAGINT:
  822. assert v == item.getint()
  823. def test_ResumeDataLoopMemo_number_boxes():
  824. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  825. b1, b2 = [IntFrontendOp(0), IntFrontendOp(0)]
  826. assert memo.num_cached_boxes() == 0
  827. boxes = []
  828. num = memo.assign_number_to_box(b1, boxes)
  829. assert num == -1
  830. assert boxes == [b1]
  831. assert memo.num_cached_boxes() == 1
  832. boxes = [None]
  833. num = memo.assign_number_to_box(b1, boxes)
  834. assert num == -1
  835. assert boxes == [b1]
  836. num = memo.assign_number_to_box(b2, boxes)
  837. assert num == -2
  838. assert boxes == [b1, b2]
  839. assert memo.num_cached_boxes() == 2
  840. boxes = [None, None]
  841. num = memo.assign_number_to_box(b2, boxes)
  842. assert num == -2
  843. assert boxes == [None, b2]
  844. num = memo.assign_number_to_box(b1, boxes)
  845. assert num == -1
  846. assert boxes == [b1, b2]
  847. memo.clear_box_virtual_numbers()
  848. assert memo.num_cached_boxes() == 0
  849. def test_ResumeDataLoopMemo_number_virtuals():
  850. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  851. b1, b2 = [IntFrontendOp(0), IntFrontendOp(0)]
  852. assert memo.num_cached_virtuals() == 0
  853. num = memo.assign_number_to_virtual(b1)
  854. assert num == -1
  855. assert memo.num_cached_virtuals() == 1
  856. num = memo.assign_number_to_virtual(b1)
  857. assert num == -1
  858. num = memo.assign_number_to_virtual(b2)
  859. assert num == -2
  860. assert memo.num_cached_virtuals() == 2
  861. num = memo.assign_number_to_virtual(b2)
  862. assert num == -2
  863. num = memo.assign_number_to_virtual(b1)
  864. assert num == -1
  865. memo.clear_box_virtual_numbers()
  866. assert memo.num_cached_virtuals() == 0
  867. def test_register_virtual_fields():
  868. b1, b2 = IntFrontendOp(0), IntFrontendOp(1)
  869. vbox = RefFrontendOp(2)
  870. modifier = ResumeDataVirtualAdder(FakeOptimizer(), None, None, None, None)
  871. modifier.liveboxes_from_env = {}
  872. modifier.liveboxes = {}
  873. modifier.vfieldboxes = {}
  874. modifier.register_virtual_fields(vbox, [b1, b2])
  875. assert modifier.liveboxes == {vbox: UNASSIGNEDVIRTUAL, b1: UNASSIGNED,
  876. b2: UNASSIGNED}
  877. assert modifier.vfieldboxes == {vbox: [b1, b2]}
  878. modifier = ResumeDataVirtualAdder(FakeOptimizer(), None, None, None, None)
  879. modifier.liveboxes_from_env = {vbox: tag(0, TAGVIRTUAL)}
  880. modifier.liveboxes = {}
  881. modifier.vfieldboxes = {}
  882. modifier.register_virtual_fields(vbox, [b1, b2, vbox])
  883. assert modifier.liveboxes == {b1: UNASSIGNED, b2: UNASSIGNED,
  884. vbox: tag(0, TAGVIRTUAL)}
  885. assert modifier.vfieldboxes == {vbox: [b1, b2, vbox]}
  886. def _resume_remap(liveboxes, expected, *newvalues):
  887. newboxes = []
  888. for box in liveboxes:
  889. i = expected.index(box)
  890. newboxes.append(newvalues[i])
  891. assert len(newboxes) == len(expected)
  892. return newboxes
  893. def make_storage(b1, b2, b3):
  894. t = Trace([box for box in [b1, b2, b3] if not isinstance(box, Const)],
  895. FakeMetaInterpStaticData())
  896. t.append(0)
  897. storage = Storage()
  898. snap1 = t.create_snapshot(FakeJitCode("code3", 41), 42,
  899. Frame([b1, ConstInt(1), b1, b2]), False)
  900. snap2 = t.create_snapshot(FakeJitCode("code2", 31), 32,
  901. Frame([ConstInt(2), ConstInt(3)]), False)
  902. snap3 = t.create_top_snapshot(FakeJitCode("code1", 21), 22,
  903. Frame([b1, b2, b3]), False, [], [])
  904. snap3.prev = snap2
  905. snap2.prev = snap1
  906. storage.rd_resume_position = 0
  907. return storage, t
  908. def test_virtual_adder_int_constants():
  909. b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**16), ConstInt(-65)]
  910. storage, t = make_storage(b1s, b2s, b3s)
  911. metainterp_sd = FakeMetaInterpStaticData()
  912. memo = ResumeDataLoopMemo(metainterp_sd)
  913. i = t.get_iter()
  914. modifier = ResumeDataVirtualAdder(FakeOptimizer(i), storage, storage, i, memo)
  915. liveboxes = modifier.finish(FakeOptimizer(i))
  916. cpu = MyCPU([])
  917. reader = ResumeDataDirectReader(MyMetaInterp(cpu), storage, "deadframe")
  918. reader.consume_vref_and_vable(None, None, None)
  919. reader.cur_index += 2 # framestack
  920. _next_section(reader, sys.maxint, 1, sys.maxint, 2**16)
  921. reader.cur_index += 2 # framestack
  922. _next_section(reader, 2, 3)
  923. reader.cur_index += 2 # framestack
  924. _next_section(reader, sys.maxint, 2**16, -65)
  925. def test_virtual_adder_memo_const_sharing():
  926. b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**16), ConstInt(-65)]
  927. storage, t = make_storage(b1s, b2s, b3s)
  928. metainterp_sd = FakeMetaInterpStaticData()
  929. memo = ResumeDataLoopMemo(metainterp_sd)
  930. i = t.get_iter()
  931. modifier = ResumeDataVirtualAdder(FakeOptimizer(i), storage, storage, i, memo)
  932. modifier.finish(FakeOptimizer(i))
  933. assert len(memo.consts) == 2
  934. assert storage.rd_consts is memo.consts
  935. b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**17), ConstInt(-65)]
  936. storage2, t = make_storage(b1s, b2s, b3s)
  937. i = t.get_iter()
  938. modifier2 = ResumeDataVirtualAdder(FakeOptimizer(i), storage2, storage2,
  939. i, memo)
  940. modifier2.finish(FakeOptimizer(i))
  941. assert len(memo.consts) == 3
  942. assert storage2.rd_consts is memo.consts
  943. class ResumeDataFakeReader(ResumeDataBoxReader):
  944. """Another subclass of AbstractResumeDataReader meant for tests."""
  945. def __init__(self, storage, newboxes, metainterp):
  946. self._init(metainterp.cpu, storage)
  947. self.liveboxes = newboxes
  948. self.metainterp = metainterp
  949. self._prepare(storage)
  950. def consume_boxes(self):
  951. self.lst = []
  952. class Whatever:
  953. def __eq__(self, other):
  954. return True
  955. class MyInfo:
  956. @staticmethod
  957. def enumerate_vars(callback_i, callback_r, callback_f, _, index):
  958. while index < len(self.numb.code):
  959. tagged, _ = resumecode.numb_next_item(self.numb, index)
  960. _, tag = untag(tagged)
  961. if tag == TAGVIRTUAL:
  962. kind = REF
  963. else:
  964. kind = Whatever()
  965. box = self.decode_box(tagged, kind)
  966. if box.type == INT:
  967. index = callback_i(index, index)
  968. elif box.type == REF:
  969. index = callback_r(index, index)
  970. elif box.type == FLOAT:
  971. index = callback_f(index, index)
  972. else:
  973. assert 0
  974. size, self.cur_index = resumecode.numb_next_item(self.numb, 0)
  975. assert size == 0
  976. size, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index)
  977. assert size == 0
  978. pc, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index)
  979. jitcode_pos, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index)
  980. self._prepare_next_section(MyInfo())
  981. return self.lst
  982. def write_an_int(self, count_i, box):
  983. assert box.type == INT
  984. self.lst.append(box)
  985. def write_a_ref(self, count_r, box):
  986. assert box.type == REF
  987. self.lst.append(box)
  988. def write_a_float(self, count_f, box):
  989. assert box.type == FLOAT
  990. self.lst.append(box)
  991. def test_virtual_adder_no_op_renaming():
  992. py.test.skip("rewrite fake reader")
  993. b1s, b2s, b3s = [InputArgInt(1), InputArgInt(2), InputArgInt(3)]
  994. storage = make_storage(b1s, b2s, b3s)
  995. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  996. b1_2 = InputArgInt()
  997. modifier = ResumeDataVirtualAdder(FakeOptimizer(), storage, storage, memo)
  998. b1s.set_forwarded(b1_2)
  999. b2s.set_forwarded(b1_2)
  1000. liveboxes = modifier.finish(FakeOptimizer())
  1001. assert storage.rd_snapshot is None
  1002. b1t, b3t = [InputArgInt(11), InputArgInt(33)]
  1003. newboxes = _resume_remap(liveboxes, [b1_2, b3s], b1t, b3t)
  1004. metainterp = MyMetaInterp()
  1005. reader = ResumeDataFakeReader(storage, newboxes, metainterp)
  1006. lst = reader.consume_boxes()
  1007. assert_same(lst, [b1t, b1t, b3t])
  1008. lst = reader.consume_boxes()
  1009. assert_same(lst, [ConstInt(2), ConstInt(3)])
  1010. lst = reader.consume_boxes()
  1011. assert_same(lst, [b1t, ConstInt(1), b1t, b1t])
  1012. assert metainterp.trace == []
  1013. def test_virtual_adder_make_constant():
  1014. py.test.skip("rewrite fake reader")
  1015. b1s, b2s, b3s = [InputArgInt(1), InputArgRef(), InputArgInt(3)]
  1016. b1s = ConstInt(111)
  1017. storage = make_storage(b1s, b2s, b3s)
  1018. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  1019. modifier = ResumeDataVirtualAdder(FakeOptimizer(), storage, storage, memo)
  1020. liveboxes = modifier.finish(FakeOptimizer())
  1021. b2t, b3t = [InputArgRef(demo55o), InputArgInt(33)]
  1022. newboxes = _resume_remap(liveboxes, [b2s, b3s], b2t, b3t)
  1023. metainterp = MyMetaInterp()
  1024. reader = ResumeDataFakeReader(storage, newboxes, metainterp)
  1025. lst = reader.consume_boxes()
  1026. c1t = ConstInt(111)
  1027. assert_same(lst, [c1t, b2t, b3t])
  1028. lst = reader.consume_boxes()
  1029. assert_same(lst, [ConstInt(2), ConstInt(3)])
  1030. lst = reader.consume_boxes()
  1031. assert_same(lst, [c1t, ConstInt(1), c1t, b2t])
  1032. assert metainterp.trace == []
  1033. def test_virtual_adder_make_virtual():
  1034. b2s, b3s, b4s, b5s = [IntFrontendOp(0), IntFrontendOp(0), RefFrontendOp(0),
  1035. RefFrontendOp(0)]
  1036. c1s = ConstInt(111)
  1037. storage = Storage()
  1038. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  1039. modifier = ResumeDataVirtualAdder(FakeOptimizer(), storage, storage, None, memo)
  1040. modifier.liveboxes_from_env = {}
  1041. modifier.liveboxes = {}
  1042. modifier.vfieldboxes = {}
  1043. vdescr = LLtypeMixin.nodesize2
  1044. ca = ConstAddr(LLtypeMixin.node_vtable_adr2, LLtypeMixin.cpu)
  1045. v4 = info.InstancePtrInfo(vdescr, ca, True)
  1046. b4s.set_forwarded(v4)
  1047. v4.setfield(LLtypeMixin.nextdescr, ca, b2s)
  1048. v4.setfield(LLtypeMixin.valuedescr, ca, b3s)
  1049. v4.setfield(LLtypeMixin.otherdescr, ca, b5s)
  1050. ca = ConstAddr(LLtypeMixin.node_vtable_adr, LLtypeMixin.cpu)
  1051. v2 = info.InstancePtrInfo(LLtypeMixin.nodesize, ca, True)
  1052. v2.setfield(LLtypeMixin.nextdescr, b4s, ca)
  1053. v2.setfield(LLtypeMixin.valuedescr, c1s, ca)
  1054. b2s.set_forwarded(v2)
  1055. modifier.register_virtual_fields(b2s, [c1s, None, None, None, b4s])
  1056. modifier.register_virtual_fields(b4s, [b3s, None, None, None, b2s, b5s])
  1057. liveboxes = []
  1058. modifier._number_virtuals(liveboxes, FakeOptimizer(), 0)
  1059. storage.rd_consts = memo.consts[:]
  1060. storage.rd_numb = None
  1061. # resume
  1062. b3t, b5t = [IntFrontendOp(0), RefFrontendOp(0)]
  1063. b5t.setref_base(demo55o)
  1064. b3t.setint(33)
  1065. newboxes = _resume_remap(liveboxes, [#b2s -- virtual
  1066. b3s,
  1067. #b4s -- virtual
  1068. #b2s -- again, shared
  1069. #b3s -- again, shared
  1070. b5s], b3t, b5t)
  1071. metainterp = MyMetaInterp()
  1072. reader = ResumeDataFakeReader(storage, newboxes, metainterp)
  1073. assert len(reader.virtuals_cache.virtuals_ptr_cache) == 2
  1074. b2t = reader.decode_ref(modifier._gettagged(b2s))
  1075. b4t = reader.decode_ref(modifier._gettagged(b4s))
  1076. trace = metainterp.trace
  1077. b2new = (rop.NEW_WITH_VTABLE, [], b2t.getref_base(), LLtypeMixin.nodesize)
  1078. b4new = (rop.NEW_WITH_VTABLE, [], b4t.getref_base(), LLtypeMixin.nodesize2)
  1079. b2set = [(rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr),
  1080. (rop.SETFIELD_GC, [b2t, c1s], None, LLtypeMixin.valuedescr)]
  1081. b4set = [(rop.SETFIELD_GC, [b4t, b2t], None, LLtypeMixin.nextdescr),
  1082. (rop.SETFIELD_GC, [b4t, b3t], None, LLtypeMixin.valuedescr),
  1083. (rop.SETFIELD_GC, [b4t, b5t], None, LLtypeMixin.otherdescr)]
  1084. expected = [b2new, b4new] + b4set + b2set
  1085. # check that we get the operations in 'expected', in a possibly different
  1086. # order.
  1087. assert len(trace) == len(expected)
  1088. orig = trace[:]
  1089. with CompareableConsts():
  1090. for x in trace:
  1091. assert x in expected
  1092. expected.remove(x)
  1093. ptr = b2t.getref_base()._obj.container._as_ptr()
  1094. assert lltype.typeOf(ptr) == lltype.Ptr(LLtypeMixin.NODE)
  1095. assert ptr.value == 111
  1096. ptr2 = ptr.next
  1097. ptr2 = lltype.cast_pointer(lltype.Ptr(LLtypeMixin.NODE2), ptr2)
  1098. assert ptr2.other == demo55
  1099. assert ptr2.parent.value == 33
  1100. assert ptr2.parent.next == ptr
  1101. class CompareableConsts(object):
  1102. def __enter__(self):
  1103. Const.__eq__ = Const.same_box
  1104. def __exit__(self, type, value, traceback):
  1105. del Const.__eq__
  1106. def test_virtual_adder_make_varray():
  1107. b2s, b4s = [IntFrontendOp(0), IntFrontendOp(0)]
  1108. b4s.setint(4)
  1109. c1s = ConstInt(111)
  1110. storage = Storage()
  1111. memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
  1112. modifier = ResumeDataVirtualAdder(FakeOptimizer(), storage, storage, None, memo)
  1113. modifier.liveboxes_from_env = {}
  1114. modifier.liveboxes = {}
  1115. modifier.vfieldboxes = {}
  1116. v2 = info.ArrayPtrInfo(LLtypeMixin.arraydescr, size=2, is_virtual=True)
  1117. b2s.set_forwarded(v2)
  1118. v2._items = [b4s, c1s]
  1119. modifier.register_virtual_fields(b2s, [b4s, c1s])
  1120. liveboxes = []
  1121. modifier._number_virtuals(liveboxes, FakeOptimizer(), 0)
  1122. dump_storage(storage, liveboxes)
  1123. storage.rd_consts = memo.consts[:]
  1124. storage.rd_numb = None
  1125. # resume
  1126. b1t, b3t, b4t = [IntFrontendOp(0), IntFrontendOp

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