PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/rpython/lltypesystem/test/test_llarena.py

https://bitbucket.org/pwaller/pypy
Python | 333 lines | 282 code | 33 blank | 18 comment | 22 complexity | 0ec3214450512c5be66e525e9f7f60fc MD5 | raw file
  1. import py
  2. from pypy.rpython.lltypesystem import lltype, llmemory
  3. from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr
  4. from pypy.rpython.lltypesystem.llarena import arena_malloc, arena_reset
  5. from pypy.rpython.lltypesystem.llarena import arena_reserve, arena_free
  6. from pypy.rpython.lltypesystem.llarena import round_up_for_allocation
  7. from pypy.rpython.lltypesystem.llarena import ArenaError, arena_new_view
  8. from pypy.rpython.lltypesystem.llarena import arena_shrink_obj
  9. from pypy.rpython.lltypesystem.llarena import arena_protect, has_protect
  10. from pypy.translator.c.test import test_genc, test_standalone
  11. def test_arena():
  12. S = lltype.Struct('S', ('x',lltype.Signed))
  13. SPTR = lltype.Ptr(S)
  14. ssize = llmemory.raw_malloc_usage(llmemory.sizeof(S))
  15. myarenasize = 2*ssize+1
  16. a = arena_malloc(myarenasize, False)
  17. assert a != llmemory.NULL
  18. assert a + 3 != llmemory.NULL
  19. arena_reserve(a, llmemory.sizeof(S))
  20. s1_ptr1 = cast_adr_to_ptr(a, SPTR)
  21. s1_ptr1.x = 1
  22. s1_ptr2 = cast_adr_to_ptr(a, SPTR)
  23. assert s1_ptr2.x == 1
  24. assert s1_ptr1 == s1_ptr2
  25. py.test.raises(ArenaError, arena_reserve, a + ssize + 1, # misaligned
  26. llmemory.sizeof(S))
  27. arena_reserve(a + ssize + 1, llmemory.sizeof(S), check_alignment=False)
  28. s2_ptr1 = cast_adr_to_ptr(a + ssize + 1, SPTR)
  29. py.test.raises(lltype.UninitializedMemoryAccess, 's2_ptr1.x')
  30. s2_ptr1.x = 2
  31. s2_ptr2 = cast_adr_to_ptr(a + ssize + 1, SPTR)
  32. assert s2_ptr2.x == 2
  33. assert s2_ptr1 == s2_ptr2
  34. assert s1_ptr1 != s2_ptr1
  35. assert not (s2_ptr2 == s1_ptr2)
  36. assert s1_ptr1 == cast_adr_to_ptr(a, SPTR)
  37. S2 = lltype.Struct('S2', ('y',lltype.Char))
  38. S2PTR = lltype.Ptr(S2)
  39. py.test.raises(lltype.InvalidCast, cast_adr_to_ptr, a, S2PTR)
  40. py.test.raises(ArenaError, cast_adr_to_ptr, a+1, SPTR)
  41. py.test.raises(ArenaError, cast_adr_to_ptr, a+ssize, SPTR)
  42. py.test.raises(ArenaError, cast_adr_to_ptr, a+2*ssize, SPTR)
  43. py.test.raises(ArenaError, cast_adr_to_ptr, a+2*ssize+1, SPTR)
  44. py.test.raises(ArenaError, arena_reserve, a+1, llmemory.sizeof(S),
  45. False)
  46. py.test.raises(ArenaError, arena_reserve, a+ssize, llmemory.sizeof(S),
  47. False)
  48. py.test.raises(ArenaError, arena_reserve, a+2*ssize, llmemory.sizeof(S),
  49. False)
  50. py.test.raises(ArenaError, arena_reserve, a+2*ssize+1, llmemory.sizeof(S),
  51. False)
  52. arena_reset(a, myarenasize, True)
  53. py.test.raises(ArenaError, cast_adr_to_ptr, a, SPTR)
  54. arena_reserve(a, llmemory.sizeof(S))
  55. s1_ptr1 = cast_adr_to_ptr(a, SPTR)
  56. assert s1_ptr1.x == 0
  57. s1_ptr1.x = 5
  58. arena_reserve(a + ssize, llmemory.sizeof(S2), check_alignment=False)
  59. s2_ptr1 = cast_adr_to_ptr(a + ssize, S2PTR)
  60. assert s2_ptr1.y == '\x00'
  61. s2_ptr1.y = 'X'
  62. assert cast_adr_to_ptr(a + 0, SPTR).x == 5
  63. assert cast_adr_to_ptr((a + ssize + 1) - 1, S2PTR).y == 'X'
  64. assert (a + 4) - (a + 1) == 3
  65. def lt(x, y):
  66. if x < y:
  67. assert (x < y) and (y > x)
  68. assert (x <= y) and (y >= x)
  69. assert not (x == y) and not (y == x)
  70. assert (x != y) and (y != x)
  71. assert not (x > y) and not (y < x)
  72. assert not (x >= y) and not (y <= x)
  73. return True
  74. else:
  75. assert (x >= y) and (y <= x)
  76. assert (x == y) == (not (x != y)) == (y == x) == (not (y != x))
  77. assert (x > y) == (not (x == y)) == (y < x)
  78. return False
  79. def eq(x, y):
  80. if x == y:
  81. assert not (x != y) and not (y != x)
  82. assert not (x < y) and not (y > x)
  83. assert not (x > y) and not (y < x)
  84. assert (x <= y) and (y >= x)
  85. assert (x >= y) and (y <= x)
  86. return True
  87. else:
  88. assert (x != y) and (y != x)
  89. assert ((x < y) == (x <= y) == (not (x > y)) == (not (x >= y)) ==
  90. (y > x) == (y >= x) == (not (y < x)) == (not (y <= x)))
  91. return False
  92. def test_address_order():
  93. a = arena_malloc(24, False)
  94. assert eq(a, a)
  95. assert lt(a, a+1)
  96. assert lt(a+5, a+20)
  97. b = arena_malloc(24, False)
  98. if a > b:
  99. a, b = b, a
  100. assert lt(a, b)
  101. assert lt(a+19, b)
  102. assert lt(a, b+19)
  103. c = b + round_up_for_allocation(llmemory.sizeof(lltype.Char))
  104. arena_reserve(c, precomputed_size)
  105. assert lt(b, c)
  106. assert lt(a, c)
  107. assert lt(llmemory.NULL, c)
  108. d = c + llmemory.offsetof(SX, 'x')
  109. assert lt(c, d)
  110. assert lt(b, d)
  111. assert lt(a, d)
  112. assert lt(llmemory.NULL, d)
  113. e = c + precomputed_size
  114. assert lt(d, e)
  115. assert lt(c, e)
  116. assert lt(b, e)
  117. assert lt(a, e)
  118. assert lt(llmemory.NULL, e)
  119. SX = lltype.Struct('S', ('foo',lltype.Signed), ('x',lltype.Signed))
  120. SPTR = lltype.Ptr(SX)
  121. precomputed_size = round_up_for_allocation(llmemory.sizeof(SX))
  122. def test_look_inside_object():
  123. # this code is also used in translation tests below
  124. myarenasize = 50
  125. a = arena_malloc(myarenasize, False)
  126. b = a + round_up_for_allocation(llmemory.sizeof(lltype.Char))
  127. arena_reserve(b, precomputed_size)
  128. (b + llmemory.offsetof(SX, 'x')).signed[0] = 123
  129. assert llmemory.cast_adr_to_ptr(b, SPTR).x == 123
  130. llmemory.cast_adr_to_ptr(b, SPTR).x += 1
  131. assert (b + llmemory.offsetof(SX, 'x')).signed[0] == 124
  132. arena_reset(a, myarenasize, True)
  133. arena_reserve(b, round_up_for_allocation(llmemory.sizeof(SX)))
  134. assert llmemory.cast_adr_to_ptr(b, SPTR).x == 0
  135. arena_free(a)
  136. return 42
  137. def test_arena_new_view():
  138. a = arena_malloc(50, False)
  139. arena_reserve(a, precomputed_size)
  140. # we can now allocate the same space in new view
  141. b = arena_new_view(a)
  142. arena_reserve(b, precomputed_size)
  143. def test_partial_arena_reset():
  144. a = arena_malloc(72, False)
  145. def reserve(i):
  146. b = a + i * llmemory.raw_malloc_usage(precomputed_size)
  147. arena_reserve(b, precomputed_size)
  148. return b
  149. blist = []
  150. plist = []
  151. for i in range(4):
  152. b = reserve(i)
  153. (b + llmemory.offsetof(SX, 'x')).signed[0] = 100 + i
  154. blist.append(b)
  155. plist.append(llmemory.cast_adr_to_ptr(b, SPTR))
  156. # clear blist[1] and blist[2] but not blist[0] nor blist[3]
  157. arena_reset(blist[1], llmemory.raw_malloc_usage(precomputed_size)*2, False)
  158. py.test.raises(RuntimeError, "plist[1].x") # marked as freed
  159. py.test.raises(RuntimeError, "plist[2].x") # marked as freed
  160. # re-reserve object at index 1 and 2
  161. blist[1] = reserve(1)
  162. blist[2] = reserve(2)
  163. # check via object pointers
  164. assert plist[0].x == 100
  165. assert plist[3].x == 103
  166. py.test.raises(RuntimeError, "plist[1].x") # marked as freed
  167. py.test.raises(RuntimeError, "plist[2].x") # marked as freed
  168. # but we can still cast the old ptrs to addresses, which compare equal
  169. # to the new ones we gotq
  170. assert llmemory.cast_ptr_to_adr(plist[1]) == blist[1]
  171. assert llmemory.cast_ptr_to_adr(plist[2]) == blist[2]
  172. # check via addresses
  173. assert (blist[0] + llmemory.offsetof(SX, 'x')).signed[0] == 100
  174. assert (blist[3] + llmemory.offsetof(SX, 'x')).signed[0] == 103
  175. py.test.raises(lltype.UninitializedMemoryAccess,
  176. "(blist[1] + llmemory.offsetof(SX, 'x')).signed[0]")
  177. py.test.raises(lltype.UninitializedMemoryAccess,
  178. "(blist[2] + llmemory.offsetof(SX, 'x')).signed[0]")
  179. # clear and zero-fill the area over blist[0] and blist[1]
  180. arena_reset(blist[0], llmemory.raw_malloc_usage(precomputed_size)*2, True)
  181. # re-reserve and check it's zero
  182. blist[0] = reserve(0)
  183. blist[1] = reserve(1)
  184. assert (blist[0] + llmemory.offsetof(SX, 'x')).signed[0] == 0
  185. assert (blist[1] + llmemory.offsetof(SX, 'x')).signed[0] == 0
  186. assert (blist[3] + llmemory.offsetof(SX, 'x')).signed[0] == 103
  187. py.test.raises(lltype.UninitializedMemoryAccess,
  188. "(blist[2] + llmemory.offsetof(SX, 'x')).signed[0]")
  189. def test_address_eq_as_int():
  190. a = arena_malloc(50, False)
  191. arena_reserve(a, precomputed_size)
  192. p = llmemory.cast_adr_to_ptr(a, SPTR)
  193. a1 = llmemory.cast_ptr_to_adr(p)
  194. assert a == a1
  195. assert not (a != a1)
  196. assert (a+1) != a1
  197. assert not ((a+1) == a1)
  198. py.test.skip("cast_adr_to_int() is hard to get consistent")
  199. assert llmemory.cast_adr_to_int(a) == llmemory.cast_adr_to_int(a1)
  200. assert llmemory.cast_adr_to_int(a+1) == llmemory.cast_adr_to_int(a1) + 1
  201. def test_replace_object_with_stub():
  202. from pypy.rpython.memory.gcheader import GCHeaderBuilder
  203. HDR = lltype.Struct('HDR', ('x', lltype.Signed))
  204. S = lltype.GcStruct('S', ('y', lltype.Signed), ('z', lltype.Signed))
  205. STUB = lltype.GcStruct('STUB', ('t', lltype.Char))
  206. gcheaderbuilder = GCHeaderBuilder(HDR)
  207. size_gc_header = gcheaderbuilder.size_gc_header
  208. ssize = llmemory.raw_malloc_usage(llmemory.sizeof(S))
  209. a = arena_malloc(13*ssize, True)
  210. hdraddr = a + 3*ssize
  211. arena_reserve(hdraddr, size_gc_header + llmemory.sizeof(S))
  212. hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
  213. hdr.x = 42
  214. obj = llmemory.cast_adr_to_ptr(hdraddr + size_gc_header, lltype.Ptr(S))
  215. obj.y = -5
  216. obj.z = -6
  217. hdraddr = llmemory.cast_ptr_to_adr(obj) - size_gc_header
  218. arena_reset(hdraddr, size_gc_header + llmemory.sizeof(S), False)
  219. arena_reserve(hdraddr, size_gc_header + llmemory.sizeof(STUB))
  220. # check that it possible to reach the newly reserved HDR+STUB
  221. # via the header of the old 'obj' pointer, both via the existing
  222. # 'hdraddr':
  223. hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
  224. hdr.x = 46
  225. stub = llmemory.cast_adr_to_ptr(hdraddr + size_gc_header, lltype.Ptr(STUB))
  226. stub.t = '!'
  227. # and via a (now-invalid) pointer to the old 'obj': (this is needed
  228. # because during a garbage collection there are still pointers to
  229. # the old 'obj' around to be fixed)
  230. hdraddr = llmemory.cast_ptr_to_adr(obj) - size_gc_header
  231. hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
  232. assert hdr.x == 46
  233. stub = llmemory.cast_adr_to_ptr(hdraddr + size_gc_header,
  234. lltype.Ptr(STUB))
  235. assert stub.t == '!'
  236. def test_llinterpreted():
  237. from pypy.rpython.test.test_llinterp import interpret
  238. res = interpret(test_look_inside_object, [])
  239. assert res == 42
  240. def test_compiled():
  241. fn = test_genc.compile(test_look_inside_object, [])
  242. res = fn()
  243. assert res == 42
  244. def test_shrink_obj():
  245. from pypy.rpython.memory.gcheader import GCHeaderBuilder
  246. HDR = lltype.Struct('HDR', ('h', lltype.Signed))
  247. gcheaderbuilder = GCHeaderBuilder(HDR)
  248. size_gc_header = gcheaderbuilder.size_gc_header
  249. S = lltype.GcStruct('S', ('x', lltype.Signed),
  250. ('a', lltype.Array(lltype.Signed)))
  251. myarenasize = 200
  252. a = arena_malloc(myarenasize, False)
  253. arena_reserve(a, size_gc_header + llmemory.sizeof(S, 10))
  254. arena_shrink_obj(a, size_gc_header + llmemory.sizeof(S, 5))
  255. arena_reset(a, size_gc_header + llmemory.sizeof(S, 5), False)
  256. def test_arena_protect():
  257. a = arena_malloc(100, False)
  258. S = lltype.Struct('S', ('x', lltype.Signed))
  259. arena_reserve(a, llmemory.sizeof(S))
  260. p = llmemory.cast_adr_to_ptr(a, lltype.Ptr(S))
  261. p.x = 123
  262. assert p.x == 123
  263. arena_protect(a, 100, True)
  264. py.test.raises(ArenaError, arena_reserve, a + 48, llmemory.sizeof(S))
  265. py.test.raises(RuntimeError, "p.x")
  266. py.test.raises(RuntimeError, "p.x = 124")
  267. arena_protect(a, 100, False)
  268. assert p.x == 123
  269. p.x = 125
  270. assert p.x == 125
  271. class TestStandalone(test_standalone.StandaloneTests):
  272. def test_compiled_arena_protect(self):
  273. import os
  274. from pypy.translator.c.test.test_genc import compile
  275. S = lltype.Struct('S', ('x', lltype.Signed))
  276. #
  277. def fn(argv):
  278. testrun = int(argv[1])
  279. a = arena_malloc(65536, False)
  280. arena_reserve(a, llmemory.sizeof(S))
  281. p = llmemory.cast_adr_to_ptr(a + 23432, lltype.Ptr(S))
  282. p.x = 123
  283. assert p.x == 123
  284. arena_protect(a, 65536, True)
  285. result = 0
  286. if testrun == 1:
  287. print p.x # segfault
  288. if testrun == 2:
  289. p.x = 124 # segfault
  290. arena_protect(a, 65536, False)
  291. p.x += 10
  292. print p.x
  293. return 0
  294. #
  295. t, cbuilder = self.compile(fn)
  296. data = cbuilder.cmdexec('0')
  297. assert data == '133\n'
  298. if has_protect:
  299. cbuilder.cmdexec('1', expect_crash=True)
  300. cbuilder.cmdexec('2', expect_crash=True)