/pypy/rpython/lltypesystem/test/test_rtagged.py

https://github.com/alemacgo/pypy · Python · 253 lines · 215 code · 36 blank · 2 comment · 40 complexity · f2cb602b5c55a0f0ba84d548ab30bdbc MD5 · raw file

  1. import sys
  2. from pypy.rpython.test.test_llinterp import interpret, get_interpreter
  3. from pypy.rpython.lltypesystem import lltype
  4. from pypy.rlib.objectmodel import UnboxedValue
  5. from pypy.translator.translator import graphof
  6. from pypy.objspace.flow.model import summary
  7. from pypy.translator.backendopt.all import backend_optimizations
  8. from pypy import conftest
  9. class A(object):
  10. __slots__ = ()
  11. def meth(self, x):
  12. raise NotImplementedError
  13. class B(A):
  14. attrvalue = 66
  15. def __init__(self, normalint):
  16. self.normalint = normalint
  17. def meth(self, x):
  18. return self.normalint + x + 2
  19. class C(A, UnboxedValue):
  20. __slots__ = 'smallint'
  21. def meth(self, x):
  22. return self.smallint + x + 3
  23. class D(B):
  24. attrvalue = 68
  25. # ____________________________________________________________
  26. def test_instantiate():
  27. def fn1(n):
  28. return C(n)
  29. res = interpret(fn1, [42], taggedpointers=True)
  30. value = lltype.cast_ptr_to_int(res)
  31. assert value == 42 * 2 + 1 # for now
  32. def test_attribute():
  33. def fn1(n):
  34. return C(n).smallint
  35. res = interpret(fn1, [42], taggedpointers=True)
  36. assert res == 42
  37. def test_get_untagged_value():
  38. def fn1(n):
  39. return C(n).get_untagged_value()
  40. res = interpret(fn1, [42], taggedpointers=True)
  41. assert res == 42
  42. def test_overflowerror():
  43. def makeint(n):
  44. try:
  45. return C(n)
  46. except OverflowError: # 'n' out of range
  47. return B(n)
  48. def fn2(n):
  49. x = makeint(n)
  50. if isinstance(x, B):
  51. return 'B', x.normalint
  52. elif isinstance(x, C):
  53. return 'C', x.smallint
  54. else:
  55. return 'A', 0
  56. res = interpret(fn2, [-117], taggedpointers=True)
  57. assert res.item0 == 'C'
  58. assert res.item1 == -117
  59. res = interpret(fn2, [sys.maxint], taggedpointers=True)
  60. assert res.item0 == 'B'
  61. assert res.item1 == sys.maxint
  62. def test_prebuilt():
  63. c = C(111)
  64. b = B(939393)
  65. def makeint(n):
  66. if n < 0:
  67. x = c
  68. elif n > 0:
  69. x = C(n)
  70. else:
  71. x = b
  72. return x
  73. def fn(n):
  74. x = makeint(n)
  75. if isinstance(x, B):
  76. return 'B', x.normalint
  77. elif isinstance(x, C):
  78. return 'C', x.smallint
  79. else:
  80. return 'A', 0
  81. res = interpret(fn, [12], taggedpointers=True)
  82. assert res.item0 == 'C'
  83. assert res.item1 == 12
  84. res = interpret(fn, [-1], taggedpointers=True)
  85. assert res.item0 == 'C'
  86. assert res.item1 == 111
  87. res = interpret(fn, [0], taggedpointers=True)
  88. assert res.item0 == 'B'
  89. assert res.item1 == 939393
  90. def test_C_or_None():
  91. def g(x):
  92. if x is None:
  93. return sys.maxint
  94. else:
  95. return x.smallint
  96. def fn(n):
  97. if n < 0:
  98. x = None
  99. else:
  100. x = C(n)
  101. return g(x)
  102. res = interpret(fn, [-1], taggedpointers=True)
  103. assert res == sys.maxint
  104. res = interpret(fn, [56], taggedpointers=True)
  105. assert res == 56
  106. def test_type():
  107. def fn(n):
  108. if n < 0:
  109. x = B(n)
  110. else:
  111. x = C(n)
  112. return type(x) is B, type(x) is C
  113. res = interpret(fn, [-212], taggedpointers=True)
  114. assert res.item0 and not res.item1
  115. res = interpret(fn, [9874], taggedpointers=True)
  116. assert res.item1 and not res.item0
  117. def test_type_of_None():
  118. # use extra function to prevent flow graph cleverness
  119. def g(n):
  120. if n < 0:
  121. x = B(n)
  122. elif n == 0:
  123. x = None
  124. else:
  125. x = C(n)
  126. return x
  127. def fn(n):
  128. x= g(n)
  129. return type(x) is B, type(x) is C
  130. res = interpret(fn, [-212], taggedpointers=True)
  131. assert res.item0 and not res.item1
  132. res = interpret(fn, [9874], taggedpointers=True)
  133. assert res.item1 and not res.item0
  134. res = interpret(fn, [0], taggedpointers=True)
  135. assert not res.item1 and not res.item0
  136. def test_str():
  137. def fn(n):
  138. if n > 0:
  139. x = B(n)
  140. else:
  141. x = C(n)
  142. return str(x)
  143. res = interpret(fn, [-832], taggedpointers=True)
  144. assert ''.join(res.chars) == '<unboxed -832>'
  145. res = interpret(fn, [1], taggedpointers=True)
  146. assert ''.join(res.chars).startswith('<B object')
  147. def test_format():
  148. def fn(n):
  149. if n > 0:
  150. x = B(n)
  151. else:
  152. x = C(n)
  153. return '%r' % (x,)
  154. res = interpret(fn, [-832], taggedpointers=True)
  155. assert ''.join(res.chars) == '<unboxed -832>'
  156. res = interpret(fn, [1], taggedpointers=True)
  157. assert ''.join(res.chars).startswith('<B object')
  158. def test_method():
  159. def fn(n):
  160. if n > 0:
  161. x = B(n)
  162. else:
  163. x = C(n)
  164. return x.meth(100)
  165. res = interpret(fn, [1000], taggedpointers=True)
  166. assert res == 1102
  167. res = interpret(fn, [-1000], taggedpointers=True)
  168. assert res == -897
  169. def test_optimize_method():
  170. def fn(n):
  171. if n > 0:
  172. x = B(n)
  173. else:
  174. x = C(n)
  175. return x.meth(100)
  176. interp, graph = get_interpreter(fn, [-1000], taggedpointers=True)
  177. t = interp.typer.annotator.translator
  178. t.config.translation.backendopt.constfold = True
  179. backend_optimizations(t)
  180. if conftest.option.view:
  181. t.view()
  182. LLFrame = interp.frame_class
  183. class MyFrame(LLFrame):
  184. def op_indirect_call(self, f, *args):
  185. raise AssertionError("this call should be optimized away")
  186. interp.frame_class = MyFrame
  187. res = interp.eval_graph(graph, [-1000])
  188. assert res == -897
  189. def test_untagged_subclasses():
  190. def g(x):
  191. return x.attrvalue # should not produce a call to ll_unboxed_getclass
  192. def fn(n):
  193. y = C(12)
  194. if n > 0:
  195. x = B(5)
  196. else:
  197. x = D(5)
  198. return g(x)
  199. interp, graph = get_interpreter(fn, [-1000], taggedpointers=True)
  200. t = interp.typer.annotator.translator
  201. ggraph = graphof(t, g)
  202. assert summary(ggraph) == {'cast_pointer': 2, 'getfield': 2}
  203. res = interp.eval_graph(graph, [-1000])
  204. assert res == 68
  205. res = interp.eval_graph(graph, [3])
  206. assert res == 66
  207. def test_disable_tagging():
  208. def fn(n):
  209. if n < 0:
  210. x = B(n)
  211. else:
  212. x = C(n)
  213. return type(x) is B, type(x) is C
  214. res = interpret(fn, [-212], taggedpointers=False)
  215. assert res.item0 and not res.item1
  216. res = interpret(fn, [9874], taggedpointers=False)
  217. assert res.item1 and not res.item0