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

/rpython/jit/backend/zarch/pool.py

https://bitbucket.org/pypy/pypy/
Python | 135 lines | 100 code | 17 blank | 18 comment | 18 complexity | 334208b0a1acfbc57fb0a336c17baa76 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.jit.backend.zarch import registers as r
  2. from rpython.jit.backend.zarch import locations as l
  3. from rpython.rlib import rgil
  4. from rpython.jit.metainterp.history import (INT, REF, FLOAT,
  5. TargetToken)
  6. from rpython.rlib.objectmodel import we_are_translated
  7. from rpython.rtyper.lltypesystem.lloperation import llop
  8. from rpython.jit.metainterp.resoperation import rop
  9. from rpython.jit.metainterp.history import Const
  10. from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
  11. from rpython.jit.backend.zarch.arch import (WORD,
  12. RECOVERY_GCMAP_POOL_OFFSET, RECOVERY_TARGET_POOL_OFFSET)
  13. from rpython.rlib.longlong2float import float2longlong
  14. from rpython.jit.metainterp.history import (ConstFloat,
  15. ConstInt, ConstPtr)
  16. class PoolOverflow(Exception):
  17. pass
  18. class LiteralPool(object):
  19. def __init__(self):
  20. self.size = 0
  21. # the offset to index the pool
  22. self.pool_start = 0
  23. # for constant offsets
  24. self.offset_map = {}
  25. # for descriptors
  26. self.offset_descr = {}
  27. def reset(self):
  28. self.pool_start = 0
  29. self.size = 0
  30. self.offset_map = {}
  31. self.offset_descr = {}
  32. def ensure_can_hold_constants(self, asm, op):
  33. # allocates 8 bytes in memory for pointers, long integers or floats
  34. if rop.is_jit_debug(op.getopnum()):
  35. return
  36. for arg in op.getarglist():
  37. if arg.is_constant():
  38. self.reserve_literal(8, arg, asm)
  39. def contains_constant(self, unique_val):
  40. return unique_val in self.offset_map
  41. def get_descr_offset(self, descr):
  42. return self.offset_descr[descr]
  43. def contains_box(self, box):
  44. uvalue = self.unique_value(box)
  45. return self.contains_constant(uvalue)
  46. def get_offset(self, box):
  47. assert box.is_constant()
  48. uvalue = self.unique_value(box)
  49. if not we_are_translated():
  50. assert self.offset_map[uvalue] >= 0
  51. return self.offset_map[uvalue]
  52. def unique_value(self, val):
  53. if isinstance(val, ConstFloat):
  54. if val.getfloat() == 0.0:
  55. return 0
  56. return float2longlong(val.getfloat())
  57. elif isinstance(val, ConstInt):
  58. return rffi.cast(lltype.Signed, val.getint())
  59. else:
  60. assert isinstance(val, ConstPtr)
  61. return rffi.cast(lltype.Signed, val.getref_base())
  62. def reserve_literal(self, size, box, asm):
  63. uvalue = self.unique_value(box)
  64. if box.type == INT and -2**31 <= uvalue <= 2**31-1:
  65. # we do not allocate non 64 bit values, these
  66. # can be loaded as imm by LGHI/LGFI
  67. return
  68. #
  69. self._ensure_value(uvalue, asm)
  70. def check_size(self, size=-1):
  71. if size == -1:
  72. size = self.size
  73. if size >= 2**19:
  74. msg = '[S390X/literalpool] size exceeded %d >= %d\n' % (size, 2**19)
  75. if we_are_translated():
  76. llop.debug_print(lltype.Void, msg)
  77. raise PoolOverflow(msg)
  78. def _ensure_value(self, uvalue, asm):
  79. if uvalue not in self.offset_map:
  80. self.offset_map[uvalue] = self.size
  81. self.allocate_slot(8)
  82. asm.mc.write_i64(uvalue)
  83. return self.offset_map[uvalue]
  84. def allocate_slot(self, size):
  85. val = self.size + size
  86. self.check_size(val)
  87. self.size = val
  88. assert val >= 0
  89. def pre_assemble(self, asm, operations, allgcrefs, bridge=False):
  90. # Problem:
  91. # constants such as floating point operations, plain pointers,
  92. # or integers might serve as parameter to an operation. thus
  93. # it must be loaded into a register. Loading them from immediate
  94. # takes quite long and slows down the resulting JIT code.
  95. # There is a space benefit for 64-bit integers/doubles used twice.
  96. #
  97. # creates the table for gc references here
  98. self.gc_table_addr = asm.mc.get_relative_pos()
  99. self.gcref_table_size = len(allgcrefs) * WORD
  100. mc = asm.mc
  101. assert mc.get_relative_pos() == 0
  102. for i in range(self.gcref_table_size):
  103. mc.writechar('\x00')
  104. asm.setup_gcrefs_list(allgcrefs)
  105. self.pool_start = asm.mc.get_relative_pos()
  106. for op in operations:
  107. self.ensure_can_hold_constants(asm, op)
  108. self._ensure_value(asm.cpu.pos_exc_value(), asm)
  109. # the top of shadow stack
  110. gcrootmap = asm.cpu.gc_ll_descr.gcrootmap
  111. if gcrootmap and gcrootmap.is_shadow_stack:
  112. self._ensure_value(gcrootmap.get_root_stack_top_addr(), asm)
  113. # endaddr of insert stack check
  114. endaddr, lengthaddr, _ = asm.cpu.insert_stack_check()
  115. self._ensure_value(endaddr, asm)
  116. # fast gil
  117. fastgil = rffi.cast(lltype.Signed, rgil.gil_fetch_fastgil())
  118. self._ensure_value(fastgil, asm)