PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/memory/gc/test/test_direct.py

https://bitbucket.org/pypy/pypy/
Python | 750 lines | 724 code | 6 blank | 20 comment | 9 complexity | dfedc07d4f14355657d3cddf4455765a MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """ The tests below don't use translation at all. They run the GCs by
  2. instantiating them and asking them to allocate memory by calling their
  3. methods directly. The tests need to maintain by hand what the GC should
  4. see as the list of roots (stack and prebuilt objects).
  5. """
  6. # XXX VERY INCOMPLETE, low coverage
  7. import py
  8. from rpython.rtyper.lltypesystem import lltype, llmemory
  9. from rpython.memory.gctypelayout import TypeLayoutBuilder, FIN_HANDLER_ARRAY
  10. from rpython.rlib.rarithmetic import LONG_BIT, is_valid_int
  11. from rpython.memory.gc import minimark, incminimark
  12. from rpython.memory.gctypelayout import zero_gc_pointers_inside, zero_gc_pointers
  13. from rpython.rlib.debug import debug_print
  14. import pdb
  15. WORD = LONG_BIT // 8
  16. ADDR_ARRAY = lltype.Array(llmemory.Address)
  17. S = lltype.GcForwardReference()
  18. S.become(lltype.GcStruct('S',
  19. ('x', lltype.Signed),
  20. ('prev', lltype.Ptr(S)),
  21. ('next', lltype.Ptr(S))))
  22. RAW = lltype.Struct('RAW', ('p', lltype.Ptr(S)), ('q', lltype.Ptr(S)))
  23. VAR = lltype.GcArray(lltype.Ptr(S))
  24. VARNODE = lltype.GcStruct('VARNODE', ('a', lltype.Ptr(VAR)))
  25. class DirectRootWalker(object):
  26. def __init__(self, tester):
  27. self.tester = tester
  28. def walk_roots(self, collect_stack_root,
  29. collect_static_in_prebuilt_nongc,
  30. collect_static_in_prebuilt_gc,
  31. is_minor=False):
  32. gc = self.tester.gc
  33. layoutbuilder = self.tester.layoutbuilder
  34. if collect_static_in_prebuilt_gc:
  35. for addrofaddr in layoutbuilder.addresses_of_static_ptrs:
  36. if addrofaddr.address[0]:
  37. collect_static_in_prebuilt_gc(gc, addrofaddr)
  38. if collect_static_in_prebuilt_nongc:
  39. for addrofaddr in layoutbuilder.addresses_of_static_ptrs_in_nongc:
  40. if addrofaddr.address[0]:
  41. collect_static_in_prebuilt_nongc(gc, addrofaddr)
  42. if collect_stack_root:
  43. stackroots = self.tester.stackroots
  44. a = lltype.malloc(ADDR_ARRAY, len(stackroots), flavor='raw')
  45. for i in range(len(a)):
  46. a[i] = llmemory.cast_ptr_to_adr(stackroots[i])
  47. a_base = lltype.direct_arrayitems(a)
  48. for i in range(len(a)):
  49. ai = lltype.direct_ptradd(a_base, i)
  50. collect_stack_root(gc, llmemory.cast_ptr_to_adr(ai))
  51. for i in range(len(a)):
  52. PTRTYPE = lltype.typeOf(stackroots[i])
  53. stackroots[i] = llmemory.cast_adr_to_ptr(a[i], PTRTYPE)
  54. lltype.free(a, flavor='raw')
  55. def _walk_prebuilt_gc(self, callback):
  56. pass
  57. def finished_minor_collection(self):
  58. pass
  59. class BaseDirectGCTest(object):
  60. GC_PARAMS = {}
  61. def setup_method(self, meth):
  62. from rpython.config.translationoption import get_combined_translation_config
  63. config = get_combined_translation_config(translating=True).translation
  64. self.stackroots = []
  65. GC_PARAMS = self.GC_PARAMS.copy()
  66. if hasattr(meth, 'GC_PARAMS'):
  67. GC_PARAMS.update(meth.GC_PARAMS)
  68. GC_PARAMS['translated_to_c'] = False
  69. self.gc = self.GCClass(config, **GC_PARAMS)
  70. self.gc.DEBUG = True
  71. self.rootwalker = DirectRootWalker(self)
  72. self.gc.set_root_walker(self.rootwalker)
  73. self.layoutbuilder = TypeLayoutBuilder(self.GCClass)
  74. self.get_type_id = self.layoutbuilder.get_type_id
  75. gcdata = self.layoutbuilder.initialize_gc_query_function(self.gc)
  76. ll_handlers = lltype.malloc(FIN_HANDLER_ARRAY, 0, immortal=True)
  77. gcdata.finalizer_handlers = llmemory.cast_ptr_to_adr(ll_handlers)
  78. self.gc.setup()
  79. def consider_constant(self, p):
  80. obj = p._obj
  81. TYPE = lltype.typeOf(obj)
  82. self.layoutbuilder.consider_constant(TYPE, obj, self.gc)
  83. def write(self, p, fieldname, newvalue):
  84. if self.gc.needs_write_barrier:
  85. addr_struct = llmemory.cast_ptr_to_adr(p)
  86. self.gc.write_barrier(addr_struct)
  87. setattr(p, fieldname, newvalue)
  88. def writearray(self, p, index, newvalue):
  89. if self.gc.needs_write_barrier:
  90. addr_struct = llmemory.cast_ptr_to_adr(p)
  91. if hasattr(self.gc, 'write_barrier_from_array'):
  92. self.gc.write_barrier_from_array(addr_struct, index)
  93. else:
  94. self.gc.write_barrier(addr_struct)
  95. p[index] = newvalue
  96. def malloc(self, TYPE, n=None):
  97. addr = self.gc.malloc(self.get_type_id(TYPE), n)
  98. debug_print(self.gc)
  99. obj_ptr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE))
  100. if not self.gc.malloc_zero_filled:
  101. zero_gc_pointers_inside(obj_ptr, TYPE)
  102. return obj_ptr
  103. class DirectGCTest(BaseDirectGCTest):
  104. def test_simple(self):
  105. p = self.malloc(S)
  106. p.x = 5
  107. self.stackroots.append(p)
  108. self.gc.collect()
  109. p = self.stackroots[0]
  110. assert p.x == 5
  111. def test_missing_stack_root(self):
  112. p = self.malloc(S)
  113. p.x = 5
  114. self.gc.collect() # 'p' should go away
  115. py.test.raises(RuntimeError, 'p.x')
  116. def test_prebuilt_gc(self):
  117. k = lltype.malloc(S, immortal=True)
  118. k.x = 42
  119. self.consider_constant(k)
  120. self.write(k, 'next', self.malloc(S))
  121. k.next.x = 43
  122. self.write(k.next, 'next', self.malloc(S))
  123. k.next.next.x = 44
  124. self.gc.collect()
  125. assert k.x == 42
  126. assert k.next.x == 43
  127. assert k.next.next.x == 44
  128. def test_prebuilt_nongc(self):
  129. raw = lltype.malloc(RAW, immortal=True)
  130. self.consider_constant(raw)
  131. raw.p = self.malloc(S)
  132. raw.p.x = 43
  133. raw.q = self.malloc(S)
  134. raw.q.x = 44
  135. self.gc.collect()
  136. assert raw.p.x == 43
  137. assert raw.q.x == 44
  138. def test_many_objects(self):
  139. def alloc2(i):
  140. a1 = self.malloc(S)
  141. a1.x = i
  142. self.stackroots.append(a1)
  143. a2 = self.malloc(S)
  144. a1 = self.stackroots.pop()
  145. a2.x = i + 1000
  146. return a1, a2
  147. def growloop(loop, a1, a2):
  148. self.write(a1, 'prev', loop.prev)
  149. self.write(a1.prev, 'next', a1)
  150. self.write(a1, 'next', loop)
  151. self.write(loop, 'prev', a1)
  152. self.write(a2, 'prev', loop)
  153. self.write(a2, 'next', loop.next)
  154. self.write(a2.next, 'prev', a2)
  155. self.write(loop, 'next', a2)
  156. def newloop():
  157. p = self.malloc(S)
  158. p.next = p # initializing stores, no write barrier
  159. p.prev = p
  160. return p
  161. # a loop attached to a stack root
  162. self.stackroots.append(newloop())
  163. # another loop attached to a prebuilt gc node
  164. k = lltype.malloc(S, immortal=True)
  165. k.next = k
  166. k.prev = k
  167. self.consider_constant(k)
  168. # a third loop attached to a prebuilt nongc
  169. raw = lltype.malloc(RAW, immortal=True)
  170. self.consider_constant(raw)
  171. raw.p = newloop()
  172. # run!
  173. for i in range(100):
  174. a1, a2 = alloc2(i)
  175. growloop(self.stackroots[0], a1, a2)
  176. a1, a2 = alloc2(i)
  177. growloop(k, a1, a2)
  178. a1, a2 = alloc2(i)
  179. growloop(raw.p, a1, a2)
  180. def test_varsized_from_stack(self):
  181. expected = {}
  182. def verify():
  183. for (index, index2), value in expected.items():
  184. assert self.stackroots[index][index2].x == value
  185. x = 0
  186. for i in range(40):
  187. assert 'DEAD' not in repr(self.stackroots)
  188. a = self.malloc(VAR, i)
  189. assert 'DEAD' not in repr(a)
  190. self.stackroots.append(a)
  191. print 'ADDED TO STACKROOTS:', llmemory.cast_adr_to_int(
  192. llmemory.cast_ptr_to_adr(a))
  193. assert 'DEAD' not in repr(self.stackroots)
  194. for j in range(5):
  195. assert 'DEAD' not in repr(self.stackroots)
  196. p = self.malloc(S)
  197. assert 'DEAD' not in repr(self.stackroots)
  198. p.x = x
  199. index = x % len(self.stackroots)
  200. if index > 0:
  201. index2 = (x / len(self.stackroots)) % index
  202. a = self.stackroots[index]
  203. assert len(a) == index
  204. self.writearray(a, index2, p)
  205. expected[index, index2] = x
  206. x += 1291
  207. verify()
  208. self.gc.collect()
  209. verify()
  210. self.gc.collect()
  211. verify()
  212. def test_varsized_from_prebuilt_gc(self):
  213. expected = {}
  214. def verify():
  215. for (index, index2), value in expected.items():
  216. assert prebuilt[index].a[index2].x == value
  217. x = 0
  218. prebuilt = [lltype.malloc(VARNODE, immortal=True, zero=True)
  219. for i in range(40)]
  220. for node in prebuilt:
  221. self.consider_constant(node)
  222. for i in range(len(prebuilt)):
  223. self.write(prebuilt[i], 'a', self.malloc(VAR, i))
  224. for j in range(20):
  225. p = self.malloc(S)
  226. p.x = x
  227. index = x % (i+1)
  228. if index > 0:
  229. index2 = (x / (i+1)) % index
  230. a = prebuilt[index].a
  231. assert len(a) == index
  232. self.writearray(a, index2, p)
  233. expected[index, index2] = x
  234. x += 1291
  235. verify()
  236. self.gc.collect()
  237. verify()
  238. self.gc.collect()
  239. verify()
  240. def test_id(self):
  241. ids = {}
  242. def allocate_bunch(count=50):
  243. base = len(self.stackroots)
  244. for i in range(count):
  245. p = self.malloc(S)
  246. self.stackroots.append(p)
  247. for i in range(count):
  248. j = base + (i*1291) % count
  249. pid = self.gc.id(self.stackroots[j])
  250. assert isinstance(pid, int)
  251. ids[j] = pid
  252. def verify():
  253. for j, expected in ids.items():
  254. assert self.gc.id(self.stackroots[j]) == expected
  255. allocate_bunch(5)
  256. verify()
  257. allocate_bunch(75)
  258. verify()
  259. allocate_bunch(5)
  260. verify()
  261. self.gc.collect()
  262. verify()
  263. self.gc.collect()
  264. verify()
  265. def test_identityhash(self):
  266. # a "does not crash" kind of test
  267. p_const = lltype.malloc(S, immortal=True)
  268. self.consider_constant(p_const)
  269. # (1) p is in the nursery
  270. self.gc.collect()
  271. p = self.malloc(S)
  272. hash = self.gc.identityhash(p)
  273. print hash
  274. assert is_valid_int(hash)
  275. assert hash == self.gc.identityhash(p)
  276. self.stackroots.append(p)
  277. for i in range(6):
  278. self.gc.collect()
  279. assert hash == self.gc.identityhash(self.stackroots[-1])
  280. self.stackroots.pop()
  281. # (2) p is an older object
  282. p = self.malloc(S)
  283. self.stackroots.append(p)
  284. self.gc.collect()
  285. hash = self.gc.identityhash(self.stackroots[-1])
  286. print hash
  287. assert is_valid_int(hash)
  288. for i in range(6):
  289. self.gc.collect()
  290. assert hash == self.gc.identityhash(self.stackroots[-1])
  291. self.stackroots.pop()
  292. # (3) p is a gen3 object (for hybrid)
  293. p = self.malloc(S)
  294. self.stackroots.append(p)
  295. for i in range(6):
  296. self.gc.collect()
  297. hash = self.gc.identityhash(self.stackroots[-1])
  298. print hash
  299. assert is_valid_int(hash)
  300. for i in range(2):
  301. self.gc.collect()
  302. assert hash == self.gc.identityhash(self.stackroots[-1])
  303. self.stackroots.pop()
  304. # (4) p is a prebuilt object
  305. hash = self.gc.identityhash(p_const)
  306. print hash
  307. assert is_valid_int(hash)
  308. assert hash == self.gc.identityhash(p_const)
  309. # (5) p is actually moving (for the markcompact gc only?)
  310. p0 = self.malloc(S)
  311. self.stackroots.append(p0)
  312. p = self.malloc(S)
  313. self.stackroots.append(p)
  314. hash = self.gc.identityhash(p)
  315. self.stackroots.pop(-2)
  316. self.gc.collect() # p0 goes away, p shifts left
  317. assert hash == self.gc.identityhash(self.stackroots[-1])
  318. self.gc.collect()
  319. assert hash == self.gc.identityhash(self.stackroots[-1])
  320. self.stackroots.pop()
  321. # (6) ask for the hash of varsized objects, larger and larger
  322. for i in range(10):
  323. self.gc.collect()
  324. p = self.malloc(VAR, i)
  325. self.stackroots.append(p)
  326. hash = self.gc.identityhash(p)
  327. self.gc.collect()
  328. assert hash == self.gc.identityhash(self.stackroots[-1])
  329. self.stackroots.pop()
  330. # (7) the same, but the objects are dying young
  331. for i in range(10):
  332. self.gc.collect()
  333. p = self.malloc(VAR, i)
  334. self.stackroots.append(p)
  335. hash1 = self.gc.identityhash(p)
  336. hash2 = self.gc.identityhash(p)
  337. assert hash1 == hash2
  338. self.stackroots.pop()
  339. def test_memory_alignment(self):
  340. A1 = lltype.GcArray(lltype.Char)
  341. for i in range(50):
  342. p1 = self.malloc(A1, i)
  343. if i:
  344. p1[i-1] = chr(i)
  345. self.stackroots.append(p1)
  346. self.gc.collect()
  347. for i in range(1, 50):
  348. p = self.stackroots[-50+i]
  349. assert p[i-1] == chr(i)
  350. class TestSemiSpaceGC(DirectGCTest):
  351. from rpython.memory.gc.semispace import SemiSpaceGC as GCClass
  352. def test_shrink_array(self):
  353. S1 = lltype.GcStruct('S1', ('h', lltype.Char),
  354. ('v', lltype.Array(lltype.Char)))
  355. p1 = self.malloc(S1, 2)
  356. p1.h = '?'
  357. for i in range(2):
  358. p1.v[i] = chr(50 + i)
  359. addr = llmemory.cast_ptr_to_adr(p1)
  360. ok = self.gc.shrink_array(addr, 1)
  361. assert ok
  362. assert p1.h == '?'
  363. assert len(p1.v) == 1
  364. for i in range(1):
  365. assert p1.v[i] == chr(50 + i)
  366. class TestGenerationGC(TestSemiSpaceGC):
  367. from rpython.memory.gc.generation import GenerationGC as GCClass
  368. def test_collect_gen(self):
  369. gc = self.gc
  370. old_semispace_collect = gc.semispace_collect
  371. old_collect_nursery = gc.collect_nursery
  372. calls = []
  373. def semispace_collect():
  374. calls.append('semispace_collect')
  375. return old_semispace_collect()
  376. def collect_nursery():
  377. calls.append('collect_nursery')
  378. return old_collect_nursery()
  379. gc.collect_nursery = collect_nursery
  380. gc.semispace_collect = semispace_collect
  381. gc.collect()
  382. assert calls == ['semispace_collect']
  383. calls = []
  384. gc.collect(0)
  385. assert calls == ['collect_nursery']
  386. calls = []
  387. gc.collect(1)
  388. assert calls == ['semispace_collect']
  389. calls = []
  390. gc.collect(9)
  391. assert calls == ['semispace_collect']
  392. calls = []
  393. def test_write_barrier_direct(self):
  394. s0 = lltype.malloc(S, immortal=True)
  395. self.consider_constant(s0)
  396. s = self.malloc(S)
  397. s.x = 1
  398. s0.next = s
  399. self.gc.write_barrier(llmemory.cast_ptr_to_adr(s0))
  400. self.gc.collect(0)
  401. assert s0.next.x == 1
  402. class TestHybridGC(TestGenerationGC):
  403. from rpython.memory.gc.hybrid import HybridGC as GCClass
  404. GC_PARAMS = {'space_size': 48*WORD,
  405. 'min_nursery_size': 12*WORD,
  406. 'nursery_size': 12*WORD,
  407. 'large_object': 3*WORD,
  408. 'large_object_gcptrs': 3*WORD,
  409. 'generation3_collect_threshold': 5,
  410. }
  411. def test_collect_gen(self):
  412. gc = self.gc
  413. old_semispace_collect = gc.semispace_collect
  414. old_collect_nursery = gc.collect_nursery
  415. calls = []
  416. def semispace_collect():
  417. gen3 = gc.is_collecting_gen3()
  418. calls.append(('semispace_collect', gen3))
  419. return old_semispace_collect()
  420. def collect_nursery():
  421. calls.append('collect_nursery')
  422. return old_collect_nursery()
  423. gc.collect_nursery = collect_nursery
  424. gc.semispace_collect = semispace_collect
  425. gc.collect()
  426. assert calls == [('semispace_collect', True)]
  427. calls = []
  428. gc.collect(0)
  429. assert calls == ['collect_nursery']
  430. calls = []
  431. gc.collect(1)
  432. assert calls == [('semispace_collect', False)]
  433. calls = []
  434. gc.collect(2)
  435. assert calls == [('semispace_collect', True)]
  436. calls = []
  437. gc.collect(9)
  438. assert calls == [('semispace_collect', True)]
  439. calls = []
  440. def test_identityhash(self):
  441. py.test.skip("does not support raw_mallocs(sizeof(S)+sizeof(hash))")
  442. class TestMiniMarkGCSimple(DirectGCTest):
  443. from rpython.memory.gc.minimark import MiniMarkGC as GCClass
  444. from rpython.memory.gc.minimarktest import SimpleArenaCollection
  445. # test the GC itself, providing a simple class for ArenaCollection
  446. GC_PARAMS = {'ArenaCollectionClass': SimpleArenaCollection}
  447. def test_card_marker(self):
  448. for arraylength in (range(4, 17)
  449. + [69] # 3 bytes
  450. + [300]): # 10 bytes
  451. print 'array length:', arraylength
  452. nums = {}
  453. a = self.malloc(VAR, arraylength)
  454. self.stackroots.append(a)
  455. for i in range(50):
  456. p = self.malloc(S)
  457. p.x = -i
  458. a = self.stackroots[-1]
  459. index = (i*i) % arraylength
  460. self.writearray(a, index, p)
  461. nums[index] = p.x
  462. #
  463. for index, expected_x in nums.items():
  464. assert a[index].x == expected_x
  465. self.stackroots.pop()
  466. test_card_marker.GC_PARAMS = {"card_page_indices": 4}
  467. def test_writebarrier_before_copy(self):
  468. largeobj_size = self.gc.nonlarge_max + 1
  469. self.gc.next_major_collection_threshold = 99999.0
  470. p_src = self.malloc(VAR, largeobj_size)
  471. p_dst = self.malloc(VAR, largeobj_size)
  472. # make them old
  473. self.stackroots.append(p_src)
  474. self.stackroots.append(p_dst)
  475. self.gc.collect()
  476. p_dst = self.stackroots.pop()
  477. p_src = self.stackroots.pop()
  478. #
  479. addr_src = llmemory.cast_ptr_to_adr(p_src)
  480. addr_dst = llmemory.cast_ptr_to_adr(p_dst)
  481. hdr_src = self.gc.header(addr_src)
  482. hdr_dst = self.gc.header(addr_dst)
  483. #
  484. assert hdr_src.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS
  485. assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS
  486. #
  487. res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10)
  488. assert res
  489. assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS
  490. #
  491. hdr_src.tid &= ~minimark.GCFLAG_TRACK_YOUNG_PTRS # pretend we have young ptrs
  492. res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10)
  493. assert res # we optimized it
  494. assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS == 0 # and we copied the flag
  495. #
  496. self.gc.card_page_indices = 128 # force > 0
  497. hdr_src.tid |= minimark.GCFLAG_TRACK_YOUNG_PTRS
  498. hdr_dst.tid |= minimark.GCFLAG_TRACK_YOUNG_PTRS
  499. hdr_src.tid |= minimark.GCFLAG_HAS_CARDS
  500. hdr_src.tid |= minimark.GCFLAG_CARDS_SET
  501. # hdr_dst.tid does not have minimark.GCFLAG_HAS_CARDS
  502. res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10)
  503. assert not res # there might be young ptrs, let ll_arraycopy to find them
  504. def test_writebarrier_before_copy_preserving_cards(self):
  505. from rpython.rtyper.lltypesystem import llarena
  506. tid = self.get_type_id(VAR)
  507. largeobj_size = self.gc.nonlarge_max + 1
  508. self.gc.next_major_collection_threshold = 99999.0
  509. addr_src = self.gc.external_malloc(tid, largeobj_size, alloc_young=True)
  510. addr_dst = self.gc.external_malloc(tid, largeobj_size, alloc_young=True)
  511. hdr_src = self.gc.header(addr_src)
  512. hdr_dst = self.gc.header(addr_dst)
  513. #
  514. assert hdr_src.tid & minimark.GCFLAG_HAS_CARDS
  515. assert hdr_dst.tid & minimark.GCFLAG_HAS_CARDS
  516. #
  517. self.gc.write_barrier_from_array(addr_src, 0)
  518. index_in_third_page = int(2.5 * self.gc.card_page_indices)
  519. assert index_in_third_page < largeobj_size
  520. self.gc.write_barrier_from_array(addr_src, index_in_third_page)
  521. #
  522. assert hdr_src.tid & minimark.GCFLAG_CARDS_SET
  523. addr_byte = self.gc.get_card(addr_src, 0)
  524. assert ord(addr_byte.char[0]) == 0x01 | 0x04 # bits 0 and 2
  525. #
  526. res = self.gc.writebarrier_before_copy(addr_src, addr_dst,
  527. 0, 0, 2*self.gc.card_page_indices)
  528. assert res
  529. #
  530. assert hdr_dst.tid & minimark.GCFLAG_CARDS_SET
  531. addr_byte = self.gc.get_card(addr_dst, 0)
  532. assert ord(addr_byte.char[0]) == 0x01 | 0x04 # bits 0 and 2
  533. test_writebarrier_before_copy_preserving_cards.GC_PARAMS = {
  534. "card_page_indices": 4}
  535. class TestMiniMarkGCFull(DirectGCTest):
  536. from rpython.memory.gc.minimark import MiniMarkGC as GCClass
  537. class TestIncrementalMiniMarkGCSimple(TestMiniMarkGCSimple):
  538. from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
  539. def test_write_barrier_marking_simple(self):
  540. for i in range(2):
  541. curobj = self.malloc(S)
  542. curobj.x = i
  543. self.stackroots.append(curobj)
  544. oldobj = self.stackroots[-1]
  545. oldhdr = self.gc.header(llmemory.cast_ptr_to_adr(oldobj))
  546. assert oldhdr.tid & incminimark.GCFLAG_VISITED == 0
  547. self.gc.debug_gc_step_until(incminimark.STATE_MARKING)
  548. oldobj = self.stackroots[-1]
  549. # object shifted by minor collect
  550. oldhdr = self.gc.header(llmemory.cast_ptr_to_adr(oldobj))
  551. assert oldhdr.tid & incminimark.GCFLAG_VISITED == 0
  552. self.gc._minor_collection()
  553. self.gc.visit_all_objects_step(1)
  554. assert oldhdr.tid & incminimark.GCFLAG_VISITED
  555. #at this point the first object should have been processed
  556. newobj = self.malloc(S)
  557. self.write(oldobj,'next',newobj)
  558. assert self.gc.header(self.gc.old_objects_pointing_to_young.tolist()[0]) == oldhdr
  559. self.gc._minor_collection()
  560. self.gc.debug_check_consistency()
  561. def test_sweeping_simple(self):
  562. assert self.gc.gc_state == incminimark.STATE_SCANNING
  563. for i in range(2):
  564. curobj = self.malloc(S)
  565. curobj.x = i
  566. self.stackroots.append(curobj)
  567. self.gc.debug_gc_step_until(incminimark.STATE_SWEEPING)
  568. oldobj = self.stackroots[-1]
  569. oldhdr = self.gc.header(llmemory.cast_ptr_to_adr(oldobj))
  570. assert oldhdr.tid & incminimark.GCFLAG_VISITED
  571. newobj1 = self.malloc(S)
  572. newobj2 = self.malloc(S)
  573. newobj1.x = 1337
  574. newobj2.x = 1338
  575. self.write(oldobj,'next',newobj1)
  576. self.gc.debug_gc_step_until(incminimark.STATE_SCANNING)
  577. #should not be cleared even though it was allocated while sweeping
  578. newobj1 = oldobj.next
  579. assert newobj1.x == 1337
  580. def test_obj_on_escapes_on_stack(self):
  581. obj0 = self.malloc(S)
  582. self.stackroots.append(obj0)
  583. obj0.next = self.malloc(S)
  584. self.gc.debug_gc_step_until(incminimark.STATE_MARKING)
  585. obj0 = self.stackroots[-1]
  586. obj1 = obj0.next
  587. obj1.x = 13
  588. obj0.next = lltype.nullptr(S)
  589. self.stackroots.append(obj1)
  590. self.gc.debug_gc_step_until(incminimark.STATE_SCANNING)
  591. assert self.stackroots[1].x == 13
  592. class TestIncrementalMiniMarkGCFull(DirectGCTest):
  593. from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
  594. def test_malloc_fixedsize_no_cleanup(self):
  595. p = self.malloc(S)
  596. import pytest
  597. #ensure the memory is uninitialized
  598. with pytest.raises(lltype.UninitializedMemoryAccess):
  599. x1 = p.x
  600. #ensure all the ptr fields are zeroed
  601. assert p.prev == lltype.nullptr(S)
  602. assert p.next == lltype.nullptr(S)
  603. def test_malloc_varsize_no_cleanup(self):
  604. x = lltype.Signed
  605. VAR1 = lltype.GcArray(x)
  606. p = self.malloc(VAR1,5)
  607. import pytest
  608. with pytest.raises(lltype.UninitializedMemoryAccess):
  609. assert isinstance(p[0], lltype._uninitialized)
  610. x1 = p[0]
  611. def test_malloc_varsize_no_cleanup2(self):
  612. #as VAR is GcArray so the ptr will don't need to be zeroed
  613. p = self.malloc(VAR, 100)
  614. for i in range(100):
  615. assert p[i] == lltype.nullptr(S)
  616. def test_malloc_varsize_no_cleanup3(self):
  617. VAR1 = lltype.Array(lltype.Ptr(S))
  618. p1 = lltype.malloc(VAR1, 10, flavor='raw', track_allocation=False)
  619. import pytest
  620. with pytest.raises(lltype.UninitializedMemoryAccess):
  621. for i in range(10):
  622. assert p1[i] == lltype.nullptr(S)
  623. p1[i]._free()
  624. p1._free()
  625. def test_malloc_struct_of_ptr_struct(self):
  626. S3 = lltype.GcForwardReference()
  627. S3.become(lltype.GcStruct('S3',
  628. ('gcptr_struct', S),
  629. ('prev', lltype.Ptr(S)),
  630. ('next', lltype.Ptr(S))))
  631. s3 = self.malloc(S3)
  632. assert s3.gcptr_struct.prev == lltype.nullptr(S)
  633. assert s3.gcptr_struct.next == lltype.nullptr(S)
  634. def test_malloc_array_of_ptr_struct(self):
  635. ARR_OF_PTR_STRUCT = lltype.GcArray(lltype.Ptr(S))
  636. arr_of_ptr_struct = self.malloc(ARR_OF_PTR_STRUCT,5)
  637. for i in range(5):
  638. assert arr_of_ptr_struct[i] == lltype.nullptr(S)
  639. assert arr_of_ptr_struct[i] == lltype.nullptr(S)
  640. arr_of_ptr_struct[i] = self.malloc(S)
  641. assert arr_of_ptr_struct[i].prev == lltype.nullptr(S)
  642. assert arr_of_ptr_struct[i].next == lltype.nullptr(S)
  643. #fail for now
  644. def xxx_test_malloc_array_of_ptr_arr(self):
  645. ARR_OF_PTR_ARR = lltype.GcArray(lltype.Ptr(lltype.GcArray(lltype.Ptr(S))))
  646. arr_of_ptr_arr = self.malloc(ARR_OF_PTR_ARR, 10)
  647. self.stackroots.append(arr_of_ptr_arr)
  648. for i in range(10):
  649. assert arr_of_ptr_arr[i] == lltype.nullptr(lltype.GcArray(lltype.Ptr(S)))
  650. for i in range(10):
  651. self.writearray(arr_of_ptr_arr, i,
  652. self.malloc(lltype.GcArray(lltype.Ptr(S)), i))
  653. #self.stackroots.append(arr_of_ptr_arr[i])
  654. #debug_print(arr_of_ptr_arr[i])
  655. for elem in arr_of_ptr_arr[i]:
  656. #self.stackroots.append(elem)
  657. assert elem == lltype.nullptr(S)
  658. elem = self.malloc(S)
  659. assert elem.prev == lltype.nullptr(S)
  660. assert elem.next == lltype.nullptr(S)