PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/rpython/jit/backend/zarch/regalloc.py

https://bitbucket.org/pypy/pypy/
Python | 1341 lines | 1048 code | 169 blank | 124 comment | 201 complexity | 4b4aa9a5f578073e61eee0e0f824083f 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.backend.llsupport.regalloc import (RegisterManager, FrameManager,
  2. TempVar, compute_vars_longevity,
  3. BaseRegalloc, NoVariableToSpill)
  4. from rpython.jit.backend.llsupport.jump import remap_frame_layout_mixed
  5. from rpython.jit.backend.zarch.arch import WORD
  6. from rpython.jit.codewriter import longlong
  7. from rpython.jit.backend.zarch.locations import imm, get_fp_offset, imm0, imm1
  8. from rpython.jit.metainterp.history import (Const, ConstInt, ConstFloat, ConstPtr,
  9. INT, REF, FLOAT, VOID)
  10. from rpython.jit.metainterp.history import JitCellToken, TargetToken
  11. from rpython.jit.metainterp.resoperation import rop
  12. from rpython.jit.backend.zarch import locations as l
  13. from rpython.jit.backend.llsupport import symbolic
  14. from rpython.jit.backend.llsupport.descr import ArrayDescr
  15. from rpython.jit.backend.llsupport.descr import unpack_arraydescr
  16. from rpython.jit.backend.llsupport.descr import unpack_fielddescr
  17. from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr
  18. from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
  19. import rpython.jit.backend.zarch.registers as r
  20. import rpython.jit.backend.zarch.conditions as c
  21. import rpython.jit.backend.zarch.helper.regalloc as helper
  22. from rpython.jit.backend.zarch.helper.regalloc import (check_imm,)
  23. from rpython.jit.codewriter.effectinfo import EffectInfo
  24. from rpython.rlib.objectmodel import we_are_translated
  25. from rpython.rlib.debug import debug_print
  26. from rpython.rlib import rgc
  27. from rpython.rlib.rarithmetic import r_uint
  28. from rpython.rtyper.lltypesystem import rffi, lltype, rstr, llmemory
  29. from rpython.rtyper.lltypesystem.lloperation import llop
  30. from rpython.rtyper.annlowlevel import cast_instance_to_gcref
  31. LIMIT_LOOP_BREAK = 15000 # should be much smaller than 32 KB
  32. def force_int(intvalue):
  33. # a hack before transaction: force the intvalue argument through
  34. # rffi.cast(), to turn Symbolics into real values
  35. return rffi.cast(lltype.Signed, intvalue)
  36. class TempInt(TempVar):
  37. type = INT
  38. def __repr__(self):
  39. return "<TempInt at %s>" % (id(self),)
  40. class TempPtr(TempVar):
  41. type = REF
  42. def __repr__(self):
  43. return "<TempPtr at %s>" % (id(self),)
  44. class TempFloat(TempVar):
  45. type = FLOAT
  46. def __repr__(self):
  47. return "<TempFloat at %s>" % (id(self),)
  48. class FPRegisterManager(RegisterManager):
  49. all_regs = r.MANAGED_FP_REGS
  50. box_types = [FLOAT]
  51. save_around_call_regs = r.VOLATILES_FLOAT
  52. assert set(save_around_call_regs).issubset(all_regs)
  53. pool = None
  54. def __init__(self, longevity, frame_manager=None, assembler=None):
  55. RegisterManager.__init__(self, longevity, frame_manager, assembler)
  56. def call_result_location(self, v):
  57. return r.FPR_RETURN
  58. def convert_to_imm(self, c):
  59. return l.pool(self.assembler.pool.get_offset(c), float=True)
  60. def ensure_reg_or_pool(self, box):
  61. if isinstance(box, Const):
  62. offset = self.assembler.pool.get_offset(box)
  63. return l.pool(offset, float=True)
  64. else:
  65. assert box in self.temp_boxes
  66. loc = self.make_sure_var_in_reg(box,
  67. forbidden_vars=self.temp_boxes)
  68. return loc
  69. def get_scratch_reg(self):
  70. box = TempVar()
  71. reg = self.force_allocate_reg(box, forbidden_vars=self.temp_boxes)
  72. self.temp_boxes.append(box)
  73. return reg
  74. def ensure_reg(self, box):
  75. if isinstance(box, Const):
  76. offset = self.assembler.pool.get_offset(box)
  77. poolloc = l.pool(offset, float=True)
  78. reg = self.get_scratch_reg()
  79. if poolloc.displace <= 2**11-1:
  80. self.assembler.mc.LD(reg, poolloc)
  81. else:
  82. self.assembler.mc.LDY(reg, poolloc)
  83. return reg
  84. else:
  85. assert box in self.temp_boxes
  86. loc = self.make_sure_var_in_reg(box,
  87. forbidden_vars=self.temp_boxes)
  88. return loc
  89. def get_scratch_reg(self, selected_reg=None):
  90. box = TempFloat()
  91. reg = self.force_allocate_reg(box, forbidden_vars=self.temp_boxes, selected_reg=selected_reg)
  92. self.temp_boxes.append(box)
  93. return reg
  94. class ZARCHRegisterManager(RegisterManager):
  95. all_regs = r.MANAGED_REGS
  96. box_types = None # or a list of acceptable types
  97. no_lower_byte_regs = all_regs
  98. save_around_call_regs = r.VOLATILES
  99. frame_reg = r.SPP
  100. assert set(save_around_call_regs).issubset(all_regs)
  101. pool = None
  102. def __init__(self, longevity, frame_manager=None, assembler=None):
  103. RegisterManager.__init__(self, longevity, frame_manager, assembler)
  104. def call_result_location(self, v):
  105. return r.GPR_RETURN
  106. def convert_to_int(self, c):
  107. if isinstance(c, ConstInt):
  108. return rffi.cast(lltype.Signed, c.value)
  109. else:
  110. assert isinstance(c, ConstPtr)
  111. return rffi.cast(lltype.Signed, c.value)
  112. def ensure_reg_or_pool(self, box):
  113. if isinstance(box, Const):
  114. if self.assembler.pool.contains_box(box):
  115. offset = self.assembler.pool.get_offset(box)
  116. return l.pool(offset)
  117. else:
  118. return self.ensure_reg(box)
  119. else:
  120. assert box in self.temp_boxes
  121. loc = self.make_sure_var_in_reg(box,
  122. forbidden_vars=self.temp_boxes)
  123. return loc
  124. def convert_to_imm(self, c):
  125. if self.assembler.pool.contains_box(c):
  126. return l.pool(self.assembler.pool.get_offset(c))
  127. immvalue = self.convert_to_int(c)
  128. return l.imm(immvalue)
  129. def ensure_reg(self, box):
  130. if isinstance(box, Const):
  131. loc = self.get_scratch_reg()
  132. immvalue = self.convert_to_int(box)
  133. self.assembler.mc.load_imm(loc, immvalue)
  134. else:
  135. assert box in self.temp_boxes
  136. loc = self.make_sure_var_in_reg(box,
  137. forbidden_vars=self.temp_boxes)
  138. return loc
  139. def get_scratch_reg(self, selected_reg=None):
  140. box = TempInt()
  141. reg = self.force_allocate_reg(box, forbidden_vars=self.temp_boxes, selected_reg=selected_reg)
  142. self.temp_boxes.append(box)
  143. return reg
  144. def ensure_even_odd_pair(self, origvar, bindvar, bind_first=True,
  145. must_exist=True, load_loc_odd=True,
  146. move_regs=True):
  147. """ Allocates two registers that can be used by the instruction.
  148. origvar: is the original register holding the value
  149. bindvar: is the variable that will be bound
  150. (= self.reg_bindings[bindvar] = new register)
  151. bind_first: the even register will be bound to bindvar,
  152. if bind_first == False: the odd register will
  153. be bound
  154. NOTE: Calling ensure_even_odd_pair twice in a prepare function is NOT supported!
  155. """
  156. self._check_type(origvar)
  157. prev_loc = self.loc(origvar, must_exist=must_exist)
  158. var2 = TempInt()
  159. if bindvar is None:
  160. bindvar = TempInt()
  161. if bind_first:
  162. loc, loc2 = self.force_allocate_reg_pair(bindvar, var2, self.temp_boxes)
  163. else:
  164. loc, loc2 = self.force_allocate_reg_pair(var2, bindvar, self.temp_boxes)
  165. if isinstance(bindvar, TempVar):
  166. self.temp_boxes.append(bindvar)
  167. self.temp_boxes.append(var2)
  168. assert loc.is_even() and loc2.is_odd()
  169. if move_regs and prev_loc is not loc2:
  170. if load_loc_odd:
  171. self.assembler.regalloc_mov(prev_loc, loc2)
  172. else:
  173. self.assembler.regalloc_mov(prev_loc, loc)
  174. return loc, loc2
  175. def force_allocate_reg_pair(self, even_var, odd_var, forbidden_vars):
  176. """ Forcibly allocate a register for the new variable even_var.
  177. even_var will have an even register (odd_var, you guessed it,
  178. will have an odd register).
  179. """
  180. self._check_type(even_var)
  181. self._check_type(odd_var)
  182. if isinstance(even_var, TempVar):
  183. self.longevity[even_var] = (self.position, self.position)
  184. if isinstance(odd_var, TempVar):
  185. self.longevity[odd_var] = (self.position, self.position)
  186. # this function steps through the following:
  187. # 1) maybe there is an even/odd pair that is always
  188. # free, then allocate them!
  189. # 2) try to just spill one variable in either the even
  190. # or the odd reg
  191. # 3) spill two variables
  192. # start in 1)
  193. SPILL_EVEN = 0
  194. SPILL_ODD = 1
  195. even, odd = None, None
  196. candidates = []
  197. i = len(self.free_regs)-1
  198. while i >= 0:
  199. even = self.free_regs[i]
  200. if even.is_even():
  201. # found an even registers that is actually free
  202. odd = r.odd_reg(even)
  203. if odd not in self.free_regs:
  204. # sadly odd is not free, but for spilling
  205. # we found a candidate
  206. candidates.append((even, odd, SPILL_ODD))
  207. i -= 1
  208. continue
  209. # even is free and so is odd! allocate these
  210. # two registers
  211. assert even_var not in self.reg_bindings
  212. assert odd_var not in self.reg_bindings
  213. self.reg_bindings[even_var] = even
  214. self.reg_bindings[odd_var] = odd
  215. self.free_regs = [fr for fr in self.free_regs \
  216. if fr is not even and \
  217. fr is not odd]
  218. return even, odd
  219. else:
  220. # an odd free register, maybe the even one is
  221. # a candidate?
  222. odd = even
  223. even = r.even_reg(odd)
  224. if even not in self.free_regs:
  225. # yes even might be a candidate
  226. # this means that odd is free, but not even
  227. candidates.append((even, odd, SPILL_EVEN))
  228. i -= 1
  229. reverse_mapping = {}
  230. for v, reg in self.reg_bindings.items():
  231. reverse_mapping[reg] = v
  232. # needs to spill one variable
  233. for even, odd, which_to_spill in candidates:
  234. # no heuristic, pick the first
  235. if which_to_spill == SPILL_EVEN:
  236. orig_var_even = reverse_mapping[even]
  237. if orig_var_even in forbidden_vars:
  238. continue # duh!
  239. self._sync_var(orig_var_even)
  240. del self.reg_bindings[orig_var_even]
  241. elif which_to_spill == SPILL_ODD:
  242. orig_var_odd = reverse_mapping[odd]
  243. if orig_var_odd in forbidden_vars:
  244. continue # duh!
  245. self._sync_var(orig_var_odd)
  246. del self.reg_bindings[orig_var_odd]
  247. # well, we got away with a single spill :)
  248. self.free_regs = [fr for fr in self.free_regs \
  249. if fr is not even and \
  250. fr is not odd]
  251. self.reg_bindings[even_var] = even
  252. self.reg_bindings[odd_var] = odd
  253. return even, odd
  254. # there is no candidate pair that only would
  255. # require one spill, thus we need to spill two!
  256. # this is a rare case!
  257. for even, odd in r.MANAGED_REG_PAIRS:
  258. orig_var_even = reverse_mapping.get(even,None)
  259. orig_var_odd = reverse_mapping.get(odd,None)
  260. if orig_var_even in forbidden_vars or \
  261. orig_var_odd in forbidden_vars:
  262. continue
  263. if orig_var_even is not None:
  264. self._sync_var(orig_var_even)
  265. del self.reg_bindings[orig_var_even]
  266. if orig_var_odd is not None:
  267. self._sync_var(orig_var_odd)
  268. del self.reg_bindings[orig_var_odd]
  269. self.reg_bindings[even_var] = even
  270. self.reg_bindings[odd_var] = odd
  271. break
  272. else:
  273. # uff! in this case, we need to move a forbidden var to another register
  274. assert len(forbidden_vars) <= 8 # otherwise it is NOT possible to complete
  275. even, odd = r.r2, r.r3
  276. old_even_var = reverse_mapping.get(even, None)
  277. old_odd_var = reverse_mapping.get(odd, None)
  278. # forbid r2 and r3 to be in free regs!
  279. self.free_regs = [fr for fr in self.free_regs \
  280. if fr is not even and \
  281. fr is not odd]
  282. if old_even_var:
  283. if old_even_var in forbidden_vars:
  284. self._relocate_forbidden_variable(even, old_even_var, reverse_mapping,
  285. forbidden_vars, odd)
  286. else:
  287. # old even var is not forbidden, sync it and be done with it
  288. self._sync_var(old_even_var)
  289. del self.reg_bindings[old_even_var]
  290. del reverse_mapping[odd]
  291. if old_odd_var:
  292. if old_odd_var in forbidden_vars:
  293. self._relocate_forbidden_variable(odd, old_odd_var, reverse_mapping,
  294. forbidden_vars, even)
  295. else:
  296. self._sync_var(old_odd_var)
  297. del self.reg_bindings[old_odd_var]
  298. del reverse_mapping[odd]
  299. self.reg_bindings[even_var] = even
  300. self.reg_bindings[odd_var] = odd
  301. return even, odd
  302. return even, odd
  303. def _relocate_forbidden_variable(self, reg, var, reverse_mapping, forbidden_vars, forbidden_reg):
  304. if len(self.free_regs) > 0:
  305. candidate = self.free_regs.pop()
  306. self.assembler.regalloc_mov(reg, candidate)
  307. self.reg_bindings[var] = candidate
  308. reverse_mapping[candidate] = var
  309. return # we found a location for that forbidden var!
  310. for candidate in r.MANAGED_REGS:
  311. # move register of var to another register
  312. # it is NOT allowed to be a reg or forbidden_reg
  313. if candidate is reg or candidate is forbidden_reg:
  314. continue
  315. # neither can we allow to move it to a register of another forbidden variable
  316. candidate_var = reverse_mapping.get(candidate, None)
  317. if not candidate_var or candidate_var not in forbidden_vars:
  318. if candidate_var is not None:
  319. self._sync_var(candidate_var)
  320. del self.reg_bindings[candidate_var]
  321. del reverse_mapping[candidate]
  322. self.assembler.regalloc_mov(reg, candidate)
  323. assert var is not None
  324. self.reg_bindings[var] = candidate
  325. reverse_mapping[candidate] = var
  326. break
  327. else:
  328. raise NoVariableToSpill
  329. class ZARCHFrameManager(FrameManager):
  330. def __init__(self, base_ofs):
  331. FrameManager.__init__(self)
  332. self.used = []
  333. self.base_ofs = base_ofs
  334. def frame_pos(self, loc, box_type):
  335. return l.StackLocation(loc, get_fp_offset(self.base_ofs, loc), box_type)
  336. @staticmethod
  337. def frame_size(type):
  338. return 1
  339. @staticmethod
  340. def get_loc_index(loc):
  341. assert isinstance(loc, l.StackLocation)
  342. return loc.position
  343. class Regalloc(BaseRegalloc):
  344. def __init__(self, assembler=None):
  345. self.cpu = assembler.cpu
  346. self.assembler = assembler
  347. self.jump_target_descr = None
  348. self.final_jump_op = None
  349. def _prepare(self, inputargs, operations, allgcrefs):
  350. cpu = self.assembler.cpu
  351. self.fm = ZARCHFrameManager(cpu.get_baseofs_of_frame_field())
  352. operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
  353. allgcrefs)
  354. # compute longevity of variables
  355. longevity, last_real_usage = compute_vars_longevity(
  356. inputargs, operations)
  357. self.longevity = longevity
  358. self.last_real_usage = last_real_usage
  359. self.rm = ZARCHRegisterManager(self.longevity,
  360. frame_manager = self.fm,
  361. assembler = self.assembler)
  362. self.rm.pool = self.assembler.pool
  363. self.fprm = FPRegisterManager(self.longevity, frame_manager = self.fm,
  364. assembler = self.assembler)
  365. self.fprm.pool = self.assembler.pool
  366. return operations
  367. def prepare_loop(self, inputargs, operations, looptoken, allgcrefs):
  368. operations = self._prepare(inputargs, operations, allgcrefs)
  369. self._set_initial_bindings(inputargs, looptoken)
  370. # note: we need to make a copy of inputargs because possibly_free_vars
  371. # is also used on op args, which is a non-resizable list
  372. self.possibly_free_vars(list(inputargs))
  373. self.min_bytes_before_label = 4 # for redirect_call_assembler()
  374. return operations
  375. def prepare_bridge(self, inputargs, arglocs, operations, allgcrefs,
  376. frame_info):
  377. operations = self._prepare(inputargs, operations, allgcrefs)
  378. self._update_bindings(arglocs, inputargs)
  379. self.min_bytes_before_label = 0
  380. return operations
  381. def ensure_next_label_is_at_least_at_position(self, at_least_position):
  382. self.min_bytes_before_label = max(self.min_bytes_before_label,
  383. at_least_position)
  384. def _update_bindings(self, locs, inputargs):
  385. # XXX this should probably go to llsupport/regalloc.py
  386. used = {}
  387. i = 0
  388. for loc in locs:
  389. if loc is None: # xxx bit kludgy
  390. loc = r.SPP
  391. arg = inputargs[i]
  392. i += 1
  393. if loc.is_core_reg():
  394. if loc is r.SPP:
  395. self.rm.bindings_to_frame_reg[arg] = None
  396. else:
  397. self.rm.reg_bindings[arg] = loc
  398. used[loc] = None
  399. elif loc.is_fp_reg():
  400. self.fprm.reg_bindings[arg] = loc
  401. used[loc] = None
  402. else:
  403. assert loc.is_stack()
  404. self.fm.bind(arg, loc)
  405. self.rm.free_regs = []
  406. for reg in self.rm.all_regs:
  407. if reg not in used:
  408. self.rm.free_regs.append(reg)
  409. self.fprm.free_regs = []
  410. for reg in self.fprm.all_regs:
  411. if reg not in used:
  412. self.fprm.free_regs.append(reg)
  413. self.possibly_free_vars(list(inputargs))
  414. self.fm.finish_binding()
  415. self.rm._check_invariants()
  416. self.fprm._check_invariants()
  417. def get_final_frame_depth(self):
  418. return self.fm.get_frame_depth()
  419. def possibly_free_var(self, var):
  420. if var is not None:
  421. if var.type == FLOAT:
  422. self.fprm.possibly_free_var(var)
  423. else:
  424. self.rm.possibly_free_var(var)
  425. def possibly_free_vars(self, vars):
  426. for var in vars:
  427. self.possibly_free_var(var)
  428. def possibly_free_vars_for_op(self, op):
  429. for i in range(op.numargs()):
  430. var = op.getarg(i)
  431. self.possibly_free_var(var)
  432. def force_result_in_reg(self, var, loc):
  433. if var.type == FLOAT:
  434. forbidden_vars = self.fprm.temp_boxes
  435. return self.fprm.force_result_in_reg(var, loc, forbidden_vars)
  436. else:
  437. forbidden_vars = self.rm.temp_boxes
  438. return self.rm.force_result_in_reg(var, loc, forbidden_vars)
  439. def force_allocate_reg(self, var):
  440. if var.type == FLOAT:
  441. forbidden_vars = self.fprm.temp_boxes
  442. return self.fprm.force_allocate_reg(var, forbidden_vars)
  443. else:
  444. forbidden_vars = self.rm.temp_boxes
  445. return self.rm.force_allocate_reg(var, forbidden_vars)
  446. def force_allocate_reg_or_cc(self, var):
  447. assert var.type == INT
  448. if self.next_op_can_accept_cc(self.operations, self.rm.position):
  449. # hack: return the SPP location to mean "lives in CC". This
  450. # SPP will not actually be used, and the location will be freed
  451. # after the next op as usual.
  452. self.rm.force_allocate_frame_reg(var)
  453. return r.SPP
  454. else:
  455. # else, return a regular register (not SPP).
  456. if self.rm.reg_bindings.get(var, None) is not None:
  457. return self.rm.loc(var, must_exist=True)
  458. forbidden_vars = self.rm.temp_boxes
  459. return self.rm.force_allocate_reg(var, forbidden_vars)
  460. def walk_operations(self, inputargs, operations):
  461. from rpython.jit.backend.zarch.assembler import (
  462. asm_operations)
  463. i = 0
  464. self.limit_loop_break = (self.assembler.mc.get_relative_pos() +
  465. LIMIT_LOOP_BREAK)
  466. self.operations = operations
  467. while i < len(operations):
  468. op = operations[i]
  469. self.assembler.mc.mark_op(op)
  470. self.rm.position = i
  471. self.fprm.position = i
  472. opnum = op.getopnum()
  473. if rop.has_no_side_effect(opnum) and op not in self.longevity:
  474. i += 1
  475. self.possibly_free_vars_for_op(op)
  476. continue
  477. #
  478. for j in range(op.numargs()):
  479. box = op.getarg(j)
  480. if box.type != FLOAT:
  481. self.rm.temp_boxes.append(box)
  482. else:
  483. self.fprm.temp_boxes.append(box)
  484. #
  485. if not we_are_translated() and opnum == rop.FORCE_SPILL:
  486. self._consider_force_spill(op)
  487. else:
  488. arglocs = prepare_oplist[opnum](self, op)
  489. asm_operations[opnum](self.assembler, op, arglocs, self)
  490. self.free_op_vars()
  491. self.possibly_free_var(op)
  492. self.rm._check_invariants()
  493. self.fprm._check_invariants()
  494. if self.assembler.mc.get_relative_pos() > self.limit_loop_break:
  495. self.assembler.break_long_loop()
  496. self.limit_loop_break = (self.assembler.mc.get_relative_pos() +
  497. LIMIT_LOOP_BREAK)
  498. i += 1
  499. assert not self.rm.reg_bindings
  500. assert not self.fprm.reg_bindings
  501. self.flush_loop()
  502. self.assembler.mc.mark_op(None) # end of the loop
  503. self.operations = None
  504. for arg in inputargs:
  505. self.possibly_free_var(arg)
  506. def flush_loop(self):
  507. # Emit a nop in the rare case where we have a guard_not_invalidated
  508. # immediately before a label
  509. mc = self.assembler.mc
  510. while self.min_bytes_before_label > mc.get_relative_pos():
  511. mc.nop()
  512. def get_gcmap(self, forbidden_regs=[], noregs=False):
  513. frame_depth = self.fm.get_frame_depth()
  514. gcmap = allocate_gcmap(self.assembler, frame_depth,
  515. r.JITFRAME_FIXED_SIZE)
  516. for box, loc in self.rm.reg_bindings.iteritems():
  517. if loc in forbidden_regs:
  518. continue
  519. if box.type == REF and self.rm.is_still_alive(box):
  520. assert not noregs
  521. assert loc.is_core_reg()
  522. val = self.assembler.cpu.all_reg_indexes[loc.value]
  523. gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
  524. for box, loc in self.fm.bindings.iteritems():
  525. if box.type == REF and self.rm.is_still_alive(box):
  526. assert isinstance(loc, l.StackLocation)
  527. val = loc.get_position() + r.JITFRAME_FIXED_SIZE
  528. gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
  529. return gcmap
  530. def loc(self, var):
  531. if var.type == FLOAT:
  532. return self.fprm.loc(var)
  533. else:
  534. return self.rm.loc(var)
  535. def next_instruction(self):
  536. self.rm.next_instruction()
  537. self.fprm.next_instruction()
  538. def force_spill_var(self, var):
  539. if var.type == FLOAT:
  540. self.fprm.force_spill_var(var)
  541. else:
  542. self.rm.force_spill_var(var)
  543. def _consider_force_spill(self, op):
  544. # This operation is used only for testing
  545. self.force_spill_var(op.getarg(0))
  546. def before_call(self, force_store=[], save_all_regs=False):
  547. self.rm.before_call(force_store, save_all_regs)
  548. self.fprm.before_call(force_store, save_all_regs)
  549. def after_call(self, v):
  550. if v.type == FLOAT:
  551. return self.fprm.after_call(v)
  552. else:
  553. return self.rm.after_call(v)
  554. def call_result_location(self, v):
  555. if v.type == FLOAT:
  556. return self.fprm.call_result_location(v)
  557. else:
  558. return self.rm.call_result_location(v)
  559. def ensure_reg_or_pool(self, box):
  560. if box.type == FLOAT:
  561. return self.fprm.ensure_reg_or_pool(box)
  562. else:
  563. return self.rm.ensure_reg_or_pool(box)
  564. def ensure_reg(self, box):
  565. if box.type == FLOAT:
  566. return self.fprm.ensure_reg(box)
  567. else:
  568. return self.rm.ensure_reg(box)
  569. def ensure_reg_or_16bit_imm(self, box):
  570. if box.type == FLOAT:
  571. return self.fprm.ensure_reg(box)
  572. else:
  573. if helper.check_imm(box):
  574. return imm(box.getint())
  575. return self.rm.ensure_reg(box)
  576. def ensure_reg_or_20bit_imm(self, box):
  577. if box.type == FLOAT:
  578. return self.fprm.ensure_reg(box)
  579. else:
  580. if helper.check_imm20(box):
  581. return imm(box.getint())
  582. return self.rm.ensure_reg(box)
  583. def ensure_reg_or_any_imm(self, box):
  584. if box.type == FLOAT:
  585. return self.fprm.ensure_reg(box)
  586. else:
  587. if isinstance(box, Const):
  588. return imm(box.getint())
  589. return self.rm.ensure_reg(box)
  590. def get_scratch_reg(self, type, selected_reg=None):
  591. if type == FLOAT:
  592. return self.fprm.get_scratch_reg()
  593. else:
  594. return self.rm.get_scratch_reg(selected_reg=selected_reg)
  595. def free_op_vars(self):
  596. # free the boxes in the 'temp_boxes' lists, which contain both
  597. # temporary boxes and all the current operation's arguments
  598. self.rm.free_temp_vars()
  599. self.fprm.free_temp_vars()
  600. def compute_hint_frame_locations(self, operations):
  601. # optimization only: fill in the 'hint_frame_locations' dictionary
  602. # of rm and xrm based on the JUMP at the end of the loop, by looking
  603. # at where we would like the boxes to be after the jump.
  604. op = operations[-1]
  605. if op.getopnum() != rop.JUMP:
  606. return
  607. self.final_jump_op = op
  608. descr = op.getdescr()
  609. assert isinstance(descr, TargetToken)
  610. if descr._ll_loop_code != 0:
  611. # if the target LABEL was already compiled, i.e. if it belongs
  612. # to some already-compiled piece of code
  613. self._compute_hint_frame_locations_from_descr(descr)
  614. #else:
  615. # The loop ends in a JUMP going back to a LABEL in the same loop.
  616. # We cannot fill 'hint_frame_locations' immediately, but we can
  617. # wait until the corresponding prepare_op_label() to know where the
  618. # we would like the boxes to be after the jump.
  619. def _compute_hint_frame_locations_from_descr(self, descr):
  620. arglocs = self.assembler.target_arglocs(descr)
  621. jump_op = self.final_jump_op
  622. assert len(arglocs) == jump_op.numargs()
  623. for i in range(jump_op.numargs()):
  624. box = jump_op.getarg(i)
  625. if not isinstance(box, Const):
  626. loc = arglocs[i]
  627. if loc is not None and loc.is_stack():
  628. self.fm.hint_frame_pos[box] = self.fm.get_loc_index(loc)
  629. def convert_to_int(self, c):
  630. if isinstance(c, ConstInt):
  631. return rffi.cast(lltype.Signed, c.value)
  632. else:
  633. assert isinstance(c, ConstPtr)
  634. return rffi.cast(lltype.Signed, c.value)
  635. # ******************************************************
  636. # * P R E P A R E O P E R A T I O N S *
  637. # ******************************************************
  638. def prepare_increment_debug_counter(self, op):
  639. immvalue = self.convert_to_int(op.getarg(0))
  640. base_loc = r.SCRATCH
  641. self.assembler.mc.load_imm(base_loc, immvalue)
  642. scratch = r.SCRATCH2
  643. return [base_loc, scratch]
  644. prepare_int_add = helper.prepare_int_add
  645. prepare_int_add_ovf = helper.prepare_int_add
  646. prepare_int_sub = helper.prepare_int_sub
  647. prepare_int_sub_ovf = helper.prepare_int_sub
  648. prepare_int_mul = helper.prepare_int_mul
  649. prepare_int_mul_ovf = helper.prepare_int_mul_ovf
  650. prepare_nursery_ptr_increment = prepare_int_add
  651. prepare_int_and = helper.prepare_int_logic
  652. prepare_int_or = helper.prepare_int_logic
  653. prepare_int_xor = helper.prepare_int_logic
  654. prepare_int_rshift = helper.prepare_int_shift
  655. prepare_int_lshift = helper.prepare_int_shift
  656. prepare_uint_rshift = helper.prepare_int_shift
  657. def prepare_uint_mul_high(self, op):
  658. a0 = op.getarg(0)
  659. a1 = op.getarg(1)
  660. if a0.is_constant():
  661. a0, a1 = a1, a0
  662. if helper.check_imm32(a1):
  663. l1 = self.ensure_reg(a1)
  664. else:
  665. l1 = self.ensure_reg_or_pool(a1)
  666. lr,lq = self.rm.ensure_even_odd_pair(a0, op, bind_first=True)
  667. return [lr, lq, l1]
  668. prepare_int_le = helper.generate_cmp_op()
  669. prepare_int_lt = helper.generate_cmp_op()
  670. prepare_int_ge = helper.generate_cmp_op()
  671. prepare_int_gt = helper.generate_cmp_op()
  672. prepare_int_eq = helper.generate_cmp_op()
  673. prepare_int_ne = helper.generate_cmp_op()
  674. prepare_ptr_eq = prepare_int_eq
  675. prepare_ptr_ne = prepare_int_ne
  676. prepare_instance_ptr_eq = prepare_ptr_eq
  677. prepare_instance_ptr_ne = prepare_ptr_ne
  678. prepare_uint_le = helper.generate_cmp_op(signed=False)
  679. prepare_uint_lt = helper.generate_cmp_op(signed=False)
  680. prepare_uint_ge = helper.generate_cmp_op(signed=False)
  681. prepare_uint_gt = helper.generate_cmp_op(signed=False)
  682. prepare_int_is_zero = helper.prepare_unary_cmp
  683. prepare_int_is_true = helper.prepare_unary_cmp
  684. prepare_int_neg = helper.prepare_unary_op
  685. prepare_int_invert = helper.prepare_unary_op
  686. prepare_int_signext = helper.prepare_unary_op
  687. prepare_int_force_ge_zero = helper.prepare_unary_op
  688. prepare_float_add = helper.generate_prepare_float_binary_op(allow_swap=True)
  689. prepare_float_sub = helper.generate_prepare_float_binary_op()
  690. prepare_float_mul = helper.generate_prepare_float_binary_op(allow_swap=True)
  691. prepare_float_truediv = helper.generate_prepare_float_binary_op()
  692. prepare_float_lt = helper.prepare_float_cmp_op
  693. prepare_float_le = helper.prepare_float_cmp_op
  694. prepare_float_eq = helper.prepare_float_cmp_op
  695. prepare_float_ne = helper.prepare_float_cmp_op
  696. prepare_float_gt = helper.prepare_float_cmp_op
  697. prepare_float_ge = helper.prepare_float_cmp_op
  698. prepare_float_neg = helper.prepare_unary_op
  699. prepare_float_abs = helper.prepare_unary_op
  700. prepare_cast_ptr_to_int = helper.prepare_same_as
  701. prepare_cast_int_to_ptr = helper.prepare_same_as
  702. prepare_same_as_i = helper.prepare_same_as
  703. prepare_same_as_r = helper.prepare_same_as
  704. prepare_same_as_f = helper.prepare_same_as
  705. def void(self, op):
  706. return []
  707. prepare_debug_merge_point = void
  708. prepare_jit_debug = void
  709. prepare_keepalive = void
  710. prepare_enter_portal_frame = void
  711. prepare_leave_portal_frame = void
  712. def _prepare_call(self, op):
  713. oopspecindex = self.get_oopspecindex(op)
  714. if oopspecindex == EffectInfo.OS_MATH_SQRT:
  715. return self._prepare_math_sqrt(op)
  716. if oopspecindex == EffectInfo.OS_THREADLOCALREF_GET:
  717. return self._prepare_threadlocalref_get(op)
  718. return self._prepare_call_default(op)
  719. prepare_call_i = _prepare_call
  720. prepare_call_r = _prepare_call
  721. prepare_call_f = _prepare_call
  722. prepare_call_n = _prepare_call
  723. def prepare_check_memory_error(self, op):
  724. loc = self.ensure_reg(op.getarg(0))
  725. return [loc]
  726. def prepare_call_malloc_nursery(self, op):
  727. self.rm.force_allocate_reg(op, selected_reg=r.RES)
  728. self.rm.temp_boxes.append(op)
  729. tmp_box = TempInt()
  730. self.rm.force_allocate_reg(tmp_box, selected_reg=r.RSZ)
  731. self.rm.temp_boxes.append(tmp_box)
  732. return []
  733. def prepare_call_malloc_nursery_varsize_frame(self, op):
  734. sizeloc = self.ensure_reg(op.getarg(0))
  735. # sizeloc must be in a register, but we can free it now
  736. # (we take care explicitly of conflicts with r.RES or r.RSZ)
  737. self.free_op_vars()
  738. # the result will be in r.RES
  739. self.rm.force_allocate_reg(op, selected_reg=r.RES)
  740. self.rm.temp_boxes.append(op)
  741. # we need r.RSZ as a temporary
  742. tmp_box = TempInt()
  743. self.rm.force_allocate_reg(tmp_box, selected_reg=r.RSZ)
  744. self.rm.temp_boxes.append(tmp_box)
  745. return [sizeloc]
  746. def prepare_call_malloc_nursery_varsize(self, op):
  747. # the result will be in r.RES
  748. self.rm.force_allocate_reg(op, selected_reg=r.RES)
  749. self.rm.temp_boxes.append(op)
  750. # we need r.RSZ as a temporary
  751. tmp_box = TempInt()
  752. self.rm.force_allocate_reg(tmp_box, selected_reg=r.RSZ)
  753. self.rm.temp_boxes.append(tmp_box)
  754. # length_box always survives: it's typically also present in the
  755. # next operation that will copy it inside the new array. Make
  756. # sure it is in a register different from r.RES and r.RSZ. (It
  757. # should not be a ConstInt at all.)
  758. length_box = op.getarg(2)
  759. assert not isinstance(length_box, Const)
  760. lengthloc = self.ensure_reg(length_box)
  761. return [lengthloc]
  762. def _prepare_gc_load(self, op):
  763. base_loc = self.ensure_reg(op.getarg(0))
  764. index_loc = self.ensure_reg_or_20bit_imm(op.getarg(1))
  765. size_box = op.getarg(2)
  766. assert isinstance(size_box, ConstInt)
  767. size = abs(size_box.value)
  768. sign_loc = imm0
  769. if size_box.value < 0:
  770. sign_loc = imm1
  771. result_loc = self.force_allocate_reg(op)
  772. self.free_op_vars()
  773. return [result_loc, base_loc, index_loc, imm(size), sign_loc]
  774. prepare_gc_load_i = _prepare_gc_load
  775. prepare_gc_load_f = _prepare_gc_load
  776. prepare_gc_load_r = _prepare_gc_load
  777. def _prepare_gc_load_indexed(self, op):
  778. base_loc = self.ensure_reg(op.getarg(0))
  779. index_loc = self.ensure_reg_or_20bit_imm(op.getarg(1))
  780. scale_box = op.getarg(2)
  781. offset_box = op.getarg(3)
  782. size_box = op.getarg(4)
  783. assert isinstance(scale_box, ConstInt)
  784. assert isinstance(offset_box, ConstInt)
  785. assert isinstance(size_box, ConstInt)
  786. scale = scale_box.value
  787. assert scale == 1
  788. offset = offset_box.value
  789. size = size_box.value
  790. size_loc = imm(abs(size))
  791. if size < 0:
  792. sign_loc = imm1
  793. else:
  794. sign_loc = imm0
  795. self.free_op_vars()
  796. result_loc = self.force_allocate_reg(op)
  797. return [result_loc, base_loc, index_loc, imm(offset), size_loc, sign_loc]
  798. prepare_gc_load_indexed_i = _prepare_gc_load_indexed
  799. prepare_gc_load_indexed_f = _prepare_gc_load_indexed
  800. prepare_gc_load_indexed_r = _prepare_gc_load_indexed
  801. def prepare_gc_store(self, op):
  802. base_loc = self.ensure_reg(op.getarg(0))
  803. index_loc = self.ensure_reg_or_20bit_imm(op.getarg(1))
  804. value_loc = self.ensure_reg(op.getarg(2))
  805. size_box = op.getarg(3)
  806. assert isinstance(size_box, ConstInt)
  807. size = abs(size_box.value)
  808. self.free_op_vars()
  809. return [base_loc, index_loc, value_loc, imm(size)]
  810. def prepare_gc_store_indexed(self, op):
  811. args = op.getarglist()
  812. base_loc = self.ensure_reg(op.getarg(0))
  813. index_loc = self.ensure_reg_or_20bit_imm(op.getarg(1))
  814. value_loc = self.ensure_reg(op.getarg(2))
  815. scale_box = op.getarg(3)
  816. offset_box = op.getarg(4)
  817. size_box = op.getarg(5)
  818. assert isinstance(scale_box, ConstInt)
  819. assert isinstance(offset_box, ConstInt)
  820. assert isinstance(size_box, ConstInt)
  821. factor = scale_box.value
  822. assert factor == 1
  823. offset = offset_box.value
  824. size = size_box.value
  825. return [base_loc, index_loc, value_loc, imm(offset), imm(abs(size))]
  826. def get_oopspecindex(self, op):
  827. descr = op.getdescr()
  828. assert descr is not None
  829. effectinfo = descr.get_extra_info()
  830. if effectinfo is not None:
  831. return effectinfo.oopspecindex
  832. return EffectInfo.OS_NONE
  833. def prepare_convert_float_bytes_to_longlong(self, op):
  834. loc1 = self.ensure_reg(op.getarg(0))
  835. res = self.force_allocate_reg(op)
  836. return [loc1, res]
  837. def prepare_convert_longlong_bytes_to_float(self, op):
  838. loc1 = self.ensure_reg(op.getarg(0))
  839. res = self.force_allocate_reg(op)
  840. return [loc1, res]
  841. def _spill_before_call(self, save_all_regs=False):
  842. # spill variables that need to be saved around calls
  843. self.fprm.before_call(save_all_regs=save_all_regs)
  844. if not save_all_regs:
  845. gcrootmap = self.assembler.cpu.gc_ll_descr.gcrootmap
  846. if gcrootmap and gcrootmap.is_shadow_stack:
  847. save_all_regs = 2
  848. self.rm.before_call(save_all_regs=save_all_regs)
  849. def _prepare_call_default(self, op, save_all_regs=False):
  850. args = [None]
  851. for i in range(op.numargs()):
  852. args.append(self.loc(op.getarg(i)))
  853. self._spill_before_call(save_all_regs)
  854. if op.type != VOID:
  855. resloc = self.after_call(op)
  856. args[0] = resloc
  857. return args
  858. def _prepare_call_may_force(self, op):
  859. return self._prepare_call_default(op, save_all_regs=True)
  860. prepare_call_may_force_i = _prepare_call_may_force
  861. prepare_call_may_force_r = _prepare_call_may_force
  862. prepare_call_may_force_f = _prepare_call_may_force
  863. prepare_call_may_force_n = _prepare_call_may_force
  864. def _prepare_call_release_gil(self, op):
  865. errno_box = op.getarg(0)
  866. assert isinstance(errno_box, ConstInt)
  867. args = [None, l.imm(errno_box.value)]
  868. for i in range(1,op.numargs()):
  869. args.append(self.loc(op.getarg(i)))
  870. self._spill_before_call(save_all_regs=True)
  871. if op.type != VOID:
  872. resloc = self.after_call(op)
  873. args[0] = resloc
  874. return args
  875. prepare_call_release_gil_i = _prepare_call_release_gil
  876. prepare_call_release_gil_f = _prepare_call_release_gil
  877. prepare_call_release_gil_n = _prepare_call_release_gil
  878. def prepare_force_token(self, op):
  879. res_loc = self.force_allocate_reg(op)
  880. return [res_loc]
  881. def _prepare_call_assembler(self, op):
  882. locs = self.locs_for_call_assembler(op)
  883. self._spill_before_call(save_all_regs=True)
  884. if op.type != VOID:
  885. resloc = self.after_call(op)
  886. else:
  887. resloc = None
  888. return [resloc] + locs
  889. prepare_call_assembler_i = _prepare_call_assembler
  890. prepare_call_assembler_r = _prepare_call_assembler
  891. prepare_call_assembler_f = _prepare_call_assembler
  892. prepare_call_assembler_n = _prepare_call_assembler
  893. def _prepare_threadlocalref_get(self, op):
  894. if self.cpu.translate_support_code:
  895. res = self.force_allocate_reg(op)
  896. return [res]
  897. else:
  898. return self._prepare_call_default(op)
  899. def prepare_zero_array(self, op):
  900. # args: base, start, len, scale_start, scale_len
  901. itemsize, ofs, _ = unpack_arraydescr(op.getdescr())
  902. startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1))
  903. ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
  904. base_loc, length_loc = self.rm.ensure_even_odd_pair(op.getarg(0), None,
  905. bind_first=True, must_exist=False, load_loc_odd=False)
  906. length_box = op.getarg(2)
  907. ll = self.rm.loc(length_box)
  908. if length_loc is not ll:
  909. self.assembler.regalloc_mov(ll, length_loc)
  910. return [base_loc, startindex_loc, length_loc, ofs_loc, imm(itemsize)]
  911. def prepare_cond_call(self, op):
  912. self.load_condition_into_cc(op.getarg(0))
  913. locs = []
  914. # support between 0 and 4 integer arguments
  915. assert 2 <= op.numargs() <= 2 + 4
  916. for i in range(1, op.numargs()):
  917. loc = self.loc(op.getarg(i))
  918. assert loc.type != FLOAT
  919. locs.append(loc)
  920. return locs
  921. def prepare_cond_call_gc_wb(self, op):
  922. arglocs = [self.ensure_reg(op.getarg(0))]
  923. return arglocs
  924. def prepare_cond_call_gc_wb_array(self, op):
  925. arglocs = [self.ensure_reg(op.getarg(0)),
  926. self.ensure_reg_or_16bit_imm(op.getarg(1)),
  927. None]
  928. if arglocs[1].is_reg():
  929. arglocs[2] = self.get_scratch_reg(INT)
  930. return arglocs
  931. def _prepare_math_sqrt(self, op):
  932. loc = self.ensure_reg(op.getarg(1))
  933. self.free_op_vars()
  934. # can be the same register as loc
  935. res = self.fprm.force_allocate_reg(op)
  936. return [loc, res]
  937. def prepare_cast_int_to_float(self, op):
  938. loc1 = self.ensure_reg(op.getarg(0))
  939. # ok not to use forbidden_vars, parameter is a int box
  940. res = self.fprm.force_allocate_reg(op)
  941. return [loc1, res]
  942. def prepare_cast_float_to_int(self, op):
  943. loc1 = self.ensure_reg(op.getarg(0))
  944. self.free_op_vars()
  945. # ok not to use forbidden_vars, parameter is a float box
  946. res = self.rm.force_allocate_reg(op)
  947. return [loc1, res]
  948. def _prepare_guard(self, op, args=None):
  949. if args is None:
  950. args = []
  951. args.append(imm(self.fm.get_frame_depth()))
  952. for arg in op.getfailargs():
  953. if arg:
  954. args.append(self.loc(arg))
  955. else:
  956. args.append(None)
  957. self.possibly_free_vars(op.getfailargs())
  958. #
  959. # generate_quick_failure() produces up to 14 instructions per guard
  960. self.limit_loop_break -= 14 * 4
  961. #
  962. return args
  963. def load_condition_into_cc(self, box):
  964. if self.assembler.guard_success_cc == c.cond_none:
  965. loc = self.ensure_reg(box)
  966. mc = self.assembler.mc
  967. mc.cmp_op(loc, l.imm(0), imm=True)
  968. self.assembler.guard_success_cc = c.NE
  969. def _prepare_guard_cc(self, op):
  970. self.load_condition_into_cc(op.getarg(0))
  971. return self._prepare_guard(op)
  972. prepare_guard_true = _prepare_guard_cc
  973. prepare_guard_false = _prepare_guard_cc
  974. prepare_guard_nonnull = _prepare_guard_cc
  975. prepare_guard_isnull = _prepare_guard_cc
  976. prepare_guard_overflow = _prepare_guard_cc
  977. def prepare_guard_class(self, op):
  978. x = self.ensure_reg(op.getarg(0))
  979. y_val = force_int(op.getarg(1).getint())
  980. arglocs = self._prepare_guard(op, [x, imm(y_val)])
  981. return arglocs
  982. prepare_guard_nonnull_class = prepare_guard_class
  983. prepare_guard_gc_type = prepare_guard_class
  984. prepare_guard_subclass = prepare_guard_class
  985. def prepare_guard_no_exception(self, op):
  986. arglocs = self._prepare_guard(op)
  987. return arglocs
  988. prepare_guard_no_overflow = prepare_guard_no_exception
  989. prepare_guard_overflow = prepare_guard_no_exception
  990. prepare_guard_not_forced = prepare_guard_no_exception
  991. def prepare_guard_not_forced_2(self, op):
  992. self.rm.before_call(op.getfailargs(), save_all_regs=True)
  993. arglocs = self._prepare_guard(op)
  994. return arglocs
  995. def prepare_guard_value(self, op):
  996. l0 = self.ensure_reg(op.getarg(0))
  997. l1 = self.ensure_reg_or_16bit_imm(op.getarg(1))
  998. arglocs = self._prepare_guard(op, [l0, l1])
  999. return arglocs
  1000. def prepare_guard_not_invalidated(self, op):
  1001. pos = self.assembler.mc.get_relative_pos()
  1002. self.ensure_next_label_is_at_least_at_position(pos + 4)
  1003. locs = self._prepare_guard(op)
  1004. return locs
  1005. def prepare_guard_exception(self, op):
  1006. loc = self.ensure_reg(op.getarg(0))
  1007. if op in self.longevity:
  1008. resloc = self.force_allocate_reg(op)
  1009. else:
  1010. resloc = None
  1011. arglocs = self._prepare_guard(op, [loc, resloc])
  1012. return arglocs
  1013. def prepare_guard_is_object(self, op):
  1014. loc_object = self.ensure_reg(op.getarg(0))
  1015. arglocs = self._prepare_guard(op, [loc_object])
  1016. return arglocs
  1017. def prepare_save_exception(self, op):
  1018. res = self.rm.force_allocate_reg(op)
  1019. return [res]
  1020. prepare_save_exc_class = prepare_save_exception
  1021. def prepare_restore_exception(self, op):
  1022. loc0 = self.ensure_reg(op.getarg(0))
  1023. loc1 = self.ensure_reg(op.getarg(1))
  1024. return [loc0, loc1]
  1025. def prepare_copystrcontent(self, op):
  1026. """ this function needs five registers.
  1027. src & src_len: are allocated using ensure_even_odd_pair.
  1028. note that these are tmp registers, thus the actual variable
  1029. value is not modified.
  1030. src_len: when entering the assembler, src_ofs_loc's value is contained
  1031. in src_len register.
  1032. """
  1033. src_ptr_loc, _ = \
  1034. self.rm.ensure_even_odd_pair(op.getarg(0),
  1035. None, bind_first=True,
  1036. must_exist=False, load_loc_odd=False)
  1037. src_ofs_loc = self.ensure_reg_or_any_imm(op.getarg(2))
  1038. dst_ptr_loc = self.ensure_reg(op.getarg(1))
  1039. dst_ofs_loc = self.ensure_reg_or_any_imm(op.getarg(3))
  1040. length_loc = self.ensure_reg_or_any_imm(op.getarg(4))
  1041. # no need to spill, we do not call memcpy, but we use s390x's
  1042. # hardware instruction to copy memory
  1043. return [src_ptr_loc, dst_ptr_loc,
  1044. src_ofs_loc, dst_ofs_loc, length_loc]
  1045. prepare_copyunicodecontent = prepare_copystrcontent
  1046. def prepare_label(self, op):
  1047. descr = op.getdescr()
  1048. assert isinstance(descr, TargetToken)
  1049. inputargs = op.getarglist()
  1050. arglocs = [None] * len(inputargs)
  1051. #
  1052. # we use force_spill() on the boxes that are not going to be really
  1053. # used any more in the loop, but that are kept alive anyway
  1054. # by being in a next LABEL's or a JUMP's argument or fail_args
  1055. # of some guard
  1056. position = self.rm.position
  1057. for arg in inputargs:
  1058. assert not isinstance(arg, Const)
  1059. if self.last_real_usage.get(arg, -1) <= position:
  1060. self.force_spill_var(arg)
  1061. #
  1062. # we need to make sure that no variable is stored in spp (=r31)
  1063. for arg in inputargs:
  1064. assert self.loc(arg) is not r.SPP, (
  1065. "variable stored in spp in prepare_label")
  1066. self.rm.bindings_to_frame_reg.clear()
  1067. #
  1068. for i in range(len(inputargs)):
  1069. arg = inputargs[i]
  1070. assert not isinstance(arg, Const)
  1071. loc = self.loc(arg)
  1072. assert loc is not r.SPP
  1073. arglocs[i] = loc
  1074. if loc.is_core_reg():
  1075. self.fm.mark_as_free(arg)
  1076. #
  1077. # if we are too close to the start of the loop, the label's target may
  1078. # get overridden by redirect_call_assembler(). (rare case)
  1079. self.flush_loop()
  1080. #
  1081. descr._zarch_arglocs = arglocs
  1082. descr._ll_loop_code = self.assembler.mc.currpos()
  1083. descr._zarch_clt = self.assembler.current_clt
  1084. self.assembler.target_tokens_currently_compiling[descr] = None
  1085. self.possibly_free_vars_for_op(op)
  1086. #
  1087. # if the LABEL's descr is precisely the target of the JUMP at the
  1088. # end of the same loop, i.e. if what we are compiling is a single
  1089. # loop that ends up jumping to this LABEL, then we can now provide
  1090. # the hints about the expected position of the spilled variables.
  1091. jump_op = self.final_jump_op
  1092. if jump_op is not None and jump_op.getdescr() is descr:
  1093. self._compute_hint_frame_locations_from_descr(descr)
  1094. def prepare_jump(self, op):
  1095. descr = op.getdescr()
  1096. assert isinstance(descr, TargetToken)
  1097. self.jump_target_descr = descr
  1098. arglocs = self.assembler.target_arglocs(descr)
  1099. # get temporary locs
  1100. tmploc = r.SCRATCH
  1101. fptmploc = r.FP_SCRATCH
  1102. # Part about non-floats
  1103. src_locations1 = []
  1104. dst_locations1 = []
  1105. src_locations2 = []
  1106. dst_locations2 = []
  1107. # Build the four lists
  1108. for i in range(op.numargs()):
  1109. box = op.getarg(i)
  1110. src_loc = self.loc(box)
  1111. dst_loc = arglocs[i]
  1112. if box.type != FLOAT:
  1113. src_locations1.append(src_loc)
  1114. dst_locations1.append(dst_loc)
  1115. else:
  1116. src_locations2.append(src_loc)
  1117. dst_locations2.append(dst_loc)
  1118. remap_frame_layout_mixed(self.assembler,
  1119. src_locations1, dst_locations1, tmploc,
  1120. src_locations2, dst_loca

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