PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/pypyjit/test/test_jit_hook.py

https://bitbucket.org/pypy/pypy/
Python | 258 lines | 248 code | 10 blank | 0 comment | 1 complexity | db5bfec6adfb36ee076a6024d38820c9 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from pypy.interpreter.gateway import interp2app
  3. from pypy.interpreter.pycode import PyCode
  4. from rpython.jit.metainterp.history import JitCellToken, ConstInt, ConstPtr,\
  5. BasicFailDescr
  6. from rpython.jit.metainterp.resoperation import rop
  7. from rpython.jit.metainterp.logger import Logger
  8. from rpython.rtyper.annlowlevel import (cast_instance_to_base_ptr,
  9. cast_base_ptr_to_instance)
  10. from rpython.rtyper.lltypesystem import lltype, llmemory
  11. from rpython.rtyper.rclass import OBJECT
  12. from pypy.module.pypyjit.interp_jit import pypyjitdriver
  13. from pypy.module.pypyjit.hooks import pypy_hooks
  14. from rpython.jit.tool.oparser import parse
  15. from rpython.jit.metainterp.typesystem import llhelper
  16. from rpython.rlib.jit import JitDebugInfo, AsmInfo, Counters
  17. class MockJitDriverSD(object):
  18. class warmstate(object):
  19. @staticmethod
  20. def get_location_str(boxes):
  21. ll_code = lltype.cast_opaque_ptr(lltype.Ptr(OBJECT),
  22. boxes[2].getref_base())
  23. pycode = cast_base_ptr_to_instance(PyCode, ll_code)
  24. return pycode.co_name
  25. jitdriver = pypyjitdriver
  26. class MockSD(object):
  27. class cpu(object):
  28. ts = llhelper
  29. jitdrivers_sd = [MockJitDriverSD]
  30. class AppTestJitHook(object):
  31. spaceconfig = dict(usemodules=('pypyjit',))
  32. def setup_class(cls):
  33. if cls.runappdirect:
  34. py.test.skip("Can't run this test with -A")
  35. w_f = cls.space.appexec([], """():
  36. def function():
  37. pass
  38. return function
  39. """)
  40. cls.w_f = w_f
  41. ll_code = cast_instance_to_base_ptr(w_f.code)
  42. code_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, ll_code)
  43. logger = Logger(MockSD())
  44. oplist = parse("""
  45. [i1, i2, p2]
  46. i3 = int_add(i1, i2)
  47. debug_merge_point(0, 0, 0, 0, 0, ConstPtr(ptr0))
  48. guard_nonnull(p2) []
  49. guard_true(i3) []
  50. """, namespace={'ptr0': code_gcref}).operations
  51. greenkey = [ConstInt(0), ConstInt(0), ConstPtr(code_gcref)]
  52. offset = {}
  53. for i, op in enumerate(oplist):
  54. if i != 1:
  55. offset[op] = i
  56. class FailDescr(BasicFailDescr):
  57. def get_jitcounter_hash(self):
  58. from rpython.rlib.rarithmetic import r_uint
  59. return r_uint(13)
  60. oplist[-1].setdescr(FailDescr())
  61. oplist[-2].setdescr(FailDescr())
  62. token = JitCellToken()
  63. token.number = 0
  64. di_loop = JitDebugInfo(MockJitDriverSD, logger, token, oplist, 'loop',
  65. greenkey)
  66. di_loop_optimize = JitDebugInfo(MockJitDriverSD, logger, JitCellToken(),
  67. oplist, 'loop', greenkey)
  68. di_loop.asminfo = AsmInfo(offset, 0x42, 12)
  69. di_bridge = JitDebugInfo(MockJitDriverSD, logger, JitCellToken(),
  70. oplist, 'bridge', fail_descr=FailDescr())
  71. di_bridge.asminfo = AsmInfo(offset, 0, 0)
  72. def interp_on_compile():
  73. di_loop.oplist = cls.oplist
  74. pypy_hooks.after_compile(di_loop)
  75. def interp_on_compile_bridge():
  76. pypy_hooks.after_compile_bridge(di_bridge)
  77. def interp_on_optimize():
  78. di_loop_optimize.oplist = cls.oplist
  79. pypy_hooks.before_compile(di_loop_optimize)
  80. def interp_on_abort():
  81. pypy_hooks.on_abort(Counters.ABORT_TOO_LONG, pypyjitdriver,
  82. greenkey, 'blah', Logger(MockSD), [])
  83. space = cls.space
  84. cls.w_on_compile = space.wrap(interp2app(interp_on_compile))
  85. cls.w_on_compile_bridge = space.wrap(interp2app(interp_on_compile_bridge))
  86. cls.w_on_abort = space.wrap(interp2app(interp_on_abort))
  87. cls.w_int_add_num = space.wrap(rop.INT_ADD)
  88. cls.w_dmp_num = space.wrap(rop.DEBUG_MERGE_POINT)
  89. cls.w_on_optimize = space.wrap(interp2app(interp_on_optimize))
  90. cls.orig_oplist = oplist
  91. cls.w_sorted_keys = space.wrap(sorted(Counters.counter_names))
  92. def setup_method(self, meth):
  93. self.__class__.oplist = self.orig_oplist[:]
  94. def test_on_compile(self):
  95. import pypyjit
  96. all = []
  97. def hook(info):
  98. all.append(info)
  99. self.on_compile()
  100. pypyjit.set_compile_hook(hook)
  101. assert not all
  102. self.on_compile()
  103. assert len(all) == 1
  104. info = all[0]
  105. assert info.jitdriver_name == 'pypyjit'
  106. assert info.greenkey[0].co_name == 'function'
  107. assert info.greenkey[1] == 0
  108. assert info.greenkey[2] == False
  109. assert info.loop_no == 0
  110. assert info.type == 'loop'
  111. assert info.asmaddr == 0x42
  112. assert info.asmlen == 12
  113. raises(TypeError, 'info.bridge_no')
  114. assert len(info.operations) == 4
  115. int_add = info.operations[0]
  116. dmp = info.operations[1]
  117. assert isinstance(dmp, pypyjit.DebugMergePoint)
  118. assert dmp.pycode is self.f.func_code
  119. assert dmp.greenkey == (self.f.func_code, 0, False)
  120. assert dmp.call_depth == 0
  121. assert dmp.call_id == 0
  122. assert dmp.offset == -1
  123. assert int_add.name == 'int_add'
  124. assert int_add.offset == 0
  125. self.on_compile_bridge()
  126. expected = ('<JitLoopInfo pypyjit, 4 operations, starting at '
  127. '<(%s, 0, False)>>' % repr(self.f.func_code))
  128. assert repr(all[0]) == expected
  129. assert len(all) == 2
  130. pypyjit.set_compile_hook(None)
  131. self.on_compile()
  132. assert len(all) == 2
  133. def test_on_compile_exception(self):
  134. import pypyjit, sys, cStringIO
  135. def hook(*args):
  136. 1/0
  137. pypyjit.set_compile_hook(hook)
  138. s = cStringIO.StringIO()
  139. prev = sys.stderr
  140. sys.stderr = s
  141. try:
  142. self.on_compile()
  143. finally:
  144. sys.stderr = prev
  145. assert 'jit hook' in s.getvalue()
  146. assert 'ZeroDivisionError' in s.getvalue()
  147. def test_on_compile_crashes(self):
  148. import pypyjit
  149. loops = []
  150. def hook(loop):
  151. loops.append(loop)
  152. pypyjit.set_compile_hook(hook)
  153. self.on_compile()
  154. loop = loops[0]
  155. op = loop.operations[2]
  156. assert op.name == 'guard_nonnull'
  157. def test_non_reentrant(self):
  158. import pypyjit
  159. l = []
  160. def hook(*args):
  161. l.append(None)
  162. self.on_compile()
  163. self.on_compile_bridge()
  164. pypyjit.set_compile_hook(hook)
  165. self.on_compile()
  166. assert len(l) == 1 # and did not crash
  167. self.on_compile_bridge()
  168. assert len(l) == 2 # and did not crash
  169. def test_on_compile_types(self):
  170. import pypyjit
  171. l = []
  172. def hook(info):
  173. l.append(info)
  174. pypyjit.set_compile_hook(hook)
  175. self.on_compile()
  176. op = l[0].operations[1]
  177. assert isinstance(op, pypyjit.ResOperation)
  178. assert 'function' in repr(op)
  179. def test_on_abort(self):
  180. import pypyjit
  181. l = []
  182. def hook(jitdriver_name, greenkey, reason, operations):
  183. l.append((jitdriver_name, reason, operations))
  184. pypyjit.set_abort_hook(hook)
  185. self.on_abort()
  186. assert l == [('pypyjit', 'ABORT_TOO_LONG', [])]
  187. def test_creation(self):
  188. from pypyjit import ResOperation
  189. op = ResOperation("int_add", -1, "int_add(1, 2)")
  190. assert op.name == 'int_add'
  191. assert repr(op) == "int_add(1, 2)"
  192. def test_creation_dmp(self):
  193. from pypyjit import DebugMergePoint
  194. def f():
  195. pass
  196. op = DebugMergePoint("debug_merge_point", 'repr', 'pypyjit', 2, 3, (f.func_code, 0, 0))
  197. assert op.bytecode_no == 0
  198. assert op.pycode is f.func_code
  199. assert repr(op) == 'repr'
  200. assert op.jitdriver_name == 'pypyjit'
  201. assert op.name == 'debug_merge_point'
  202. assert op.call_depth == 2
  203. assert op.call_id == 3
  204. op = DebugMergePoint('debug_merge_point', 'repr', 'notmain',
  205. 5, 4, ('str',))
  206. raises(AttributeError, 'op.pycode')
  207. assert op.call_depth == 5
  208. def test_get_stats_snapshot(self):
  209. skip("a bit no idea how to test it")
  210. from pypyjit import get_stats_snapshot
  211. stats = get_stats_snapshot() # we can't do much here, unfortunately
  212. assert stats.w_loop_run_times == []
  213. assert isinstance(stats.w_counters, dict)
  214. assert sorted(stats.w_counters.keys()) == self.sorted_keys