/pypy/translator/c/test/test_refcount.py

https://github.com/alemacgo/pypy · Python · 239 lines · 215 code · 20 blank · 4 comment · 17 complexity · e73e9f813bed3f4879485d329add521f MD5 · raw file

  1. import py
  2. import os
  3. from pypy.translator.translator import TranslationContext
  4. from pypy.translator.c import genc
  5. from pypy.rpython.lltypesystem import lltype
  6. from pypy import conftest
  7. def compile_func(fn, inputtypes, t=None, gcpolicy="ref"):
  8. from pypy.config.pypyoption import get_pypy_config
  9. config = get_pypy_config(translating=True)
  10. config.translation.gc = gcpolicy
  11. config.translation.countmallocs = True
  12. if t is None:
  13. t = TranslationContext(config=config)
  14. if inputtypes is not None:
  15. t.buildannotator().build_types(fn, inputtypes)
  16. t.buildrtyper().specialize()
  17. builder = genc.CExtModuleBuilder(t, fn, config=config)
  18. builder.generate_source()
  19. builder.compile()
  20. if conftest.option.view:
  21. t.view()
  22. compiled_fn = builder.get_entry_point()
  23. malloc_counters = builder.get_malloc_counters()
  24. def checking_fn(*args, **kwds):
  25. try:
  26. return compiled_fn(*args, **kwds)
  27. finally:
  28. mallocs, frees = malloc_counters()
  29. assert mallocs == frees
  30. return checking_fn
  31. def test_something():
  32. def f():
  33. return 1
  34. fn = compile_func(f, [])
  35. assert fn() == 1
  36. def test_something_more():
  37. S = lltype.GcStruct("S", ('x', lltype.Signed))
  38. def f(x):
  39. s = lltype.malloc(S)
  40. s.x = x
  41. return s.x
  42. fn = compile_func(f, [int])
  43. assert fn(1) == 1
  44. def test_call_function():
  45. class C:
  46. pass
  47. def f():
  48. c = C()
  49. c.x = 1
  50. return c
  51. def g():
  52. return f().x
  53. fn = compile_func(g, [])
  54. assert fn() == 1
  55. def test_multiple_exits():
  56. S = lltype.GcStruct("S", ('x', lltype.Signed))
  57. T = lltype.GcStruct("T", ('y', lltype.Signed))
  58. def f(n):
  59. c = lltype.malloc(S)
  60. d = lltype.malloc(T)
  61. d.y = 1
  62. e = lltype.malloc(T)
  63. e.y = 2
  64. if n:
  65. x = d
  66. else:
  67. x = e
  68. return x.y
  69. fn = compile_func(f, [int])
  70. assert fn(1) == 1
  71. assert fn(0) == 2
  72. def test_cleanup_vars_on_call():
  73. S = lltype.GcStruct("S", ('x', lltype.Signed))
  74. def f():
  75. return lltype.malloc(S)
  76. def g():
  77. s1 = f()
  78. s1.x = 42
  79. s2 = f()
  80. s3 = f()
  81. return s1.x
  82. fn = compile_func(g, [])
  83. assert fn() == 42
  84. def test_multiply_passed_var():
  85. S = lltype.GcStruct("S", ('x', lltype.Signed))
  86. def f(x):
  87. if x:
  88. a = lltype.malloc(S)
  89. a.x = 1
  90. b = a
  91. else:
  92. a = lltype.malloc(S)
  93. a.x = 1
  94. b = lltype.malloc(S)
  95. b.x = 2
  96. return a.x + b.x
  97. fn = compile_func(f, [int])
  98. fn(1) == 2
  99. fn(0) == 3
  100. def test_write_barrier():
  101. S = lltype.GcStruct("S", ('x', lltype.Signed))
  102. T = lltype.GcStruct("T", ('s', lltype.Ptr(S)))
  103. def f(x):
  104. s = lltype.malloc(S)
  105. s.x = 0
  106. s1 = lltype.malloc(S)
  107. s1.x = 1
  108. s2 = lltype.malloc(S)
  109. s2.x = 2
  110. t = lltype.malloc(T)
  111. t.s = s
  112. if x:
  113. t.s = s1
  114. else:
  115. t.s = s2
  116. return t.s.x + s.x + s1.x + s2.x
  117. fn = compile_func(f, [int])
  118. assert fn(1) == 4
  119. assert fn(0) == 5
  120. def test_del_basic():
  121. for gcpolicy in ["ref"]: #, "framework"]:
  122. S = lltype.GcStruct('S', ('x', lltype.Signed), rtti=True)
  123. TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed))
  124. GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed))
  125. glob = lltype.malloc(GLOBAL, immortal=True)
  126. def destructor(s):
  127. glob.x = s.x + 1
  128. def type_info_S(s):
  129. return lltype.getRuntimeTypeInfo(S)
  130. def g(n):
  131. s = lltype.malloc(S)
  132. s.x = n
  133. # now 's' should go away
  134. def entrypoint(n):
  135. g(n)
  136. # llop.gc__collect(lltype.Void)
  137. return glob.x
  138. t = TranslationContext()
  139. t.buildannotator().build_types(entrypoint, [int])
  140. rtyper = t.buildrtyper()
  141. destrptr = rtyper.annotate_helper_fn(destructor, [lltype.Ptr(S)])
  142. rtyper.attachRuntimeTypeInfoFunc(S, type_info_S, destrptr=destrptr)
  143. rtyper.specialize()
  144. fn = compile_func(entrypoint, None, t, gcpolicy=gcpolicy)
  145. res = fn(123)
  146. assert res == 124
  147. def test_del_catches():
  148. import os
  149. def g():
  150. pass
  151. class A(object):
  152. def __del__(self):
  153. try:
  154. g()
  155. except:
  156. os.write(1, "hallo")
  157. def f1(i):
  158. if i:
  159. raise TypeError
  160. def f(i):
  161. a = A()
  162. f1(i)
  163. a.b = 1
  164. return a.b
  165. fn = compile_func(f, [int])
  166. assert fn(0) == 1
  167. assert py.test.raises(TypeError, fn, 1)
  168. def test_del_raises():
  169. class B(object):
  170. def __del__(self):
  171. raise TypeError
  172. def func():
  173. b = B()
  174. fn = compile_func(func, [])
  175. # does not crash
  176. fn()
  177. def test_wrong_order_setitem():
  178. import os
  179. class A(object):
  180. pass
  181. a = A()
  182. a.b = None
  183. class B(object):
  184. def __del__(self):
  185. a.freed += 1
  186. a.b = None
  187. def f(n):
  188. a.freed = 0
  189. a.b = B()
  190. if n:
  191. a.b = None
  192. return a.freed
  193. fn = compile_func(f, [int])
  194. res = fn(1)
  195. assert res == 1
  196. def test_wrong_startblock_incref():
  197. class B(object):
  198. pass
  199. def g(b):
  200. while True:
  201. b.x -= 10
  202. if b.x < 0:
  203. return b.x
  204. def f(n):
  205. b = B()
  206. b.x = n
  207. return g(b)
  208. # XXX obscure: remove the first empty block in the graph of 'g'
  209. t = TranslationContext()
  210. graph = t.buildflowgraph(g)
  211. assert graph.startblock.operations == []
  212. graph.startblock = graph.startblock.exits[0].target
  213. graph.startblock.isstartblock = True
  214. from pypy.objspace.flow.model import checkgraph
  215. checkgraph(graph)
  216. t._prebuilt_graphs[g] = graph
  217. fn = compile_func(f, [int], t)
  218. res = fn(112)
  219. assert res == -8