PageRenderTime 110ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/rpython/jit/metainterp/resume.py

https://bitbucket.org/pypy/pypy/
Python | 1611 lines | 1263 code | 240 blank | 108 comment | 203 complexity | 45e7648facf1522b499ff2ba98e8750a 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 rpython.jit.codewriter.effectinfo import EffectInfo
  2. from rpython.jit.metainterp import jitprof
  3. from rpython.jit.metainterp.history import (Const, ConstInt, getkind,
  4. INT, REF, FLOAT, AbstractDescr, IntFrontendOp, RefFrontendOp,
  5. FloatFrontendOp)
  6. from rpython.jit.metainterp.resoperation import rop
  7. from rpython.rlib import rarithmetic, rstack
  8. from rpython.rlib.objectmodel import (we_are_translated, specialize,
  9. compute_unique_id)
  10. from rpython.rlib.debug import ll_assert, debug_print
  11. from rpython.rtyper import annlowlevel
  12. from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
  13. from rpython.rtyper.rclass import OBJECTPTR
  14. from rpython.jit.metainterp.walkvirtual import VirtualVisitor
  15. from rpython.jit.metainterp import resumecode
  16. # Logic to encode the chain of frames and the state of the boxes at a
  17. # guard operation, and to decode it again. This is a bit advanced,
  18. # because it needs to support optimize.py which encodes virtuals with
  19. # arbitrary cycles and also to compress the information
  20. class VectorInfo(object):
  21. """
  22. prev: the previous VectorInfo or None
  23. failargs_pos: the index where to find it in the fail arguments
  24. location: the register location (an integer), specified by the backend
  25. variable: the original variable that lived at failargs_pos
  26. """
  27. _attrs_ = ('prev', 'failargs_pos', 'location', 'variable')
  28. prev = None
  29. failargs_pos = -1
  30. location = None
  31. variable = None
  32. def __init__(self, position, variable):
  33. self.failargs_pos = position
  34. self.variable = variable
  35. def getpos_in_failargs(self):
  36. return self.failargs_pos
  37. def next(self):
  38. return self.prev
  39. def getoriginal(self):
  40. return self.variable
  41. def clone(self):
  42. prev = None
  43. if self.prev:
  44. prev = self.prev.clone()
  45. return self.instance_clone(prev)
  46. def instance_clone(self, prev):
  47. raise NotImplementedError
  48. class UnpackAtExitInfo(VectorInfo):
  49. def instance_clone(self, prev):
  50. info = UnpackAtExitInfo(self.failargs_pos, self.variable)
  51. info.prev = prev
  52. return info
  53. class AccumInfo(VectorInfo):
  54. _attrs_ = ('accum_operation', 'scalar')
  55. def __init__(self, position, variable, operation):
  56. VectorInfo.__init__(self, position, variable)
  57. self.accum_operation = operation
  58. def instance_clone(self, prev):
  59. info = AccumInfo(self.failargs_pos, self.variable,
  60. self.accum_operation)
  61. info.location = self.location
  62. info.prev = prev
  63. return info
  64. def __repr__(self):
  65. return 'AccumInfo(%s,%s,%s,%s,%s)' % (self.prev is None,
  66. self.accum_operation,
  67. self.failargs_pos,
  68. self.variable,
  69. self.location)
  70. def _ensure_parent_resumedata(framestack, n, t, snapshot):
  71. if n == 0:
  72. return
  73. target = framestack[n]
  74. back = framestack[n - 1]
  75. if target.parent_snapshot:
  76. snapshot.prev = target.parent_snapshot
  77. return
  78. s = t.create_snapshot(back.jitcode, back.pc, back, True)
  79. snapshot.prev = s
  80. _ensure_parent_resumedata(framestack, n - 1, t, s)
  81. target.parent_snapshot = s
  82. def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, t):
  83. n = len(framestack) - 1
  84. result = t.length()
  85. if virtualizable_boxes is not None:
  86. virtualizable_boxes = ([virtualizable_boxes[-1]] +
  87. virtualizable_boxes[:-1])
  88. else:
  89. virtualizable_boxes = []
  90. virtualref_boxes = virtualref_boxes[:]
  91. if n >= 0:
  92. top = framestack[n]
  93. snapshot = t.create_top_snapshot(top.jitcode, top.pc,
  94. top, False, virtualizable_boxes,
  95. virtualref_boxes)
  96. _ensure_parent_resumedata(framestack, n, t,snapshot)
  97. else:
  98. snapshot = t.create_empty_top_snapshot(
  99. virtualizable_boxes, virtualref_boxes)
  100. return result
  101. PENDINGFIELDSTRUCT = lltype.Struct('PendingField',
  102. ('lldescr', OBJECTPTR),
  103. ('num', rffi.SHORT),
  104. ('fieldnum', rffi.SHORT),
  105. ('itemindex', rffi.INT))
  106. PENDINGFIELDSP = lltype.Ptr(lltype.GcArray(PENDINGFIELDSTRUCT))
  107. TAGMASK = 3
  108. class TagOverflow(Exception):
  109. pass
  110. def tag(value, tagbits):
  111. assert 0 <= tagbits <= 3
  112. sx = value >> 13
  113. if sx != 0 and sx != -1:
  114. raise TagOverflow
  115. return rffi.r_short(value<<2|tagbits)
  116. def untag(value):
  117. value = rarithmetic.widen(value)
  118. tagbits = value & TAGMASK
  119. return value >> 2, tagbits
  120. def tagged_eq(x, y):
  121. # please rpython :(
  122. return rarithmetic.widen(x) == rarithmetic.widen(y)
  123. def tagged_list_eq(tl1, tl2):
  124. if len(tl1) != len(tl2):
  125. return False
  126. for i in range(len(tl1)):
  127. if not tagged_eq(tl1[i], tl2[i]):
  128. return False
  129. return True
  130. TAGCONST = 0
  131. TAGINT = 1
  132. TAGBOX = 2
  133. TAGVIRTUAL = 3
  134. UNASSIGNED = tag(-1 << 13, TAGBOX)
  135. UNASSIGNEDVIRTUAL = tag(-1 << 13, TAGVIRTUAL)
  136. NULLREF = tag(-1, TAGCONST)
  137. UNINITIALIZED = tag(-2, TAGCONST) # used for uninitialized string characters
  138. TAG_CONST_OFFSET = 0
  139. class NumberingState(object):
  140. def __init__(self, size):
  141. self.liveboxes = {}
  142. self.current = [0] * size
  143. self._pos = 0
  144. self.n = 0
  145. self.v = 0
  146. def append(self, item):
  147. self.current[self._pos] = item
  148. self._pos += 1
  149. class ResumeDataLoopMemo(object):
  150. def __init__(self, metainterp_sd):
  151. self.metainterp_sd = metainterp_sd
  152. self.cpu = metainterp_sd.cpu
  153. self.consts = []
  154. self.large_ints = {}
  155. self.refs = self.cpu.ts.new_ref_dict_2()
  156. self.numberings = {}
  157. self.cached_boxes = {}
  158. self.cached_virtuals = {}
  159. self.nvirtuals = 0
  160. self.nvholes = 0
  161. self.nvreused = 0
  162. def getconst(self, const):
  163. if const.type == INT:
  164. val = const.getint()
  165. if not we_are_translated() and not isinstance(val, int):
  166. # unhappiness, probably a symbolic
  167. return self._newconst(const)
  168. try:
  169. return tag(val, TAGINT)
  170. except TagOverflow:
  171. pass
  172. tagged = self.large_ints.get(val, UNASSIGNED)
  173. if not tagged_eq(tagged, UNASSIGNED):
  174. return tagged
  175. tagged = self._newconst(const)
  176. self.large_ints[val] = tagged
  177. return tagged
  178. elif const.type == REF:
  179. val = const.getref_base()
  180. if not val:
  181. return NULLREF
  182. tagged = self.refs.get(val, UNASSIGNED)
  183. if not tagged_eq(tagged, UNASSIGNED):
  184. return tagged
  185. tagged = self._newconst(const)
  186. self.refs[val] = tagged
  187. return tagged
  188. return self._newconst(const)
  189. def _newconst(self, const):
  190. result = tag(len(self.consts) + TAG_CONST_OFFSET, TAGCONST)
  191. self.consts.append(const)
  192. return result
  193. # env numbering
  194. def _number_boxes(self, iter, arr, optimizer, state):
  195. """ Number boxes from one snapshot
  196. """
  197. n = state.n
  198. v = state.v
  199. liveboxes = state.liveboxes
  200. for item in arr:
  201. box = iter.get(rffi.cast(lltype.Signed, item))
  202. box = optimizer.get_box_replacement(box)
  203. if isinstance(box, Const):
  204. tagged = self.getconst(box)
  205. elif box in liveboxes:
  206. tagged = liveboxes[box]
  207. else:
  208. is_virtual = False
  209. if box.type == 'r':
  210. info = optimizer.getptrinfo(box)
  211. is_virtual = (info is not None and info.is_virtual())
  212. if box.type == 'i':
  213. info = optimizer.getrawptrinfo(box, create=False)
  214. is_virtual = (info is not None and info.is_virtual())
  215. if is_virtual:
  216. tagged = tag(v, TAGVIRTUAL)
  217. v += 1
  218. else:
  219. tagged = tag(n, TAGBOX)
  220. n += 1
  221. liveboxes[box] = tagged
  222. state.append(tagged)
  223. state.n = n
  224. state.v = v
  225. def number(self, optimizer, position, trace):
  226. snapshot_iter = trace.get_snapshot_iter(position)
  227. state = NumberingState(snapshot_iter.size)
  228. arr = snapshot_iter.vable_array
  229. state.append(rffi.cast(rffi.SHORT, len(arr)))
  230. self._number_boxes(snapshot_iter, arr, optimizer, state)
  231. arr = snapshot_iter.vref_array
  232. n = len(arr)
  233. assert not (n & 1)
  234. state.append(rffi.cast(rffi.SHORT, n >> 1))
  235. self._number_boxes(snapshot_iter, arr, optimizer, state)
  236. for snapshot in snapshot_iter.framestack:
  237. jitcode_index, pc = snapshot_iter.unpack_jitcode_pc(snapshot)
  238. state.append(rffi.cast(rffi.SHORT, jitcode_index))
  239. state.append(rffi.cast(rffi.SHORT, pc))
  240. self._number_boxes(snapshot_iter, snapshot.box_array, optimizer, state)
  241. numb = resumecode.create_numbering(state.current)
  242. return numb, state.liveboxes, state.v
  243. def forget_numberings(self):
  244. # XXX ideally clear only the affected numberings
  245. self.numberings.clear()
  246. self.clear_box_virtual_numbers()
  247. # caching for virtuals and boxes inside them
  248. def num_cached_boxes(self):
  249. return len(self.cached_boxes)
  250. def assign_number_to_box(self, box, boxes):
  251. # returns a negative number
  252. if box in self.cached_boxes:
  253. num = self.cached_boxes[box]
  254. boxes[-num - 1] = box
  255. else:
  256. boxes.append(box)
  257. num = -len(boxes)
  258. self.cached_boxes[box] = num
  259. return num
  260. def num_cached_virtuals(self):
  261. return len(self.cached_virtuals)
  262. def assign_number_to_virtual(self, box):
  263. # returns a negative number
  264. if box in self.cached_virtuals:
  265. num = self.cached_virtuals[box]
  266. else:
  267. num = self.cached_virtuals[box] = -len(self.cached_virtuals) - 1
  268. return num
  269. def clear_box_virtual_numbers(self):
  270. self.cached_boxes.clear()
  271. self.cached_virtuals.clear()
  272. def update_counters(self, profiler):
  273. profiler.count(jitprof.Counters.NVIRTUALS, self.nvirtuals)
  274. profiler.count(jitprof.Counters.NVHOLES, self.nvholes)
  275. profiler.count(jitprof.Counters.NVREUSED, self.nvreused)
  276. _frame_info_placeholder = (None, 0, 0)
  277. class ResumeDataVirtualAdder(VirtualVisitor):
  278. def __init__(self, optimizer, storage, guard_op, trace, memo):
  279. self.optimizer = optimizer
  280. self.trace = trace
  281. self.storage = storage
  282. self.guard_op = guard_op
  283. self.memo = memo
  284. def make_virtual_info(self, info, fieldnums):
  285. assert fieldnums is not None
  286. vinfo = info._cached_vinfo
  287. if vinfo is not None and vinfo.equals(fieldnums):
  288. return vinfo
  289. vinfo = info.visitor_dispatch_virtual_type(self)
  290. vinfo.set_content(fieldnums)
  291. info._cached_vinfo = vinfo
  292. return vinfo
  293. def visit_not_virtual(self, value):
  294. assert 0, "unreachable"
  295. def visit_virtual(self, descr, fielddescrs):
  296. return VirtualInfo(descr, fielddescrs)
  297. def visit_vstruct(self, typedescr, fielddescrs):
  298. return VStructInfo(typedescr, fielddescrs)
  299. def visit_varray(self, arraydescr, clear):
  300. if clear:
  301. return VArrayInfoClear(arraydescr)
  302. else:
  303. return VArrayInfoNotClear(arraydescr)
  304. def visit_varraystruct(self, arraydescr, size, fielddescrs):
  305. return VArrayStructInfo(arraydescr, size, fielddescrs)
  306. def visit_vrawbuffer(self, size, offsets, descrs):
  307. return VRawBufferInfo(size, offsets, descrs)
  308. def visit_vrawslice(self, offset):
  309. return VRawSliceInfo(offset)
  310. def visit_vstrplain(self, is_unicode=False):
  311. if is_unicode:
  312. return VUniPlainInfo()
  313. else:
  314. return VStrPlainInfo()
  315. def visit_vstrconcat(self, is_unicode=False):
  316. if is_unicode:
  317. return VUniConcatInfo()
  318. else:
  319. return VStrConcatInfo()
  320. def visit_vstrslice(self, is_unicode=False):
  321. if is_unicode:
  322. return VUniSliceInfo()
  323. else:
  324. return VStrSliceInfo()
  325. def register_virtual_fields(self, virtualbox, _fieldboxes):
  326. tagged = self.liveboxes_from_env.get(virtualbox, UNASSIGNEDVIRTUAL)
  327. self.liveboxes[virtualbox] = tagged
  328. fieldboxes = []
  329. for box in _fieldboxes:
  330. if box is not None:
  331. box = self.optimizer.get_box_replacement(box)
  332. fieldboxes.append(box)
  333. self.vfieldboxes[virtualbox] = fieldboxes
  334. self._register_boxes(fieldboxes)
  335. def register_box(self, box):
  336. if (box is not None and not isinstance(box, Const)
  337. and box not in self.liveboxes_from_env
  338. and box not in self.liveboxes):
  339. self.liveboxes[box] = UNASSIGNED
  340. def _register_boxes(self, boxes):
  341. for box in boxes:
  342. self.register_box(box)
  343. def already_seen_virtual(self, virtualbox):
  344. if virtualbox not in self.liveboxes:
  345. assert virtualbox in self.liveboxes_from_env
  346. assert untag(self.liveboxes_from_env[virtualbox])[1] == TAGVIRTUAL
  347. return False
  348. tagged = self.liveboxes[virtualbox]
  349. _, tagbits = untag(tagged)
  350. return tagbits == TAGVIRTUAL
  351. def finish(self, optimizer, pending_setfields=[]):
  352. # compute the numbering
  353. storage = self.storage
  354. # make sure that nobody attached resume data to this guard yet
  355. assert not storage.rd_numb
  356. resume_position = self.guard_op.rd_resume_position
  357. assert resume_position >= 0
  358. # count stack depth
  359. numb, liveboxes_from_env, v = self.memo.number(optimizer,
  360. resume_position, self.optimizer.trace)
  361. self.liveboxes_from_env = liveboxes_from_env
  362. self.liveboxes = {}
  363. storage.rd_numb = numb
  364. # collect liveboxes and virtuals
  365. n = len(liveboxes_from_env) - v
  366. liveboxes = [None] * n
  367. self.vfieldboxes = {}
  368. for box, tagged in liveboxes_from_env.iteritems():
  369. i, tagbits = untag(tagged)
  370. if tagbits == TAGBOX:
  371. liveboxes[i] = box
  372. else:
  373. assert tagbits == TAGVIRTUAL
  374. if box.type == 'r':
  375. info = optimizer.getptrinfo(box)
  376. else:
  377. assert box.type == 'i'
  378. info = optimizer.getrawptrinfo(box)
  379. assert info.is_virtual()
  380. info.visitor_walk_recursive(box, self, optimizer)
  381. for setfield_op in pending_setfields:
  382. box = setfield_op.getarg(0)
  383. box = optimizer.get_box_replacement(box)
  384. if setfield_op.getopnum() == rop.SETFIELD_GC:
  385. fieldbox = setfield_op.getarg(1)
  386. else:
  387. fieldbox = setfield_op.getarg(2)
  388. fieldbox = optimizer.get_box_replacement(fieldbox)
  389. self.register_box(box)
  390. self.register_box(fieldbox)
  391. info = optimizer.getptrinfo(fieldbox)
  392. assert info is not None and info.is_virtual()
  393. info.visitor_walk_recursive(fieldbox, self, optimizer)
  394. self._number_virtuals(liveboxes, optimizer, v)
  395. self._add_pending_fields(optimizer, pending_setfields)
  396. storage.rd_consts = self.memo.consts
  397. return liveboxes[:]
  398. def _number_virtuals(self, liveboxes, optimizer, num_env_virtuals):
  399. from rpython.jit.metainterp.optimizeopt.info import AbstractVirtualPtrInfo
  400. # !! 'liveboxes' is a list that is extend()ed in-place !!
  401. memo = self.memo
  402. new_liveboxes = [None] * memo.num_cached_boxes()
  403. count = 0
  404. # So far, self.liveboxes should contain 'tagged' values that are
  405. # either UNASSIGNED, UNASSIGNEDVIRTUAL, or a *non-negative* value
  406. # with the TAGVIRTUAL. The following loop removes the UNASSIGNED
  407. # and UNASSIGNEDVIRTUAL entries, and replaces them with real
  408. # negative values.
  409. for box, tagged in self.liveboxes.iteritems():
  410. i, tagbits = untag(tagged)
  411. if tagbits == TAGBOX:
  412. assert box not in self.liveboxes_from_env
  413. assert tagged_eq(tagged, UNASSIGNED)
  414. index = memo.assign_number_to_box(box, new_liveboxes)
  415. self.liveboxes[box] = tag(index, TAGBOX)
  416. count += 1
  417. else:
  418. assert tagbits == TAGVIRTUAL
  419. if tagged_eq(tagged, UNASSIGNEDVIRTUAL):
  420. assert box not in self.liveboxes_from_env
  421. index = memo.assign_number_to_virtual(box)
  422. self.liveboxes[box] = tag(index, TAGVIRTUAL)
  423. else:
  424. assert i >= 0
  425. new_liveboxes.reverse()
  426. liveboxes.extend(new_liveboxes)
  427. nholes = len(new_liveboxes) - count
  428. storage = self.storage
  429. storage.rd_virtuals = None
  430. vfieldboxes = self.vfieldboxes
  431. if vfieldboxes:
  432. length = num_env_virtuals + memo.num_cached_virtuals()
  433. virtuals = storage.rd_virtuals = [None] * length
  434. memo.nvirtuals += length
  435. memo.nvholes += length - len(vfieldboxes)
  436. for virtualbox, fieldboxes in vfieldboxes.iteritems():
  437. num, _ = untag(self.liveboxes[virtualbox])
  438. info = optimizer.getptrinfo(virtualbox)
  439. assert info.is_virtual()
  440. assert isinstance(info, AbstractVirtualPtrInfo)
  441. fieldnums = [self._gettagged(box)
  442. for box in fieldboxes]
  443. vinfo = self.make_virtual_info(info, fieldnums)
  444. # if a new vinfo instance is made, we get the fieldnums list we
  445. # pass in as an attribute. hackish.
  446. if vinfo.fieldnums is not fieldnums:
  447. memo.nvreused += 1
  448. virtuals[num] = vinfo
  449. if self._invalidation_needed(len(liveboxes), nholes):
  450. memo.clear_box_virtual_numbers()
  451. def _invalidation_needed(self, nliveboxes, nholes):
  452. memo = self.memo
  453. # xxx heuristic a bit out of thin air
  454. failargs_limit = memo.metainterp_sd.options.failargs_limit
  455. if nliveboxes > (failargs_limit // 2):
  456. if nholes > nliveboxes // 3:
  457. return True
  458. return False
  459. def _add_pending_fields(self, optimizer, pending_setfields):
  460. rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
  461. if pending_setfields:
  462. n = len(pending_setfields)
  463. rd_pendingfields = lltype.malloc(PENDINGFIELDSP.TO, n)
  464. for i in range(n):
  465. op = pending_setfields[i]
  466. box = optimizer.get_box_replacement(op.getarg(0))
  467. descr = op.getdescr()
  468. opnum = op.getopnum()
  469. if opnum == rop.SETARRAYITEM_GC:
  470. fieldbox = op.getarg(2)
  471. boxindex = optimizer.get_box_replacement(op.getarg(1))
  472. itemindex = boxindex.getint()
  473. # sanity: it's impossible to run code with SETARRAYITEM_GC
  474. # with negative index, so this guard cannot ever fail;
  475. # but it's possible to try to *build* such invalid code
  476. if itemindex < 0:
  477. raise TagOverflow
  478. elif opnum == rop.SETFIELD_GC:
  479. fieldbox = op.getarg(1)
  480. itemindex = -1
  481. else:
  482. raise AssertionError
  483. fieldbox = optimizer.get_box_replacement(fieldbox)
  484. #descr, box, fieldbox, itemindex = pending_setfields[i]
  485. lldescr = annlowlevel.cast_instance_to_base_ptr(descr)
  486. num = self._gettagged(box)
  487. fieldnum = self._gettagged(fieldbox)
  488. # the index is limited to 2147483647 (64-bit machines only)
  489. if itemindex > 2147483647:
  490. raise TagOverflow
  491. #
  492. rd_pendingfields[i].lldescr = lldescr
  493. rd_pendingfields[i].num = num
  494. rd_pendingfields[i].fieldnum = fieldnum
  495. rd_pendingfields[i].itemindex = rffi.cast(rffi.INT, itemindex)
  496. self.storage.rd_pendingfields = rd_pendingfields
  497. def _gettagged(self, box):
  498. if box is None:
  499. return UNINITIALIZED
  500. if isinstance(box, Const):
  501. return self.memo.getconst(box)
  502. else:
  503. if box in self.liveboxes_from_env:
  504. return self.liveboxes_from_env[box]
  505. return self.liveboxes[box]
  506. class AbstractVirtualInfo(object):
  507. kind = REF
  508. is_about_raw = False
  509. #def allocate(self, decoder, index):
  510. # raise NotImplementedError
  511. def equals(self, fieldnums):
  512. return tagged_list_eq(self.fieldnums, fieldnums)
  513. def set_content(self, fieldnums):
  514. self.fieldnums = fieldnums
  515. def debug_prints(self):
  516. raise NotImplementedError
  517. class AbstractVirtualStructInfo(AbstractVirtualInfo):
  518. def __init__(self, fielddescrs):
  519. self.fielddescrs = fielddescrs
  520. #self.fieldnums = ...
  521. @specialize.argtype(1)
  522. def setfields(self, decoder, struct):
  523. for i in range(len(self.fielddescrs)):
  524. descr = self.fielddescrs[i]
  525. num = self.fieldnums[i]
  526. if not tagged_eq(num, UNINITIALIZED):
  527. decoder.setfield(struct, num, descr)
  528. return struct
  529. def debug_prints(self):
  530. assert len(self.fielddescrs) == len(self.fieldnums)
  531. for i in range(len(self.fielddescrs)):
  532. debug_print("\t\t",
  533. str(self.fielddescrs[i]),
  534. str(untag(self.fieldnums[i])))
  535. class VirtualInfo(AbstractVirtualStructInfo):
  536. def __init__(self, descr, fielddescrs):
  537. AbstractVirtualStructInfo.__init__(self, fielddescrs)
  538. self.descr = descr
  539. @specialize.argtype(1)
  540. def allocate(self, decoder, index):
  541. struct = decoder.allocate_with_vtable(descr=self.descr)
  542. decoder.virtuals_cache.set_ptr(index, struct)
  543. return self.setfields(decoder, struct)
  544. def debug_prints(self):
  545. debug_print("\tvirtualinfo", self.known_class.repr_rpython(), " at ", compute_unique_id(self))
  546. AbstractVirtualStructInfo.debug_prints(self)
  547. class VStructInfo(AbstractVirtualStructInfo):
  548. def __init__(self, typedescr, fielddescrs):
  549. AbstractVirtualStructInfo.__init__(self, fielddescrs)
  550. self.typedescr = typedescr
  551. @specialize.argtype(1)
  552. def allocate(self, decoder, index):
  553. struct = decoder.allocate_struct(self.typedescr)
  554. decoder.virtuals_cache.set_ptr(index, struct)
  555. return self.setfields(decoder, struct)
  556. def debug_prints(self):
  557. debug_print("\tvstructinfo", self.typedescr.repr_rpython(), " at ", compute_unique_id(self))
  558. AbstractVirtualStructInfo.debug_prints(self)
  559. class AbstractVArrayInfo(AbstractVirtualInfo):
  560. def __init__(self, arraydescr):
  561. assert arraydescr is not None
  562. self.arraydescr = arraydescr
  563. #self.fieldnums = ...
  564. @specialize.argtype(1)
  565. def allocate(self, decoder, index):
  566. length = len(self.fieldnums)
  567. arraydescr = self.arraydescr
  568. array = decoder.allocate_array(length, arraydescr, self.clear)
  569. decoder.virtuals_cache.set_ptr(index, array)
  570. # NB. the check for the kind of array elements is moved out of the loop
  571. if arraydescr.is_array_of_pointers():
  572. for i in range(length):
  573. num = self.fieldnums[i]
  574. if not tagged_eq(num, UNINITIALIZED):
  575. decoder.setarrayitem_ref(array, i, num, arraydescr)
  576. elif arraydescr.is_array_of_floats():
  577. for i in range(length):
  578. num = self.fieldnums[i]
  579. if not tagged_eq(num, UNINITIALIZED):
  580. decoder.setarrayitem_float(array, i, num, arraydescr)
  581. else:
  582. for i in range(length):
  583. num = self.fieldnums[i]
  584. if not tagged_eq(num, UNINITIALIZED):
  585. decoder.setarrayitem_int(array, i, num, arraydescr)
  586. return array
  587. def debug_prints(self):
  588. debug_print("\tvarrayinfo", self.arraydescr, " at ",
  589. compute_unique_id(self), " clear=", self.clear)
  590. for i in self.fieldnums:
  591. debug_print("\t\t", str(untag(i)))
  592. class VArrayInfoClear(AbstractVArrayInfo):
  593. clear = True
  594. class VArrayInfoNotClear(AbstractVArrayInfo):
  595. clear = False
  596. class VAbstractRawInfo(AbstractVirtualInfo):
  597. kind = INT
  598. is_about_raw = True
  599. class VRawBufferInfo(VAbstractRawInfo):
  600. def __init__(self, size, offsets, descrs):
  601. self.size = size
  602. self.offsets = offsets
  603. self.descrs = descrs
  604. @specialize.argtype(1)
  605. def allocate_int(self, decoder, index):
  606. length = len(self.fieldnums)
  607. buffer = decoder.allocate_raw_buffer(self.size)
  608. decoder.virtuals_cache.set_int(index, buffer)
  609. for i in range(len(self.offsets)):
  610. offset = self.offsets[i]
  611. descr = self.descrs[i]
  612. decoder.setrawbuffer_item(buffer, self.fieldnums[i], offset, descr)
  613. return buffer
  614. def debug_prints(self):
  615. debug_print("\tvrawbufferinfo", " at ", compute_unique_id(self))
  616. for i in self.fieldnums:
  617. debug_print("\t\t", str(untag(i)))
  618. class VRawSliceInfo(VAbstractRawInfo):
  619. def __init__(self, offset):
  620. self.offset = offset
  621. @specialize.argtype(1)
  622. def allocate_int(self, decoder, index):
  623. assert len(self.fieldnums) == 1
  624. base_buffer = decoder.decode_int(self.fieldnums[0])
  625. buffer = decoder.int_add_const(base_buffer, self.offset)
  626. decoder.virtuals_cache.set_int(index, buffer)
  627. return buffer
  628. def debug_prints(self):
  629. debug_print("\tvrawsliceinfo", " at ", compute_unique_id(self))
  630. for i in self.fieldnums:
  631. debug_print("\t\t", str(untag(i)))
  632. class VArrayStructInfo(AbstractVirtualInfo):
  633. def __init__(self, arraydescr, size, fielddescrs):
  634. self.size = size
  635. self.arraydescr = arraydescr
  636. self.fielddescrs = fielddescrs
  637. def debug_prints(self):
  638. debug_print("\tvarraystructinfo", self.arraydescr, " at ", compute_unique_id(self))
  639. for i in self.fieldnums:
  640. debug_print("\t\t", str(untag(i)))
  641. @specialize.argtype(1)
  642. def allocate(self, decoder, index):
  643. array = decoder.allocate_array(self.size, self.arraydescr,
  644. clear=True)
  645. decoder.virtuals_cache.set_ptr(index, array)
  646. p = 0
  647. for i in range(self.size):
  648. for j in range(len(self.fielddescrs)):
  649. num = self.fieldnums[p]
  650. if not tagged_eq(num, UNINITIALIZED):
  651. decoder.setinteriorfield(i, array, num,
  652. self.fielddescrs[j])
  653. p += 1
  654. return array
  655. class VStrPlainInfo(AbstractVirtualInfo):
  656. """Stands for the string made out of the characters of all fieldnums."""
  657. @specialize.argtype(1)
  658. def allocate(self, decoder, index):
  659. length = len(self.fieldnums)
  660. string = decoder.allocate_string(length)
  661. decoder.virtuals_cache.set_ptr(index, string)
  662. for i in range(length):
  663. charnum = self.fieldnums[i]
  664. if not tagged_eq(charnum, UNINITIALIZED):
  665. decoder.string_setitem(string, i, charnum)
  666. return string
  667. def debug_prints(self):
  668. debug_print("\tvstrplaininfo length", len(self.fieldnums), " at ", compute_unique_id(self))
  669. class VStrConcatInfo(AbstractVirtualInfo):
  670. """Stands for the string made out of the concatenation of two
  671. other strings."""
  672. @specialize.argtype(1)
  673. def allocate(self, decoder, index):
  674. # xxx for blackhole resuming, this will build all intermediate
  675. # strings and throw them away immediately, which is a bit sub-
  676. # efficient. Not sure we care.
  677. left, right = self.fieldnums
  678. string = decoder.concat_strings(left, right)
  679. decoder.virtuals_cache.set_ptr(index, string)
  680. return string
  681. def debug_prints(self):
  682. debug_print("\tvstrconcatinfo at ", compute_unique_id(self))
  683. for i in self.fieldnums:
  684. debug_print("\t\t", str(untag(i)))
  685. class VStrSliceInfo(AbstractVirtualInfo):
  686. """Stands for the string made out of slicing another string."""
  687. @specialize.argtype(1)
  688. def allocate(self, decoder, index):
  689. largerstr, start, length = self.fieldnums
  690. string = decoder.slice_string(largerstr, start, length)
  691. decoder.virtuals_cache.set_ptr(index, string)
  692. return string
  693. def debug_prints(self):
  694. debug_print("\tvstrsliceinfo at ", compute_unique_id(self))
  695. for i in self.fieldnums:
  696. debug_print("\t\t", str(untag(i)))
  697. class VUniPlainInfo(AbstractVirtualInfo):
  698. """Stands for the unicode string made out of the characters of all
  699. fieldnums."""
  700. @specialize.argtype(1)
  701. def allocate(self, decoder, index):
  702. length = len(self.fieldnums)
  703. string = decoder.allocate_unicode(length)
  704. decoder.virtuals_cache.set_ptr(index, string)
  705. for i in range(length):
  706. charnum = self.fieldnums[i]
  707. if not tagged_eq(charnum, UNINITIALIZED):
  708. decoder.unicode_setitem(string, i, charnum)
  709. return string
  710. def debug_prints(self):
  711. debug_print("\tvuniplaininfo length", len(self.fieldnums), " at ", compute_unique_id(self))
  712. class VUniConcatInfo(AbstractVirtualInfo):
  713. """Stands for the unicode string made out of the concatenation of two
  714. other unicode strings."""
  715. @specialize.argtype(1)
  716. def allocate(self, decoder, index):
  717. # xxx for blackhole resuming, this will build all intermediate
  718. # strings and throw them away immediately, which is a bit sub-
  719. # efficient. Not sure we care.
  720. left, right = self.fieldnums
  721. string = decoder.concat_unicodes(left, right)
  722. decoder.virtuals_cache.set_ptr(index, string)
  723. return string
  724. def debug_prints(self):
  725. debug_print("\tvuniconcatinfo at ", compute_unique_id(self))
  726. for i in self.fieldnums:
  727. debug_print("\t\t", str(untag(i)))
  728. class VUniSliceInfo(AbstractVirtualInfo):
  729. """Stands for the unicode string made out of slicing another
  730. unicode string."""
  731. @specialize.argtype(1)
  732. def allocate(self, decoder, index):
  733. largerstr, start, length = self.fieldnums
  734. string = decoder.slice_unicode(largerstr, start, length)
  735. decoder.virtuals_cache.set_ptr(index, string)
  736. return string
  737. def debug_prints(self):
  738. debug_print("\tvunisliceinfo at ", compute_unique_id(self))
  739. for i in self.fieldnums:
  740. debug_print("\t\t", str(untag(i)))
  741. # ____________________________________________________________
  742. class AbstractVirtualCache(object):
  743. pass
  744. def get_VirtualCache_class(suffix):
  745. # we need to create two copy of this class, because virtuals_*_cache will
  746. # be lists of different types (one for ResumeDataDirectReader and one for
  747. # ResumeDataBoxReader)
  748. class VirtualCache(AbstractVirtualCache):
  749. def __init__(self, virtuals_ptr_cache, virtuals_int_cache):
  750. self.virtuals_ptr_cache = virtuals_ptr_cache
  751. self.virtuals_int_cache = virtuals_int_cache
  752. def get_ptr(self, i):
  753. return self.virtuals_ptr_cache[i]
  754. def get_int(self, i):
  755. return self.virtuals_int_cache[i]
  756. def set_ptr(self, i, v):
  757. self.virtuals_ptr_cache[i] = v
  758. def set_int(self, i, v):
  759. self.virtuals_int_cache[i] = v
  760. VirtualCache.__name__ += suffix
  761. return VirtualCache
  762. class AbstractResumeDataReader(object):
  763. """A base mixin containing the logic to reconstruct virtuals out of
  764. guard failure. There are two implementations of this mixin:
  765. ResumeDataBoxReader for when we are compiling (i.e. when we have a
  766. metainterp), and ResumeDataDirectReader for when we are merely
  767. blackholing and want the best performance.
  768. """
  769. _mixin_ = True
  770. rd_virtuals = None
  771. virtuals_cache = None
  772. virtual_ptr_default = None
  773. virtual_int_default = None
  774. def _init(self, cpu, storage):
  775. self.cpu = cpu
  776. self.numb = storage.rd_numb
  777. self.cur_index = 0
  778. self.count = storage.rd_count
  779. self.consts = storage.rd_consts
  780. def _prepare(self, storage):
  781. self._prepare_virtuals(storage.rd_virtuals)
  782. self._prepare_pendingfields(storage.rd_pendingfields)
  783. def read_jitcode_pos_pc(self):
  784. jitcode_pos, self.cur_index = resumecode.numb_next_item(self.numb,
  785. self.cur_index)
  786. pc, self.cur_index = resumecode.numb_next_item(self.numb,
  787. self.cur_index)
  788. return jitcode_pos, pc
  789. def done_reading(self):
  790. return self.cur_index >= len(self.numb.code)
  791. def getvirtual_ptr(self, index):
  792. # Returns the index'th virtual, building it lazily if needed.
  793. # Note that this may be called recursively; that's why the
  794. # allocate() methods must fill in the cache as soon as they
  795. # have the object, before they fill its fields.
  796. assert self.virtuals_cache is not None
  797. v = self.virtuals_cache.get_ptr(index)
  798. if not v:
  799. assert self.rd_virtuals is not None
  800. v = self.rd_virtuals[index].allocate(self, index)
  801. ll_assert(v == self.virtuals_cache.get_ptr(index), "resume.py: bad cache")
  802. return v
  803. def getvirtual_int(self, index):
  804. assert self.virtuals_cache is not None
  805. v = self.virtuals_cache.get_int(index)
  806. if not v:
  807. v = self.rd_virtuals[index]
  808. ll_assert(bool(v), "resume.py: null rd_virtuals[index]")
  809. assert v.is_about_raw and isinstance(v, VAbstractRawInfo)
  810. v = v.allocate_int(self, index)
  811. ll_assert(v == self.virtuals_cache.get_int(index), "resume.py: bad cache")
  812. return v
  813. def force_all_virtuals(self):
  814. rd_virtuals = self.rd_virtuals
  815. if rd_virtuals:
  816. for i in range(len(rd_virtuals)):
  817. rd_virtual = rd_virtuals[i]
  818. if rd_virtual is not None:
  819. if rd_virtual.kind == REF:
  820. self.getvirtual_ptr(i)
  821. elif rd_virtual.kind == INT:
  822. self.getvirtual_int(i)
  823. else:
  824. assert False
  825. return self.virtuals_cache
  826. def _prepare_virtuals(self, virtuals):
  827. if virtuals:
  828. self.rd_virtuals = virtuals
  829. # XXX: this is suboptimal, because we are creating two lists, one
  830. # for REFs and one for INTs: but for each index, we are using
  831. # either one or the other, so we should think of a way to
  832. # "compact" them
  833. self.virtuals_cache = self.VirtualCache([self.virtual_ptr_default] * len(virtuals),
  834. [self.virtual_int_default] * len(virtuals))
  835. def _prepare_pendingfields(self, pendingfields):
  836. if pendingfields:
  837. for i in range(len(pendingfields)):
  838. lldescr = pendingfields[i].lldescr
  839. num = pendingfields[i].num
  840. fieldnum = pendingfields[i].fieldnum
  841. itemindex = pendingfields[i].itemindex
  842. descr = annlowlevel.cast_base_ptr_to_instance(AbstractDescr,
  843. lldescr)
  844. struct = self.decode_ref(num)
  845. itemindex = rffi.cast(lltype.Signed, itemindex)
  846. if itemindex < 0:
  847. self.setfield(struct, fieldnum, descr)
  848. else:
  849. self.setarrayitem(struct, itemindex, fieldnum, descr)
  850. def setarrayitem(self, array, index, fieldnum, arraydescr):
  851. if arraydescr.is_array_of_pointers():
  852. self.setarrayitem_ref(array, index, fieldnum, arraydescr)
  853. elif arraydescr.is_array_of_floats():
  854. self.setarrayitem_float(array, index, fieldnum, arraydescr)
  855. else:
  856. self.setarrayitem_int(array, index, fieldnum, arraydescr)
  857. def _prepare_next_section(self, info):
  858. # Use info.enumerate_vars(), normally dispatching to
  859. # rpython.jit.codewriter.jitcode. Some tests give a different 'info'.
  860. self.cur_index = info.enumerate_vars(self._callback_i,
  861. self._callback_r,
  862. self._callback_f,
  863. self.unique_id, # <-- annotation hack
  864. self.cur_index)
  865. def _callback_i(self, index, register_index):
  866. item, index = resumecode.numb_next_item(self.numb, index)
  867. value = self.decode_int(item)
  868. self.write_an_int(register_index, value)
  869. return index
  870. def _callback_r(self, index, register_index):
  871. item, index = resumecode.numb_next_item(self.numb, index)
  872. value = self.decode_ref(item)
  873. self.write_a_ref(register_index, value)
  874. return index
  875. def _callback_f(self, index, register_index):
  876. item, index = resumecode.numb_next_item(self.numb, index)
  877. value = self.decode_float(item)
  878. self.write_a_float(register_index, value)
  879. return index
  880. # ---------- when resuming for pyjitpl.py, make boxes ----------
  881. def rebuild_from_resumedata(metainterp, storage, deadframe,
  882. virtualizable_info, greenfield_info):
  883. resumereader = ResumeDataBoxReader(storage, deadframe, metainterp)
  884. boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info,
  885. greenfield_info)
  886. virtualizable_boxes, virtualref_boxes = boxes
  887. while not resumereader.done_reading():
  888. jitcode_pos, pc = resumereader.read_jitcode_pos_pc()
  889. jitcode = metainterp.staticdata.jitcodes[jitcode_pos]
  890. f = metainterp.newframe(jitcode)
  891. f.setup_resume_at_op(pc)
  892. resumereader.consume_boxes(f.get_current_position_info(),
  893. f.registers_i, f.registers_r, f.registers_f)
  894. f.handle_rvmprof_enter_on_resume()
  895. return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes
  896. class ResumeDataBoxReader(AbstractResumeDataReader):
  897. unique_id = lambda: None
  898. VirtualCache = get_VirtualCache_class('BoxReader')
  899. def __init__(self, storage, deadframe, metainterp):
  900. self._init(metainterp.cpu, storage)
  901. self.deadframe = deadframe
  902. self.metainterp = metainterp
  903. self.liveboxes = [None] * storage.rd_count
  904. self._prepare(storage)
  905. def consume_boxes(self, info, boxes_i, boxes_r, boxes_f):
  906. self.boxes_i = boxes_i
  907. self.boxes_r = boxes_r
  908. self.boxes_f = boxes_f
  909. self._prepare_next_section(info)
  910. def consume_virtualizable_boxes(self, vinfo, index):
  911. # we have to ignore the initial part of 'nums' (containing vrefs),
  912. # find the virtualizable from nums[-1], and use it to know how many
  913. # boxes of which type we have to return. This does not write
  914. # anything into the virtualizable.
  915. numb = self.numb
  916. item, index = resumecode.numb_next_item(numb, index)
  917. virtualizablebox = self.decode_ref(item)
  918. virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox)
  919. return vinfo.load_list_of_boxes(virtualizable, self, virtualizablebox,
  920. numb, index)
  921. def consume_virtualref_boxes(self, index):
  922. # Returns a list of boxes, assumed to be all BoxPtrs.
  923. # We leave up to the caller to call vrefinfo.continue_tracing().
  924. size, index = resumecode.numb_next_item(self.numb, index)
  925. if size == 0:
  926. return [], index
  927. lst = []
  928. for i in range(size * 2):
  929. item, index = resumecode.numb_next_item(self.numb, index)
  930. lst.append(self.decode_ref(item))
  931. return lst, index
  932. def consume_vref_and_vable_boxes(self, vinfo, ginfo):
  933. vable_size, index = resumecode.numb_next_item(self.numb, 0)
  934. if vinfo is not None:
  935. virtualizable_boxes, index = self.consume_virtualizable_boxes(vinfo,
  936. index)
  937. elif ginfo is not None:
  938. item, index = resumecode.numb_next_item(self.numb, index)
  939. virtualizable_boxes = [self.decode_ref(item)]
  940. else:
  941. virtualizable_boxes = None
  942. virtualref_boxes, index = self.consume_virtualref_boxes(index)
  943. self.cur_index = index
  944. return virtualizable_boxes, virtualref_boxes
  945. def allocate_with_vtable(self, descr=None):
  946. return self.metainterp.execute_new_with_vtable(descr=descr)
  947. def allocate_struct(self, typedescr):
  948. return self.metainterp.execute_new(typedescr)
  949. def allocate_array(self, length, arraydescr, clear):
  950. lengthbox = ConstInt(length)
  951. if clear:
  952. return self.metainterp.execute_new_array_clear(arraydescr,
  953. lengthbox)
  954. return self.metainterp.execute_new_array(arraydescr, lengthbox)
  955. def allocate_raw_buffer(self, size):
  956. cic = self.metainterp.staticdata.callinfocollection
  957. calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)
  958. return self.metainterp.execute_and_record_varargs(
  959. rop.CALL_I, [ConstInt(func), ConstInt(size)], calldescr)
  960. def allocate_string(self, length):
  961. return self.metainterp.execute_and_record(rop.NEWSTR,
  962. None, ConstInt(length))
  963. def string_setitem(self, strbox, index, charnum):
  964. charbox = self.decode_box(charnum, INT)
  965. self.metainterp.execute_and_record(rop.STRSETITEM, None,
  966. strbox, ConstInt(index), charbox)
  967. def concat_strings(self, str1num, str2num):
  968. cic = self.metainterp.staticdata.callinfocollection
  969. calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_STR_CONCAT)
  970. str1box = self.decode_box(str1num, REF)
  971. str2box = self.decode_box(str2num, REF)
  972. return self.metainterp.execute_and_record_varargs(
  973. rop.CALL_R, [ConstInt(func), str1box, str2box], calldescr)
  974. def slice_string(self, strnum, startnum, lengthnum):
  975. cic = self.metainterp.staticdata.callinfocollection
  976. calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_STR_SLICE)
  977. strbox = self.decode_box(strnum, REF)
  978. startbox = self.decode_box(startnum, INT)
  979. lengthbox = self.decode_box(lengthnum, INT)
  980. stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
  981. startbox, lengthbox)
  982. return self.metainterp.execute_and_record_varargs(
  983. rop.CALL_R, [ConstInt(func), strbox, startbox, stopbox], calldescr)
  984. def allocate_unicode(self, length):
  985. return self.metainterp.execute_and_record(rop.NEWUNICODE,
  986. None, ConstInt(length))
  987. def unicode_setitem(self, strbox, index, charnum):
  988. charbox = self.decode_box(charnum, INT)
  989. self.metainterp.execute_and_record(rop.UNICODESETITEM, None,
  990. strbox, ConstInt(index), charbox)
  991. def concat_unicodes(self, str1num, str2num):
  992. cic = self.metainterp.staticdata.callinfocollection
  993. calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
  994. str1box = self.decode_box(str1num, REF)
  995. str2box = self.decode_box(str2num, REF)
  996. return self.metainterp.execute_and_record_varargs(
  997. rop.CALL_R, [ConstInt(func), str1box, str2box], calldescr)
  998. def slice_unicode(self, strnum, startnum, lengthnum):
  999. cic = self.metainterp.staticdata.callinfocollection
  1000. calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
  1001. strbox = self.decode_box(strnum, REF)
  1002. startbox = self.decode_box(startnum, INT)
  1003. lengthbox = self.decode_box(lengthnum, INT)
  1004. stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
  1005. startbox, lengthbox)
  1006. return self.metainterp.execute_and_record_varargs(
  1007. rop.CALL_R, [ConstInt(func), strbox, startbox, stopbox], calldescr)
  1008. def setfield(self, structbox, fieldnum, descr):
  1009. if descr.is_pointer_field():
  1010. kind = REF
  1011. elif descr.is_float_field():
  1012. kind = FLOAT
  1013. else:
  1014. kind = INT
  1015. fieldbox = self.decode_box(fieldnum, kind)
  1016. self.metainterp.execute_setfield_gc(descr, structbox, fieldbox)
  1017. def setinteriorfield(self, index, array, fieldnum, descr):
  1018. if descr.is_pointer_field():
  1019. kind = REF
  1020. elif descr.is_float_field():
  1021. kind = FLOAT
  1022. else:
  1023. kind = INT
  1024. fieldbox = self.decode_box(fieldnum, kind)
  1025. self.metainterp.execute_setinteriorfield_gc(descr, array,
  1026. ConstInt(index), fieldbox)
  1027. def setarrayitem_int(self, arraybox, index, fieldnum, arraydescr):
  1028. self._setarrayitem(arraybox, index, fieldnum, arraydescr, INT)
  1029. def setarrayitem_ref(self, arraybox, index, fieldnum, arraydescr):
  1030. self._setarrayitem(arraybox, index, fieldnum, arraydescr, REF)
  1031. def setarrayitem_float(self, arraybox, index, fieldnum, arraydescr):
  1032. self._setarrayitem(arraybox, index, fieldnum, arraydescr, FLOAT)
  1033. def _setarrayitem(self, arraybox, index, fieldnum, arraydescr, kind):
  1034. itembox = self.decode_box(fieldnum, kind)
  1035. self.metainterp.execute_setarrayitem_gc(arraydescr, arraybox,
  1036. ConstInt(index), itembox)
  1037. def setrawbuffer_item(self, bufferbox, fieldnum, offset, arraydescr):
  1038. if arraydescr.is_array_of_pointers():
  1039. kind = REF
  1040. elif arraydescr.is_array_of_floats():
  1041. kind = FLOAT
  1042. else:
  1043. kind = INT
  1044. itembox = self.decode_box(fieldnum, kind)
  1045. self.metainterp.execute_raw_store(arraydescr, bufferbox,
  1046. ConstInt(offset), itembox)
  1047. def decode_int(self, tagged):
  1048. return self.decode_box(tagged, INT)
  1049. def decode_ref(self, tagged):
  1050. return self.decode_box(tagged, REF)
  1051. def decode_float(self, tagged):
  1052. return self.decode_box(tagged, FLOAT)
  1053. def decode_box(self, tagged, kind):
  1054. num, tag = untag(tagged)
  1055. if tag == TAGCONST:
  1056. if tagged_eq(tagged, NULLREF):
  1057. box = self.cpu.ts.CONST_NULL
  1058. else:
  1059. box = self.consts[num - TAG_CONST_OFFSET]
  1060. elif tag == TAGVIRTUAL:
  1061. if kind == INT:
  1062. box = self.getvirtual_int(num)
  1063. else:
  1064. box = self.getvirtual_ptr(num)
  1065. elif tag == TAGINT:
  1066. box = ConstInt(num)
  1067. else:
  1068. assert tag == TAGBOX
  1069. box = self.liveboxes[num]
  1070. if box is None:
  1071. box = self.load_box_from_cpu(num, kind)
  1072. assert box.type == kind
  1073. return box
  1074. def load_box_from_cpu(self, num, kind):
  1075. if num < 0:
  1076. num += len(self.liveboxes)
  1077. assert num >= 0
  1078. if kind == INT:
  1079. box = IntFrontendOp(0)
  1080. box.setint(self.cpu.get_int_value(self.deadframe, num))
  1081. elif kind == REF:
  1082. box = RefFrontendOp(0)
  1083. box.setref_base(self.cpu.get_ref_value(self.deadframe, num))
  1084. elif kind == FLOAT:
  1085. box = FloatFrontendOp(0)
  1086. box.setfloatstorage(self.cpu.get_float_value(self.deadframe, num))
  1087. else:
  1088. assert 0, "bad kind: %d" % ord(kind)
  1089. self.liveboxes[num] = box
  1090. return box
  1091. def decode_box_of_type(self, TYPE, tagged):
  1092. kind = getkind(TYPE)
  1093. if kind == 'int':
  1094. kind = INT
  1095. elif kind == 'ref':
  1096. kind = REF
  1097. elif kind == 'float':
  1098. kind = FLOAT
  1099. else:
  1100. raise AssertionError(kind)
  1101. return self.decode_box(tagged, kind)
  1102. decode_box_of_type._annspecialcase_ = 'specialize:arg(1)'
  1103. def write_an_int(self, index, box):
  1104. self.boxes_i[index] = box
  1105. def write_a_ref(self, index, box):
  1106. self.boxes_r[index] = box
  1107. def write_a_float(self, index, box):
  1108. self.boxes_f[index] = box
  1109. def int_add_const(self, intbox, offset):
  1110. return self.metainterp.execute_and_record(rop.INT_ADD, None, intbox,
  1111. ConstInt(offset))
  1112. # ---------- when resuming for blackholing, get direct values ----------
  1113. def blackhole_from_resumedata(blackholeinterpbuilder, jitcodes,
  1114. jitdriver_sd, storage,
  1115. deadframe, all_virtuals=None):
  1116. #

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