PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

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