PageRenderTime 71ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/translator/c/gcc/test/test_asmgcroot.py

https://bitbucket.org/pypy/pypy/
Python | 252 lines | 245 code | 5 blank | 2 comment | 7 complexity | 1927471ffef3d9da818b61805b207879 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. import sys, os, gc
  3. from pypy.translator.c.test import test_newgc
  4. from pypy.translator.translator import TranslationContext
  5. from pypy.translator.c.genc import CStandaloneBuilder
  6. from pypy.annotation.listdef import s_list_of_strings
  7. from pypy import conftest
  8. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  9. from pypy.rpython.lltypesystem import lltype, rffi
  10. from pypy.rlib.entrypoint import entrypoint, secondary_entrypoints
  11. from pypy.rpython.lltypesystem.lloperation import llop
  12. class AbstractTestAsmGCRoot:
  13. # the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
  14. # instructions:
  15. should_be_moving = False
  16. @classmethod
  17. def make_config(cls):
  18. from pypy.config.pypyoption import get_pypy_config
  19. config = get_pypy_config(translating=True)
  20. config.translation.gc = cls.gcpolicy
  21. config.translation.gcrootfinder = "asmgcc"
  22. config.translation.taggedpointers = getattr(cls, "taggedpointers", False)
  23. return config
  24. @classmethod
  25. def _makefunc_str_int(cls, func):
  26. def main(argv):
  27. arg0 = argv[1]
  28. arg1 = int(argv[2])
  29. try:
  30. res = func(arg0, arg1)
  31. except MemoryError:
  32. print 'Result: MemoryError'
  33. else:
  34. print 'Result: "%s"' % (res,)
  35. return 0
  36. config = cls.make_config()
  37. t = TranslationContext(config=config)
  38. a = t.buildannotator()
  39. sec_ep = getattr(cls, 'secondary_entrypoints', [])
  40. for f, inputtypes in sec_ep:
  41. a.build_types(f, inputtypes, False)
  42. a.build_types(main, [s_list_of_strings])
  43. t.buildrtyper().specialize()
  44. t.checkgraphs()
  45. cbuilder = CStandaloneBuilder(t, main, config=config,
  46. secondary_entrypoints=sec_ep)
  47. c_source_filename = cbuilder.generate_source(
  48. defines = cbuilder.DEBUG_DEFINES)
  49. cls._patch_makefile(cbuilder.targetdir)
  50. if conftest.option.view:
  51. t.view()
  52. exe_name = cbuilder.compile()
  53. def run(arg0, arg1):
  54. lines = []
  55. print >> sys.stderr, 'RUN: starting', exe_name, arg0, arg1
  56. if sys.platform == 'win32':
  57. redirect = ' 2> NUL'
  58. else:
  59. redirect = ''
  60. if config.translation.shared and os.name == 'posix':
  61. env = 'LD_LIBRARY_PATH="%s" ' % (exe_name.dirpath(),)
  62. else:
  63. env = ''
  64. cwd = os.getcwd()
  65. try:
  66. os.chdir(str(exe_name.dirpath()))
  67. g = os.popen(
  68. '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r')
  69. finally:
  70. os.chdir(cwd)
  71. for line in g:
  72. print >> sys.stderr, 'RUN:', line.rstrip()
  73. lines.append(line)
  74. g.close()
  75. if not lines:
  76. py.test.fail("no output from subprocess")
  77. if not lines[-1].startswith('Result:'):
  78. py.test.fail("unexpected output from subprocess")
  79. result = lines[-1][len('Result:'):].strip()
  80. if result == 'MemoryError':
  81. raise MemoryError("subprocess got an RPython MemoryError")
  82. if result.startswith('"') and result.endswith('"'):
  83. return result[1:-1]
  84. else:
  85. return int(result)
  86. return run
  87. @classmethod
  88. def _patch_makefile(cls, targetdir):
  89. # for testing, patch the Makefile to add the -r option to
  90. # trackgcroot.py.
  91. makefile = targetdir.join('Makefile')
  92. f = makefile.open()
  93. lines = f.readlines()
  94. f.close()
  95. found = False
  96. for i in range(len(lines)):
  97. if 'trackgcroot.py' in lines[i]:
  98. lines[i] = lines[i].replace('trackgcroot.py',
  99. 'trackgcroot.py -r')
  100. found = True
  101. assert found
  102. f = makefile.open('w')
  103. f.writelines(lines)
  104. f.close()
  105. if sys.platform == 'win32':
  106. def test_callback_with_collect(self):
  107. py.test.skip("No libffi yet with mingw32")
  108. def define_callback_with_collect(cls):
  109. return lambda: 0
  110. class TestAsmGCRootWithSemiSpaceGC(AbstractTestAsmGCRoot,
  111. test_newgc.TestSemiSpaceGC):
  112. # for the individual tests see
  113. # ====> ../../test/test_newgc.py
  114. secondary_entrypoints = []
  115. def define_large_function(cls):
  116. class A(object):
  117. def __init__(self):
  118. self.x = 0
  119. d = dict(A=A)
  120. exec ("def g(a):\n" +
  121. " a.x += 1\n" * 1000 +
  122. " return A()\n"
  123. ) in d
  124. g = d['g']
  125. def f():
  126. a = A()
  127. g(a)
  128. return a.x
  129. return f
  130. def test_large_function(self):
  131. res = self.run('large_function')
  132. assert res == 1000
  133. def define_callback_simple(cls):
  134. c_source = py.code.Source("""
  135. int mystuff(int(*cb)(int, int))
  136. {
  137. return cb(40, 2) + cb(3, 4);
  138. }
  139. """)
  140. eci = ExternalCompilationInfo(separate_module_sources=[c_source])
  141. S = lltype.GcStruct('S', ('x', lltype.Signed))
  142. CALLBACK = lltype.FuncType([lltype.Signed, lltype.Signed],
  143. lltype.Signed)
  144. z = rffi.llexternal('mystuff', [lltype.Ptr(CALLBACK)], lltype.Signed,
  145. compilation_info=eci)
  146. def mycallback(a, b):
  147. gc.collect()
  148. return a + b
  149. def f():
  150. p = lltype.malloc(S)
  151. p.x = 100
  152. result = z(mycallback)
  153. return result * p.x
  154. return f
  155. def test_callback_simple(self):
  156. res = self.run('callback_simple')
  157. assert res == 4900
  158. def define_secondary_entrypoint_callback(cls):
  159. # XXX this is baaaad, cleanup global state
  160. try:
  161. del secondary_entrypoints["x42"]
  162. except KeyError:
  163. pass
  164. @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback')
  165. def mycallback(a, b):
  166. llop.gc_stack_bottom(lltype.Void)
  167. rffi.stackcounter.stacks_counter += 1
  168. gc.collect()
  169. rffi.stackcounter.stacks_counter -= 1
  170. return a + b
  171. c_source = py.code.Source("""
  172. int mystuff2()
  173. {
  174. return callback(40, 2) + callback(3, 4);
  175. }
  176. """)
  177. eci = ExternalCompilationInfo(separate_module_sources=[c_source])
  178. z = rffi.llexternal('mystuff2', [], lltype.Signed,
  179. compilation_info=eci)
  180. S = lltype.GcStruct('S', ('x', lltype.Signed))
  181. cls.secondary_entrypoints = secondary_entrypoints["x42"]
  182. def f():
  183. p = lltype.malloc(S)
  184. p.x = 100
  185. result = z()
  186. return result * p.x
  187. return f
  188. def test_secondary_entrypoint_callback(self):
  189. res = self.run('secondary_entrypoint_callback')
  190. assert res == 4900
  191. class TestAsmGCRootWithSemiSpaceGC_Mingw32(TestAsmGCRootWithSemiSpaceGC):
  192. # for the individual tests see
  193. # ====> ../../test/test_newgc.py
  194. @classmethod
  195. def setup_class(cls):
  196. if sys.platform != 'win32':
  197. py.test.skip("mingw32 specific test")
  198. if not ('mingw' in os.popen('gcc --version').read() and
  199. 'GNU' in os.popen('make --version').read()):
  200. py.test.skip("mingw32 and MSYS are required for this test")
  201. test_newgc.TestSemiSpaceGC.setup_class.im_func(cls)
  202. @classmethod
  203. def make_config(cls):
  204. config = TestAsmGCRootWithSemiSpaceGC.make_config()
  205. config.translation.cc = 'mingw32'
  206. return config
  207. def test_callback_with_collect(self):
  208. py.test.skip("No libffi yet with mingw32")
  209. def define_callback_with_collect(cls):
  210. return lambda: 0
  211. class TestAsmGCRootWithSemiSpaceGC_Shared(TestAsmGCRootWithSemiSpaceGC):
  212. @classmethod
  213. def make_config(cls):
  214. config = TestAsmGCRootWithSemiSpaceGC.make_config()
  215. config.translation.shared = True
  216. return config
  217. class TestAsmGCRootWithHybridTagged(AbstractTestAsmGCRoot,
  218. test_newgc.TestHybridTaggedPointers):
  219. pass