PageRenderTime 172ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/rpython/memory/gc/minimark.py

http://github.com/pypy/pypy
Python | 2072 lines | 1625 code | 88 blank | 359 comment | 96 complexity | 5cfdd62428b6a136ac7c0b6b1c3f6d39 MD5 | raw file
  1. """ MiniMark GC.
  2. Environment variables can be used to fine-tune the following parameters:
  3. PYPY_GC_NURSERY The nursery size. Defaults to '4MB'. Small values
  4. (like 1 or 1KB) are useful for debugging.
  5. PYPY_GC_MAJOR_COLLECT Major collection memory factor. Default is '1.82',
  6. which means trigger a major collection when the
  7. memory consumed equals 1.82 times the memory
  8. really used at the end of the previous major
  9. collection.
  10. PYPY_GC_GROWTH Major collection threshold's max growth rate.
  11. Default is '1.4'. Useful to collect more often
  12. than normally on sudden memory growth, e.g. when
  13. there is a temporary peak in memory usage.
  14. PYPY_GC_MAX The max heap size. If coming near this limit, it
  15. will first collect more often, then raise an
  16. RPython MemoryError, and if that is not enough,
  17. crash the program with a fatal error. Try values
  18. like '1.6GB'.
  19. PYPY_GC_MAX_DELTA The major collection threshold will never be set
  20. to more than PYPY_GC_MAX_DELTA the amount really
  21. used after a collection. Defaults to 1/8th of the
  22. total RAM size (which is constrained to be at most
  23. 2/3/4GB on 32-bit systems). Try values like '200MB'.
  24. PYPY_GC_MIN Don't collect while the memory size is below this
  25. limit. Useful to avoid spending all the time in
  26. the GC in very small programs. Defaults to 8
  27. times the nursery.
  28. PYPY_GC_DEBUG Enable extra checks around collections that are
  29. too slow for normal use. Values are 0 (off),
  30. 1 (on major collections) or 2 (also on minor
  31. collections).
  32. """
  33. # XXX Should find a way to bound the major collection threshold by the
  34. # XXX total addressable size. Maybe by keeping some minimarkpage arenas
  35. # XXX pre-reserved, enough for a few nursery collections? What about
  36. # XXX raw-malloced memory?
  37. import sys
  38. from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
  39. from pypy.rpython.lltypesystem.lloperation import llop
  40. from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
  41. from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
  42. from pypy.rpython.memory.gc import minimarkpage, env
  43. from pypy.rpython.memory.support import mangle_hash
  44. from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
  45. from pypy.rlib.rarithmetic import LONG_BIT_SHIFT
  46. from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
  47. from pypy.rlib.objectmodel import we_are_translated
  48. from pypy.tool.sourcetools import func_with_new_name
  49. #
  50. # Handles the objects in 2 generations:
  51. #
  52. # * young objects: allocated in the nursery if they are not too large, or
  53. # raw-malloced otherwise. The nursery is a fixed-size memory buffer of
  54. # 4MB by default. When full, we do a minor collection;
  55. # the surviving objects from the nursery are moved outside, and the
  56. # non-surviving raw-malloced objects are freed. All surviving objects
  57. # become old.
  58. #
  59. # * old objects: never move again. These objects are either allocated by
  60. # minimarkpage.py (if they are small), or raw-malloced (if they are not
  61. # small). Collected by regular mark-n-sweep during major collections.
  62. #
  63. WORD = LONG_BIT // 8
  64. NULL = llmemory.NULL
  65. first_gcflag = 1 << (LONG_BIT//2)
  66. # The following flag is set on objects if we need to do something to
  67. # track the young pointers that it might contain. The flag is not set
  68. # on young objects (unless they are large arrays, see below), and we
  69. # simply assume that any young object can point to any other young object.
  70. # For old and prebuilt objects, the flag is usually set, and is cleared
  71. # when we write a young pointer to it. For large arrays with
  72. # GCFLAG_HAS_CARDS, we rely on card marking to track where the
  73. # young pointers are; the flag GCFLAG_TRACK_YOUNG_PTRS is set in this
  74. # case too, to speed up the write barrier.
  75. GCFLAG_TRACK_YOUNG_PTRS = first_gcflag << 0
  76. # The following flag is set on some prebuilt objects. The flag is set
  77. # unless the object is already listed in 'prebuilt_root_objects'.
  78. # When a pointer is written inside an object with GCFLAG_NO_HEAP_PTRS
  79. # set, the write_barrier clears the flag and adds the object to
  80. # 'prebuilt_root_objects'.
  81. GCFLAG_NO_HEAP_PTRS = first_gcflag << 1
  82. # The following flag is set on surviving objects during a major collection,
  83. # and on surviving raw-malloced young objects during a minor collection.
  84. GCFLAG_VISITED = first_gcflag << 2
  85. # The following flag is set on nursery objects of which we asked the id
  86. # or the identityhash. It means that a space of the size of the object
  87. # has already been allocated in the nonmovable part. The same flag is
  88. # abused to mark prebuilt objects whose hash has been taken during
  89. # translation and is statically recorded.
  90. GCFLAG_HAS_SHADOW = first_gcflag << 3
  91. # The following flag is set temporarily on some objects during a major
  92. # collection. See pypy/doc/discussion/finalizer-order.txt
  93. GCFLAG_FINALIZATION_ORDERING = first_gcflag << 4
  94. # The following flag is set on externally raw_malloc'ed arrays of pointers.
  95. # They are allocated with some extra space in front of them for a bitfield,
  96. # one bit per 'card_page_indices' indices.
  97. GCFLAG_HAS_CARDS = first_gcflag << 5
  98. GCFLAG_CARDS_SET = first_gcflag << 6 # <- at least one card bit is set
  99. TID_MASK = (first_gcflag << 7) - 1
  100. FORWARDSTUB = lltype.GcStruct('forwarding_stub',
  101. ('forw', llmemory.Address))
  102. FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
  103. # ____________________________________________________________
  104. class MiniMarkGC(MovingGCBase):
  105. _alloc_flavor_ = "raw"
  106. inline_simple_malloc = True
  107. inline_simple_malloc_varsize = True
  108. needs_write_barrier = True
  109. prebuilt_gc_objects_are_static_roots = False
  110. malloc_zero_filled = True # xxx experiment with False
  111. gcflag_extra = GCFLAG_FINALIZATION_ORDERING
  112. # All objects start with a HDR, i.e. with a field 'tid' which contains
  113. # a word. This word is divided in two halves: the lower half contains
  114. # the typeid, and the upper half contains various flags, as defined
  115. # by GCFLAG_xxx above.
  116. HDR = lltype.Struct('header', ('tid', lltype.Signed))
  117. typeid_is_in_field = 'tid'
  118. withhash_flag_is_in_field = 'tid', GCFLAG_HAS_SHADOW
  119. # ^^^ prebuilt objects may have the flag GCFLAG_HAS_SHADOW;
  120. # then they are one word longer, the extra word storing the hash.
  121. # During a minor collection, the objects in the nursery that are
  122. # moved outside are changed in-place: their header is replaced with
  123. # the value -42, and the following word is set to the address of
  124. # where the object was moved. This means that all objects in the
  125. # nursery need to be at least 2 words long, but objects outside the
  126. # nursery don't need to.
  127. minimal_size_in_nursery = (
  128. llmemory.sizeof(HDR) + llmemory.sizeof(llmemory.Address))
  129. TRANSLATION_PARAMS = {
  130. # Automatically adjust the size of the nursery and the
  131. # 'major_collection_threshold' from the environment.
  132. # See docstring at the start of the file.
  133. "read_from_env": True,
  134. # The size of the nursery. Note that this is only used as a
  135. # fall-back number.
  136. "nursery_size": 896*1024,
  137. # The system page size. Like obmalloc.c, we assume that it is 4K
  138. # for 32-bit systems; unlike obmalloc.c, we assume that it is 8K
  139. # for 64-bit systems, for consistent results.
  140. "page_size": 1024*WORD,
  141. # The size of an arena. Arenas are groups of pages allocated
  142. # together.
  143. "arena_size": 65536*WORD,
  144. # The maximum size of an object allocated compactly. All objects
  145. # that are larger are just allocated with raw_malloc(). Note that
  146. # the size limit for being first allocated in the nursery is much
  147. # larger; see below.
  148. "small_request_threshold": 35*WORD,
  149. # Full collection threshold: after a major collection, we record
  150. # the total size consumed; and after every minor collection, if the
  151. # total size is now more than 'major_collection_threshold' times,
  152. # we trigger the next major collection.
  153. "major_collection_threshold": 1.82,
  154. # Threshold to avoid that the total heap size grows by a factor of
  155. # major_collection_threshold at every collection: it can only
  156. # grow at most by the following factor from one collection to the
  157. # next. Used e.g. when there is a sudden, temporary peak in memory
  158. # usage; this avoids that the upper bound grows too fast.
  159. "growth_rate_max": 1.4,
  160. # The number of array indices that are mapped to a single bit in
  161. # write_barrier_from_array(). Must be a power of two. The default
  162. # value of 128 means that card pages are 512 bytes (1024 on 64-bits)
  163. # in regular arrays of pointers; more in arrays whose items are
  164. # larger. A value of 0 disables card marking.
  165. "card_page_indices": 128,
  166. # Objects whose total size is at least 'large_object' bytes are
  167. # allocated out of the nursery immediately, as old objects. The
  168. # minimal allocated size of the nursery is 2x the following
  169. # number (by default, at least 132KB on 32-bit and 264KB on 64-bit).
  170. "large_object": (16384+512)*WORD,
  171. }
  172. def __init__(self, config,
  173. read_from_env=False,
  174. nursery_size=32*WORD,
  175. page_size=16*WORD,
  176. arena_size=64*WORD,
  177. small_request_threshold=5*WORD,
  178. major_collection_threshold=2.5,
  179. growth_rate_max=2.5, # for tests
  180. card_page_indices=0,
  181. large_object=8*WORD,
  182. ArenaCollectionClass=None,
  183. **kwds):
  184. MovingGCBase.__init__(self, config, **kwds)
  185. assert small_request_threshold % WORD == 0
  186. self.read_from_env = read_from_env
  187. self.nursery_size = nursery_size
  188. self.small_request_threshold = small_request_threshold
  189. self.major_collection_threshold = major_collection_threshold
  190. self.growth_rate_max = growth_rate_max
  191. self.num_major_collects = 0
  192. self.min_heap_size = 0.0
  193. self.max_heap_size = 0.0
  194. self.max_heap_size_already_raised = False
  195. self.max_delta = float(r_uint(-1))
  196. #
  197. self.card_page_indices = card_page_indices
  198. if self.card_page_indices > 0:
  199. self.card_page_shift = 0
  200. while (1 << self.card_page_shift) < self.card_page_indices:
  201. self.card_page_shift += 1
  202. #
  203. # 'large_object' limit how big objects can be in the nursery, so
  204. # it gives a lower bound on the allowed size of the nursery.
  205. self.nonlarge_max = large_object - 1
  206. #
  207. self.nursery = NULL
  208. self.nursery_free = NULL
  209. self.nursery_top = NULL
  210. self.debug_tiny_nursery = -1
  211. self.debug_rotating_nurseries = None
  212. #
  213. # The ArenaCollection() handles the nonmovable objects allocation.
  214. if ArenaCollectionClass is None:
  215. ArenaCollectionClass = minimarkpage.ArenaCollection
  216. self.ac = ArenaCollectionClass(arena_size, page_size,
  217. small_request_threshold)
  218. #
  219. # Used by minor collection: a list of (mostly non-young) objects that
  220. # (may) contain a pointer to a young object. Populated by
  221. # the write barrier: when we clear GCFLAG_TRACK_YOUNG_PTRS, we
  222. # add it to this list.
  223. # Note that young array objects may (by temporary "mistake") be added
  224. # to this list, but will be removed again at the start of the next
  225. # minor collection.
  226. self.old_objects_pointing_to_young = self.AddressStack()
  227. #
  228. # Similar to 'old_objects_pointing_to_young', but lists objects
  229. # that have the GCFLAG_CARDS_SET bit. For large arrays. Note
  230. # that it is possible for an object to be listed both in here
  231. # and in 'old_objects_pointing_to_young', in which case we
  232. # should just clear the cards and trace it fully, as usual.
  233. # Note also that young array objects are never listed here.
  234. self.old_objects_with_cards_set = self.AddressStack()
  235. #
  236. # A list of all prebuilt GC objects that contain pointers to the heap
  237. self.prebuilt_root_objects = self.AddressStack()
  238. #
  239. self._init_writebarrier_logic()
  240. def setup(self):
  241. """Called at run-time to initialize the GC."""
  242. #
  243. # Hack: MovingGCBase.setup() sets up stuff related to id(), which
  244. # we implement differently anyway. So directly call GCBase.setup().
  245. GCBase.setup(self)
  246. #
  247. # Two lists of all raw_malloced objects (the objects too large)
  248. self.young_rawmalloced_objects = self.null_address_dict()
  249. self.old_rawmalloced_objects = self.AddressStack()
  250. self.rawmalloced_total_size = r_uint(0)
  251. #
  252. # A list of all objects with finalizers (these are never young).
  253. self.objects_with_finalizers = self.AddressDeque()
  254. self.young_objects_with_light_finalizers = self.AddressStack()
  255. self.old_objects_with_light_finalizers = self.AddressStack()
  256. #
  257. # Two lists of the objects with weakrefs. No weakref can be an
  258. # old object weakly pointing to a young object: indeed, weakrefs
  259. # are immutable so they cannot point to an object that was
  260. # created after it.
  261. self.young_objects_with_weakrefs = self.AddressStack()
  262. self.old_objects_with_weakrefs = self.AddressStack()
  263. #
  264. # Support for id and identityhash: map nursery objects with
  265. # GCFLAG_HAS_SHADOW to their future location at the next
  266. # minor collection.
  267. self.nursery_objects_shadows = self.AddressDict()
  268. #
  269. # Allocate a nursery. In case of auto_nursery_size, start by
  270. # allocating a very small nursery, enough to do things like look
  271. # up the env var, which requires the GC; and then really
  272. # allocate the nursery of the final size.
  273. if not self.read_from_env:
  274. self.allocate_nursery()
  275. else:
  276. #
  277. defaultsize = self.nursery_size
  278. minsize = 2 * (self.nonlarge_max + 1)
  279. self.nursery_size = minsize
  280. self.allocate_nursery()
  281. #
  282. # From there on, the GC is fully initialized and the code
  283. # below can use it
  284. newsize = env.read_from_env('PYPY_GC_NURSERY')
  285. # PYPY_GC_NURSERY=smallvalue means that minor collects occur
  286. # very frequently; the extreme case is PYPY_GC_NURSERY=1, which
  287. # forces a minor collect for every malloc. Useful to debug
  288. # external factors, like trackgcroot or the handling of the write
  289. # barrier. Implemented by still using 'minsize' for the nursery
  290. # size (needed to handle mallocs just below 'large_objects') but
  291. # hacking at the current nursery position in collect_and_reserve().
  292. if newsize <= 0:
  293. newsize = 4*1024*1024 # fixed to 4MB by default
  294. # (it was env.estimate_best_nursery_size())
  295. if newsize <= 0:
  296. newsize = defaultsize
  297. if newsize < minsize:
  298. self.debug_tiny_nursery = newsize & ~(WORD-1)
  299. newsize = minsize
  300. #
  301. major_coll = env.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
  302. if major_coll > 1.0:
  303. self.major_collection_threshold = major_coll
  304. #
  305. growth = env.read_float_from_env('PYPY_GC_GROWTH')
  306. if growth > 1.0:
  307. self.growth_rate_max = growth
  308. #
  309. min_heap_size = env.read_uint_from_env('PYPY_GC_MIN')
  310. if min_heap_size > 0:
  311. self.min_heap_size = float(min_heap_size)
  312. else:
  313. # defaults to 8 times the nursery
  314. self.min_heap_size = newsize * 8
  315. #
  316. max_heap_size = env.read_uint_from_env('PYPY_GC_MAX')
  317. if max_heap_size > 0:
  318. self.max_heap_size = float(max_heap_size)
  319. #
  320. max_delta = env.read_uint_from_env('PYPY_GC_MAX_DELTA')
  321. if max_delta > 0:
  322. self.max_delta = float(max_delta)
  323. else:
  324. self.max_delta = 0.125 * env.get_total_memory()
  325. #
  326. self.minor_collection() # to empty the nursery
  327. llarena.arena_free(self.nursery)
  328. self.nursery_size = newsize
  329. self.allocate_nursery()
  330. def _nursery_memory_size(self):
  331. extra = self.nonlarge_max + 1
  332. return self.nursery_size + extra
  333. def _alloc_nursery(self):
  334. # the start of the nursery: we actually allocate a bit more for
  335. # the nursery than really needed, to simplify pointer arithmetic
  336. # in malloc_fixedsize_clear(). The few extra pages are never used
  337. # anyway so it doesn't even count.
  338. nursery = llarena.arena_malloc(self._nursery_memory_size(), 2)
  339. if not nursery:
  340. raise MemoryError("cannot allocate nursery")
  341. return nursery
  342. def allocate_nursery(self):
  343. debug_start("gc-set-nursery-size")
  344. debug_print("nursery size:", self.nursery_size)
  345. self.nursery = self._alloc_nursery()
  346. # the current position in the nursery:
  347. self.nursery_free = self.nursery
  348. # the end of the nursery:
  349. self.nursery_top = self.nursery + self.nursery_size
  350. # initialize the threshold
  351. self.min_heap_size = max(self.min_heap_size, self.nursery_size *
  352. self.major_collection_threshold)
  353. # the following two values are usually equal, but during raw mallocs
  354. # of arrays, next_major_collection_threshold is decremented to make
  355. # the next major collection arrive earlier.
  356. # See translator/c/test/test_newgc, test_nongc_attached_to_gc
  357. self.next_major_collection_initial = self.min_heap_size
  358. self.next_major_collection_threshold = self.min_heap_size
  359. self.set_major_threshold_from(0.0)
  360. debug_stop("gc-set-nursery-size")
  361. def set_major_threshold_from(self, threshold, reserving_size=0):
  362. # Set the next_major_collection_threshold.
  363. threshold_max = (self.next_major_collection_initial *
  364. self.growth_rate_max)
  365. if threshold > threshold_max:
  366. threshold = threshold_max
  367. #
  368. threshold += reserving_size
  369. if threshold < self.min_heap_size:
  370. threshold = self.min_heap_size
  371. #
  372. if self.max_heap_size > 0.0 and threshold > self.max_heap_size:
  373. threshold = self.max_heap_size
  374. bounded = True
  375. else:
  376. bounded = False
  377. #
  378. self.next_major_collection_initial = threshold
  379. self.next_major_collection_threshold = threshold
  380. return bounded
  381. def post_setup(self):
  382. # set up extra stuff for PYPY_GC_DEBUG.
  383. MovingGCBase.post_setup(self)
  384. if self.DEBUG and llarena.has_protect:
  385. # gc debug mode: allocate 23 nurseries instead of just 1,
  386. # and use them alternatively, while mprotect()ing the unused
  387. # ones to detect invalid access.
  388. debug_start("gc-debug")
  389. self.debug_rotating_nurseries = []
  390. for i in range(22):
  391. nurs = self._alloc_nursery()
  392. llarena.arena_protect(nurs, self._nursery_memory_size(), True)
  393. self.debug_rotating_nurseries.append(nurs)
  394. debug_print("allocated", len(self.debug_rotating_nurseries),
  395. "extra nurseries")
  396. debug_stop("gc-debug")
  397. def debug_rotate_nursery(self):
  398. if self.debug_rotating_nurseries is not None:
  399. debug_start("gc-debug")
  400. oldnurs = self.nursery
  401. llarena.arena_protect(oldnurs, self._nursery_memory_size(), True)
  402. self.debug_rotating_nurseries.append(oldnurs)
  403. #
  404. newnurs = self.debug_rotating_nurseries.pop(0)
  405. llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
  406. self.nursery = newnurs
  407. self.nursery_top = self.nursery + self.nursery_size
  408. debug_print("switching from nursery", oldnurs,
  409. "to nursery", self.nursery,
  410. "size", self.nursery_size)
  411. debug_stop("gc-debug")
  412. def malloc_fixedsize_clear(self, typeid, size,
  413. needs_finalizer=False,
  414. is_finalizer_light=False,
  415. contains_weakptr=False):
  416. size_gc_header = self.gcheaderbuilder.size_gc_header
  417. totalsize = size_gc_header + size
  418. rawtotalsize = raw_malloc_usage(totalsize)
  419. #
  420. # If the object needs a finalizer, ask for a rawmalloc.
  421. # The following check should be constant-folded.
  422. if needs_finalizer and not is_finalizer_light:
  423. ll_assert(not contains_weakptr,
  424. "'needs_finalizer' and 'contains_weakptr' both specified")
  425. obj = self.external_malloc(typeid, 0, can_make_young=False)
  426. self.objects_with_finalizers.append(obj)
  427. #
  428. # If totalsize is greater than nonlarge_max (which should never be
  429. # the case in practice), ask for a rawmalloc. The following check
  430. # should be constant-folded.
  431. elif rawtotalsize > self.nonlarge_max:
  432. ll_assert(not contains_weakptr,
  433. "'contains_weakptr' specified for a large object")
  434. obj = self.external_malloc(typeid, 0)
  435. #
  436. else:
  437. # If totalsize is smaller than minimal_size_in_nursery, round it
  438. # up. The following check should also be constant-folded.
  439. min_size = raw_malloc_usage(self.minimal_size_in_nursery)
  440. if rawtotalsize < min_size:
  441. totalsize = rawtotalsize = min_size
  442. #
  443. # Get the memory from the nursery. If there is not enough space
  444. # there, do a collect first.
  445. result = self.nursery_free
  446. self.nursery_free = result + totalsize
  447. if self.nursery_free > self.nursery_top:
  448. result = self.collect_and_reserve(totalsize)
  449. #
  450. # Build the object.
  451. llarena.arena_reserve(result, totalsize)
  452. obj = result + size_gc_header
  453. if is_finalizer_light:
  454. self.young_objects_with_light_finalizers.append(obj)
  455. self.init_gc_object(result, typeid, flags=0)
  456. #
  457. # If it is a weakref, record it (check constant-folded).
  458. if contains_weakptr:
  459. self.young_objects_with_weakrefs.append(obj)
  460. #
  461. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  462. def malloc_varsize_clear(self, typeid, length, size, itemsize,
  463. offset_to_length):
  464. size_gc_header = self.gcheaderbuilder.size_gc_header
  465. nonvarsize = size_gc_header + size
  466. #
  467. # Compute the maximal length that makes the object still
  468. # below 'nonlarge_max'. All the following logic is usually
  469. # constant-folded because self.nonlarge_max, size and itemsize
  470. # are all constants (the arguments are constant due to
  471. # inlining).
  472. maxsize = self.nonlarge_max - raw_malloc_usage(nonvarsize)
  473. if maxsize < 0:
  474. toobig = r_uint(0) # the nonvarsize alone is too big
  475. elif raw_malloc_usage(itemsize):
  476. toobig = r_uint(maxsize // raw_malloc_usage(itemsize)) + 1
  477. else:
  478. toobig = r_uint(sys.maxint) + 1
  479. if r_uint(length) >= r_uint(toobig):
  480. #
  481. # If the total size of the object would be larger than
  482. # 'nonlarge_max', then allocate it externally. We also
  483. # go there if 'length' is actually negative.
  484. obj = self.external_malloc(typeid, length)
  485. #
  486. else:
  487. # With the above checks we know now that totalsize cannot be more
  488. # than 'nonlarge_max'; in particular, the + and * cannot overflow.
  489. totalsize = nonvarsize + itemsize * length
  490. totalsize = llarena.round_up_for_allocation(totalsize)
  491. #
  492. # 'totalsize' should contain at least the GC header and
  493. # the length word, so it should never be smaller than
  494. # 'minimal_size_in_nursery'
  495. ll_assert(raw_malloc_usage(totalsize) >=
  496. raw_malloc_usage(self.minimal_size_in_nursery),
  497. "malloc_varsize_clear(): totalsize < minimalsize")
  498. #
  499. # Get the memory from the nursery. If there is not enough space
  500. # there, do a collect first.
  501. result = self.nursery_free
  502. self.nursery_free = result + totalsize
  503. if self.nursery_free > self.nursery_top:
  504. result = self.collect_and_reserve(totalsize)
  505. #
  506. # Build the object.
  507. llarena.arena_reserve(result, totalsize)
  508. self.init_gc_object(result, typeid, flags=0)
  509. #
  510. # Set the length and return the object.
  511. obj = result + size_gc_header
  512. (obj + offset_to_length).signed[0] = length
  513. #
  514. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  515. def collect(self, gen=1):
  516. """Do a minor (gen=0) or major (gen>0) collection."""
  517. self.minor_collection()
  518. if gen > 0:
  519. self.major_collection()
  520. def collect_and_reserve(self, totalsize):
  521. """To call when nursery_free overflows nursery_top.
  522. Do a minor collection, and possibly also a major collection,
  523. and finally reserve 'totalsize' bytes at the start of the
  524. now-empty nursery.
  525. """
  526. self.minor_collection()
  527. #
  528. if self.get_total_memory_used() > self.next_major_collection_threshold:
  529. self.major_collection()
  530. #
  531. # The nursery might not be empty now, because of
  532. # execute_finalizers(). If it is almost full again,
  533. # we need to fix it with another call to minor_collection().
  534. if self.nursery_free + totalsize > self.nursery_top:
  535. self.minor_collection()
  536. #
  537. result = self.nursery_free
  538. self.nursery_free = result + totalsize
  539. ll_assert(self.nursery_free <= self.nursery_top, "nursery overflow")
  540. #
  541. if self.debug_tiny_nursery >= 0: # for debugging
  542. if self.nursery_top - self.nursery_free > self.debug_tiny_nursery:
  543. self.nursery_free = self.nursery_top - self.debug_tiny_nursery
  544. #
  545. return result
  546. collect_and_reserve._dont_inline_ = True
  547. def external_malloc(self, typeid, length, can_make_young=True):
  548. """Allocate a large object using the ArenaCollection or
  549. raw_malloc(), possibly as an object with card marking enabled,
  550. if it has gc pointers in its var-sized part. 'length' should be
  551. specified as 0 if the object is not varsized. The returned
  552. object is fully initialized and zero-filled."""
  553. #
  554. # Here we really need a valid 'typeid', not 0 (as the JIT might
  555. # try to send us if there is still a bug).
  556. ll_assert(bool(self.combine(typeid, 0)),
  557. "external_malloc: typeid == 0")
  558. #
  559. # Compute the total size, carefully checking for overflows.
  560. size_gc_header = self.gcheaderbuilder.size_gc_header
  561. nonvarsize = size_gc_header + self.fixed_size(typeid)
  562. if length == 0:
  563. # this includes the case of fixed-size objects, for which we
  564. # should not even ask for the varsize_item_sizes().
  565. totalsize = nonvarsize
  566. elif length > 0:
  567. # var-sized allocation with at least one item
  568. itemsize = self.varsize_item_sizes(typeid)
  569. try:
  570. varsize = ovfcheck(itemsize * length)
  571. totalsize = ovfcheck(nonvarsize + varsize)
  572. except OverflowError:
  573. raise MemoryError
  574. else:
  575. # negative length! This likely comes from an overflow
  576. # earlier. We will just raise MemoryError here.
  577. raise MemoryError
  578. #
  579. # If somebody calls this function a lot, we must eventually
  580. # force a full collection.
  581. if (float(self.get_total_memory_used()) + raw_malloc_usage(totalsize) >
  582. self.next_major_collection_threshold):
  583. self.minor_collection()
  584. self.major_collection(raw_malloc_usage(totalsize))
  585. #
  586. # Check if the object would fit in the ArenaCollection.
  587. if raw_malloc_usage(totalsize) <= self.small_request_threshold:
  588. #
  589. # Yes. Round up 'totalsize' (it cannot overflow and it
  590. # must remain <= self.small_request_threshold.)
  591. totalsize = llarena.round_up_for_allocation(totalsize)
  592. ll_assert(raw_malloc_usage(totalsize) <=
  593. self.small_request_threshold,
  594. "rounding up made totalsize > small_request_threshold")
  595. #
  596. # Allocate from the ArenaCollection and clear the memory returned.
  597. result = self.ac.malloc(totalsize)
  598. llmemory.raw_memclear(result, totalsize)
  599. #
  600. # An object allocated from ArenaCollection is always old, even
  601. # if 'can_make_young'. The interesting case of 'can_make_young'
  602. # is for large objects, bigger than the 'large_objects' threshold,
  603. # which are raw-malloced but still young.
  604. extra_flags = GCFLAG_TRACK_YOUNG_PTRS
  605. #
  606. else:
  607. # No, so proceed to allocate it externally with raw_malloc().
  608. # Check if we need to introduce the card marker bits area.
  609. if (self.card_page_indices <= 0 # <- this check is constant-folded
  610. or not self.has_gcptr_in_varsize(typeid) or
  611. raw_malloc_usage(totalsize) <= self.nonlarge_max):
  612. #
  613. # In these cases, we don't want a card marker bits area.
  614. # This case also includes all fixed-size objects.
  615. cardheadersize = 0
  616. extra_flags = 0
  617. #
  618. else:
  619. # Reserve N extra words containing card bits before the object.
  620. extra_words = self.card_marking_words_for_length(length)
  621. cardheadersize = WORD * extra_words
  622. extra_flags = GCFLAG_HAS_CARDS | GCFLAG_TRACK_YOUNG_PTRS
  623. # if 'can_make_young', then we also immediately set
  624. # GCFLAG_CARDS_SET, but without adding the object to
  625. # 'old_objects_with_cards_set'. In this way it should
  626. # never be added to that list as long as it is young.
  627. if can_make_young:
  628. extra_flags |= GCFLAG_CARDS_SET
  629. #
  630. # Detect very rare cases of overflows
  631. if raw_malloc_usage(totalsize) > (sys.maxint - (WORD-1)
  632. - cardheadersize):
  633. raise MemoryError("rare case of overflow")
  634. #
  635. # Now we know that the following computations cannot overflow.
  636. # Note that round_up_for_allocation() is also needed to get the
  637. # correct number added to 'rawmalloced_total_size'.
  638. allocsize = (cardheadersize + raw_malloc_usage(
  639. llarena.round_up_for_allocation(totalsize)))
  640. #
  641. # Allocate the object using arena_malloc(), which we assume here
  642. # is just the same as raw_malloc(), but allows the extra
  643. # flexibility of saying that we have extra words in the header.
  644. # The memory returned is cleared by a raw_memclear().
  645. arena = llarena.arena_malloc(allocsize, 2)
  646. if not arena:
  647. raise MemoryError("cannot allocate large object")
  648. #
  649. # Reserve the card mark bits as a list of single bytes
  650. # (the loop is empty in C).
  651. i = 0
  652. while i < cardheadersize:
  653. llarena.arena_reserve(arena + i, llmemory.sizeof(lltype.Char))
  654. i += 1
  655. #
  656. # Reserve the actual object. (This is also a no-op in C).
  657. result = arena + cardheadersize
  658. llarena.arena_reserve(result, totalsize)
  659. #
  660. # Record the newly allocated object and its full malloced size.
  661. # The object is young or old depending on the argument.
  662. self.rawmalloced_total_size += r_uint(allocsize)
  663. if can_make_young:
  664. if not self.young_rawmalloced_objects:
  665. self.young_rawmalloced_objects = self.AddressDict()
  666. self.young_rawmalloced_objects.add(result + size_gc_header)
  667. else:
  668. self.old_rawmalloced_objects.append(result + size_gc_header)
  669. extra_flags |= GCFLAG_TRACK_YOUNG_PTRS
  670. #
  671. # Common code to fill the header and length of the object.
  672. self.init_gc_object(result, typeid, extra_flags)
  673. if self.is_varsize(typeid):
  674. offset_to_length = self.varsize_offset_to_length(typeid)
  675. (result + size_gc_header + offset_to_length).signed[0] = length
  676. return result + size_gc_header
  677. # ----------
  678. # Other functions in the GC API
  679. def set_max_heap_size(self, size):
  680. self.max_heap_size = float(size)
  681. if self.max_heap_size > 0.0:
  682. if self.max_heap_size < self.next_major_collection_initial:
  683. self.next_major_collection_initial = self.max_heap_size
  684. if self.max_heap_size < self.next_major_collection_threshold:
  685. self.next_major_collection_threshold = self.max_heap_size
  686. def raw_malloc_memory_pressure(self, sizehint):
  687. self.next_major_collection_threshold -= sizehint
  688. if self.next_major_collection_threshold < 0:
  689. # cannot trigger a full collection now, but we can ensure
  690. # that one will occur very soon
  691. self.nursery_free = self.nursery_top
  692. def can_malloc_nonmovable(self):
  693. return True
  694. def can_optimize_clean_setarrayitems(self):
  695. if self.card_page_indices > 0:
  696. return False
  697. return MovingGCBase.can_optimize_clean_setarrayitems(self)
  698. def can_move(self, obj):
  699. """Overrides the parent can_move()."""
  700. return self.is_in_nursery(obj)
  701. def shrink_array(self, obj, smallerlength):
  702. #
  703. # Only objects in the nursery can be "resized". Resizing them
  704. # means recording that they have a smaller size, so that when
  705. # moved out of the nursery, they will consume less memory.
  706. # In particular, an array with GCFLAG_HAS_CARDS is never resized.
  707. # Also, a nursery object with GCFLAG_HAS_SHADOW is not resized
  708. # either, as this would potentially loose part of the memory in
  709. # the already-allocated shadow.
  710. if not self.is_in_nursery(obj):
  711. return False
  712. if self.header(obj).tid & GCFLAG_HAS_SHADOW:
  713. return False
  714. #
  715. size_gc_header = self.gcheaderbuilder.size_gc_header
  716. typeid = self.get_type_id(obj)
  717. totalsmallersize = (
  718. size_gc_header + self.fixed_size(typeid) +
  719. self.varsize_item_sizes(typeid) * smallerlength)
  720. llarena.arena_shrink_obj(obj - size_gc_header, totalsmallersize)
  721. #
  722. offset_to_length = self.varsize_offset_to_length(typeid)
  723. (obj + offset_to_length).signed[0] = smallerlength
  724. return True
  725. def malloc_fixedsize_nonmovable(self, typeid):
  726. obj = self.external_malloc(typeid, 0)
  727. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  728. def malloc_varsize_nonmovable(self, typeid, length):
  729. obj = self.external_malloc(typeid, length)
  730. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  731. def malloc_nonmovable(self, typeid, length, zero):
  732. # helper for testing, same as GCBase.malloc
  733. return self.external_malloc(typeid, length or 0) # None -> 0
  734. # ----------
  735. # Simple helpers
  736. def get_type_id(self, obj):
  737. tid = self.header(obj).tid
  738. return llop.extract_ushort(llgroup.HALFWORD, tid)
  739. def combine(self, typeid16, flags):
  740. return llop.combine_ushort(lltype.Signed, typeid16, flags)
  741. def init_gc_object(self, addr, typeid16, flags=0):
  742. # The default 'flags' is zero. The flags GCFLAG_NO_xxx_PTRS
  743. # have been chosen to allow 'flags' to be zero in the common
  744. # case (hence the 'NO' in their name).
  745. hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
  746. hdr.tid = self.combine(typeid16, flags)
  747. def init_gc_object_immortal(self, addr, typeid16, flags=0):
  748. # For prebuilt GC objects, the flags must contain
  749. # GCFLAG_NO_xxx_PTRS, at least initially.
  750. flags |= GCFLAG_NO_HEAP_PTRS | GCFLAG_TRACK_YOUNG_PTRS
  751. self.init_gc_object(addr, typeid16, flags)
  752. def is_in_nursery(self, addr):
  753. ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0,
  754. "odd-valued (i.e. tagged) pointer unexpected here")
  755. return self.nursery <= addr < self.nursery_top
  756. def appears_to_be_young(self, addr):
  757. # "is a valid addr to a young object?"
  758. # but it's ok to occasionally return True accidentally.
  759. # Maybe the best implementation would be a bloom filter
  760. # of some kind instead of the dictionary lookup that is
  761. # sometimes done below. But the expected common answer
  762. # is "Yes" because addr points to the nursery, so it may
  763. # not be useful to optimize the other case too much.
  764. #
  765. # First, if 'addr' appears to be a pointer to some place within
  766. # the nursery, return True
  767. if not self.translated_to_c:
  768. # When non-translated, filter out tagged pointers explicitly.
  769. # When translated, it may occasionally give a wrong answer
  770. # of True if 'addr' is a tagged pointer with just the wrong value.
  771. if not self.is_valid_gc_object(addr):
  772. return False
  773. if self.nursery <= addr < self.nursery_top:
  774. return True # addr is in the nursery
  775. #
  776. # Else, it may be in the set 'young_rawmalloced_objects'
  777. return (bool(self.young_rawmalloced_objects) and
  778. self.young_rawmalloced_objects.contains(addr))
  779. appears_to_be_young._always_inline_ = True
  780. def debug_is_old_object(self, addr):
  781. return (self.is_valid_gc_object(addr)
  782. and not self.appears_to_be_young(addr))
  783. def is_forwarded(self, obj):
  784. """Returns True if the nursery obj is marked as forwarded.
  785. Implemented a bit obscurely by checking an unrelated flag
  786. that can never be set on a young object -- except if tid == -42.
  787. """
  788. assert self.is_in_nursery(obj)
  789. tid = self.header(obj).tid
  790. result = (tid & GCFLAG_FINALIZATION_ORDERING != 0)
  791. if result:
  792. ll_assert(tid == -42, "bogus header for young obj")
  793. else:
  794. ll_assert(bool(tid), "bogus header (1)")
  795. ll_assert(tid & ~TID_MASK == 0, "bogus header (2)")
  796. return result
  797. def get_forwarding_address(self, obj):
  798. return llmemory.cast_adr_to_ptr(obj, FORWARDSTUBPTR).forw
  799. def get_total_memory_used(self):
  800. """Return the total memory used, not counting any object in the
  801. nursery: only objects in the ArenaCollection or raw-malloced.
  802. """
  803. return self.ac.total_memory_used + self.rawmalloced_total_size
  804. def card_marking_words_for_length(self, length):
  805. # --- Unoptimized version:
  806. #num_bits = ((length-1) >> self.card_page_shift) + 1
  807. #return (num_bits + (LONG_BIT - 1)) >> LONG_BIT_SHIFT
  808. # --- Optimized version:
  809. return intmask(
  810. ((r_uint(length) + r_uint((LONG_BIT << self.card_page_shift) - 1)) >>
  811. (self.card_page_shift + LONG_BIT_SHIFT)))
  812. def card_marking_bytes_for_length(self, length):
  813. # --- Unoptimized version:
  814. #num_bits = ((length-1) >> self.card_page_shift) + 1
  815. #return (num_bits + 7) >> 3
  816. # --- Optimized version:
  817. return intmask(
  818. ((r_uint(length) + r_uint((8 << self.card_page_shift) - 1)) >>
  819. (self.card_page_shift + 3)))
  820. def debug_check_consistency(self):
  821. if self.DEBUG:
  822. ll_assert(not self.young_rawmalloced_objects,
  823. "young raw-malloced objects in a major collection")
  824. ll_assert(not self.young_objects_with_weakrefs.non_empty(),
  825. "young objects with weakrefs in a major collection")
  826. MovingGCBase.debug_check_consistency(self)
  827. def debug_check_object(self, obj):
  828. # after a minor or major collection, no object should be in the nursery
  829. ll_assert(not self.is_in_nursery(obj),
  830. "object in nursery after collection")
  831. # similarily, all objects should have this flag:
  832. ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
  833. "missing GCFLAG_TRACK_YOUNG_PTRS")
  834. # the GCFLAG_VISITED should not be set between collections
  835. ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0,
  836. "unexpected GCFLAG_VISITED")
  837. # the GCFLAG_FINALIZATION_ORDERING should not be set between coll.
  838. ll_assert(self.header(obj).tid & GCFLAG_FINALIZATION_ORDERING == 0,
  839. "unexpected GCFLAG_FINALIZATION_ORDERING")
  840. # the GCFLAG_CARDS_SET should not be set between collections
  841. ll_assert(self.header(obj).tid & GCFLAG_CARDS_SET == 0,
  842. "unexpected GCFLAG_CARDS_SET")
  843. # if the GCFLAG_HAS_CARDS is set, check that all bits are zero now
  844. if self.header(obj).tid & GCFLAG_HAS_CARDS:
  845. if self.card_page_indices <= 0:
  846. ll_assert(False, "GCFLAG_HAS_CARDS but not using card marking")
  847. return
  848. typeid = self.get_type_id(obj)
  849. ll_assert(self.has_gcptr_in_varsize(typeid),
  850. "GCFLAG_HAS_CARDS but not has_gcptr_in_varsize")
  851. ll_assert(self.header(obj).tid & GCFLAG_NO_HEAP_PTRS == 0,
  852. "GCFLAG_HAS_CARDS && GCFLAG_NO_HEAP_PTRS")
  853. offset_to_length = self.varsize_offset_to_length(typeid)
  854. length = (obj + offset_to_length).signed[0]
  855. extra_words = self.card_marking_words_for_length(length)
  856. #
  857. size_gc_header = self.gcheaderbuilder.size_gc_header
  858. p = llarena.getfakearenaaddress(obj - size_gc_header)
  859. i = extra_words * WORD
  860. while i > 0:
  861. p -= 1
  862. ll_assert(p.char[0] == '\x00',
  863. "the card marker bits are not cleared")
  864. i -= 1
  865. # ----------
  866. # Write barrier
  867. # for the JIT: a minimal description of the write_barrier() method
  868. # (the JIT assumes it is of the shape
  869. # "if addr_struct.int0 & JIT_WB_IF_FLAG: remember_young_pointer()")
  870. JIT_WB_IF_FLAG = GCFLAG_TRACK_YOUNG_PTRS
  871. # for the JIT to generate custom code corresponding to the array
  872. # write barrier for the simplest case of cards. If JIT_CARDS_SET
  873. # is already set on an object, it will execute code like this:
  874. # MOV eax, index
  875. # SHR eax, JIT_WB_CARD_PAGE_SHIFT
  876. # XOR eax, -8
  877. # BTS [object], eax
  878. if TRANSLATION_PARAMS['card_page_indices'] > 0:
  879. JIT_WB_CARDS_SET = GCFLAG_CARDS_SET
  880. JIT_WB_CARD_PAGE_SHIFT = 1
  881. while ((1 << JIT_WB_CARD_PAGE_SHIFT) !=
  882. TRANSLATION_PARAMS['card_page_indices']):
  883. JIT_WB_CARD_PAGE_SHIFT += 1
  884. @classmethod
  885. def JIT_max_size_of_young_obj(cls):
  886. return cls.TRANSLATION_PARAMS['large_object']
  887. @classmethod
  888. def JIT_minimal_size_in_nursery(cls):
  889. return cls.minimal_size_in_nursery
  890. def write_barrier(self, newvalue, addr_struct):
  891. if self.header(addr_struct).tid & GCFLAG_TRACK_YOUNG_PTRS:
  892. self.remember_young_pointer(addr_struct, newvalue)
  893. def write_barrier_from_array(self, newvalue, addr_array, index):
  894. if self.header(addr_array).tid & GCFLAG_TRACK_YOUNG_PTRS:
  895. if self.card_page_indices > 0: # <- constant-folded
  896. self.remember_young_pointer_from_array2(addr_array, index)
  897. else:
  898. self.remember_young_pointer(addr_array, newvalue)
  899. def _init_writebarrier_logic(self):
  900. DEBUG = self.DEBUG
  901. # The purpose of attaching remember_young_pointer to the instance
  902. # instead of keeping it as a regular method is to help the JIT call it.
  903. # Additionally, it makes the code in write_barrier() marginally smaller
  904. # (which is important because it is inlined *everywhere*).
  905. # For x86, there is also an extra requirement: when the JIT calls
  906. # remember_young_pointer(), it assumes that it will not touch the SSE
  907. # registers, so it does not save and restore them (that's a *hack*!).
  908. def remember_young_pointer(addr_struct, newvalue):
  909. # 'addr_struct' is the address of the object in which we write.
  910. # 'newvalue' is the address that we are going to write in there.
  911. # We know that 'addr_struct' has GCFLAG_TRACK_YOUNG_PTRS so far.
  912. #
  913. if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
  914. ll_assert(self.debug_is_old_object(addr_struct) or
  915. self.header(addr_struct).tid & GCFLAG_HAS_CARDS != 0,
  916. "young object with GCFLAG_TRACK_YOUNG_PTRS and no cards")
  917. #
  918. # If it seems that what we are writing is a pointer to a young obj
  919. # (as checked with appears_to_be_young()), then we need
  920. # to remove the flag GCFLAG_TRACK_YOUNG_PTRS and add the object
  921. # to the list 'old_objects_pointing_to_young'. We know that
  922. # 'addr_struct' cannot be in the nursery, because nursery objects
  923. # never have the flag GCFLAG_TRACK_YOUNG_PTRS to start with.
  924. objhdr = self.header(addr_struct)
  925. if self.appears_to_be_young(newvalue):
  926. self.old_objects_pointing_to_young.append(addr_struct)
  927. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  928. #
  929. # Second part: if 'addr_struct' is actually a prebuilt GC
  930. # object and it's the first time we see a write to it, we
  931. # add it to the list 'prebuilt_root_objects'. Note that we
  932. # do it even in the (rare?) case of 'addr' being NULL or another
  933. # prebuilt object, to simplify code.
  934. if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
  935. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  936. self.prebuilt_root_objects.append(addr_struct)
  937. remember_young_pointer._dont_inline_ = True
  938. self.remember_young_pointer = remember_young_pointer
  939. #
  940. if self.card_page_indices > 0:
  941. self._init_writebarrier_with_card_marker()
  942. def _init_writebarrier_with_card_marker(self):
  943. DEBUG = self.DEBUG
  944. def remember_young_pointer_from_array2(addr_array, index):
  945. # 'addr_array' is the address of the object in which we write,
  946. # which must have an array part; 'index' is the index of the
  947. # item that is (or contains) the pointer that we write.
  948. # We know that 'addr_array' has GCFLAG_TRACK_YOUNG_PTRS so far.
  949. #
  950. objhdr = self.header(addr_array)
  951. if objhdr.tid & GCFLAG_HAS_CARDS == 0:
  952. #
  953. if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
  954. ll_assert(self.debug_is_old_object(addr_array),
  955. "young array with no card but GCFLAG_TRACK_YOUNG_PTRS")
  956. #
  957. # no cards, use default logic. Mostly copied from above.
  958. self.old_objects_pointing_to_young.append(addr_array)
  959. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  960. if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
  961. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  962. self.prebuilt_root_objects.append(addr_array)
  963. return
  964. #
  965. # 'addr_array' is a raw_malloc'ed array with card markers
  966. # in front. Compute the index of the bit to set:
  967. bitindex = index >> self.card_page_shift
  968. byteindex = bitindex >> 3
  969. bitmask = 1 << (bitindex & 7)
  970. #
  971. # If the bit is already set, leave now.
  972. addr_byte = self.get_card(addr_array, byteindex)
  973. byte = ord(addr_byte.char[0])
  974. if byte & bitmask:
  975. return
  976. #
  977. # We set the flag (even if the newly written address does not
  978. # actually point to the nursery, which seems to be ok -- actually
  979. # it seems more important that remember_young_pointer_from_array2()
  980. # does not take 3 arguments).
  981. addr_byte.char[0] = chr(byte | bitmask)
  982. #
  983. if objhdr.tid & GCFLAG_CARDS_SET == 0:
  984. self.old_objects_with_cards_set.append(addr_array)
  985. objhdr.tid |= GCFLAG_CARDS_SET
  986. remember_young_pointer_from_array2._dont_inline_ = True
  987. assert self.card_page_indices > 0
  988. self.remember_young_pointer_from_array2 = (
  989. remember_young_pointer_from_array2)
  990. # xxx trying it out for the JIT: a 3-arguments version of the above
  991. def remember_young_pointer_from_array3(addr_array, index, newvalue):
  992. objhdr = self.header(addr_array)
  993. #
  994. # a single check for the common case of neither GCFLAG_HAS_CARDS
  995. # nor GCFLAG_NO_HEAP_PTRS
  996. if objhdr.tid & (GCFLAG_HAS_CARDS | GCFLAG_NO_HEAP_PTRS) == 0:
  997. # common case: fast path, jump to the end of the function
  998. pass
  999. elif objhdr.tid & GCFLAG_HAS_CARDS == 0:
  1000. # no cards, but GCFLAG_NO_HEAP_PTRS is set.
  1001. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  1002. self.prebuilt_root_objects.append(addr_array)
  1003. # jump to the end of the function
  1004. else:
  1005. # case with cards.
  1006. #
  1007. # If the newly written address does not actually point to a
  1008. # young object, leave now.
  1009. if not self.appears_to_be_young(newvalue):
  1010. return
  1011. #
  1012. # 'addr_array' is a raw_malloc'ed array with card markers
  1013. # in front. Compute the index of the bit to set:
  1014. bitindex = index >> self.card_page_shift
  1015. byteindex = bitindex >> 3
  1016. bitmask = 1 << (bitindex & 7)
  1017. #
  1018. # If the bit is already set, leave now.
  1019. addr_byte = self.get_card(addr_array, byteindex)
  1020. byte = ord(addr_byte.char[0])
  1021. if byte & bitmask:
  1022. return
  1023. addr_byte.char[0] = chr(byte | bitmask)
  1024. #
  1025. if objhdr.tid & GCFLAG_CARDS_SET == 0:
  1026. self.old_objects_with_cards_set.append(addr_array)
  1027. objhdr.tid |= GCFLAG_CARDS_SET
  1028. return
  1029. #
  1030. # Logic for the no-cards case, put here to minimize the number
  1031. # of checks done at the start of the function
  1032. if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
  1033. ll_assert(self.debug_is_old_object(addr_array),
  1034. "young array with no card but GCFLAG_TRACK_YOUNG_PTRS")
  1035. #
  1036. if self.appears_to_be_young(newvalue):
  1037. self.old_objects_pointing_to_young.append(addr_array)
  1038. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  1039. remember_young_pointer_from_array3._dont_inline_ = True
  1040. assert self.card_page_indices > 0
  1041. self.remember_young_pointer_from_array3 = (
  1042. remember_young_pointer_from_array3)
  1043. def get_card(self, obj, byteindex):
  1044. size_gc_header = self.gcheaderbuilder.size_gc_header
  1045. addr_byte = obj - size_gc_header
  1046. return llarena.getfakearenaaddress(addr_byte) + (~byteindex)
  1047. def assume_young_pointers(self, addr_struct):
  1048. """Called occasionally by the JIT to mean ``assume that 'addr_struct'
  1049. may now contain young pointers.''
  1050. """
  1051. objhdr = self.header(addr_struct)
  1052. if objhdr.tid & GCFLAG_TRACK_YOUNG_PTRS:
  1053. self.old_objects_pointing_to_young.append(addr_struct)
  1054. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  1055. #
  1056. if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
  1057. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  1058. self.prebuilt_root_objects.append(addr_struct)
  1059. def writebarrier_before_copy(self, source_addr, dest_addr,
  1060. source_start, dest_start, length):
  1061. """ This has the same effect as calling writebarrier over
  1062. each element in dest copied from source, except it might reset
  1063. one of the following flags a bit too eagerly, which means we'll have
  1064. a bit more objects to track, but being on the safe side.
  1065. """
  1066. source_hdr = self.header(source_addr)
  1067. dest_hdr = self.header(dest_addr)
  1068. if dest_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1069. return True
  1070. # ^^^ a fast path of write-barrier
  1071. #
  1072. if source_hdr.tid & GCFLAG_HAS_CARDS != 0:
  1073. #
  1074. if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1075. # The source object may have random young pointers.
  1076. # Return False to mean "do it manually in ll_arraycopy".
  1077. return False
  1078. #
  1079. if source_hdr.tid & GCFLAG_CARDS_SET == 0:
  1080. # The source object has no young pointers at all. Done.
  1081. return True
  1082. #
  1083. if dest_hdr.tid & GCFLAG_HAS_CARDS == 0:
  1084. # The dest object doesn't have cards. Do it manually.
  1085. return False
  1086. #
  1087. if source_start != 0 or dest_start != 0:
  1088. # Misaligned. Do it manually.
  1089. return False
  1090. #
  1091. self.manually_copy_card_bits(source_addr, dest_addr, length)
  1092. return True
  1093. #
  1094. if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1095. # there might be in source a pointer to a young object
  1096. self.old_objects_pointing_to_young.append(dest_addr)
  1097. dest_hdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  1098. #
  1099. if dest_hdr.tid & GCFLAG_NO_HEAP_PTRS:
  1100. if source_hdr.tid & GCFLAG_NO_HEAP_PTRS == 0:
  1101. dest_hdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  1102. self.prebuilt_root_objects.append(dest_addr)
  1103. return True
  1104. def manually_copy_card_bits(self, source_addr, dest_addr, length):
  1105. # manually copy the individual card marks from source to dest
  1106. bytes = self.card_marking_bytes_for_length(length)
  1107. #
  1108. anybyte = 0
  1109. i = 0
  1110. while i < bytes:
  1111. addr_srcbyte = self.get_card(source_addr, i)
  1112. addr_dstbyte = self.get_card(dest_addr, i)
  1113. byte = ord(addr_srcbyte.char[0])
  1114. anybyte |= byte
  1115. addr_dstbyte.char[0] = chr(ord(addr_dstbyte.char[0]) | byte)
  1116. i += 1
  1117. #
  1118. if anybyte:
  1119. dest_hdr = self.header(dest_addr)
  1120. if dest_hdr.tid & GCFLAG_CARDS_SET == 0:
  1121. self.old_objects_with_cards_set.append(dest_addr)
  1122. dest_hdr.tid |= GCFLAG_CARDS_SET
  1123. # ----------
  1124. # Nursery collection
  1125. def minor_collection(self):
  1126. """Perform a minor collection: find the objects from the nursery
  1127. that remain alive and move them out."""
  1128. #
  1129. debug_start("gc-minor")
  1130. #
  1131. # Before everything else, remove from 'old_objects_pointing_to_young'
  1132. # the young arrays.
  1133. if self.young_rawmalloced_objects:
  1134. self.remove_young_arrays_from_old_objects_pointing_to_young()
  1135. #
  1136. # First, find the roots that point to young objects. All nursery
  1137. # objects found are copied out of the nursery, and the occasional
  1138. # young raw-malloced object is flagged with GCFLAG_VISITED.
  1139. # Note that during this step, we ignore references to further
  1140. # young objects; only objects directly referenced by roots
  1141. # are copied out or flagged. They are also added to the list
  1142. # 'old_objects_pointing_to_young'.
  1143. self.collect_roots_in_nursery()
  1144. #
  1145. while True:
  1146. # If we are using card marking, do a partial trace of the arrays
  1147. # that are flagged with GCFLAG_CARDS_SET.
  1148. if self.card_page_indices > 0:
  1149. self.collect_cardrefs_to_nursery()
  1150. #
  1151. # Now trace objects from 'old_objects_pointing_to_young'.
  1152. # All nursery objects they reference are copied out of the
  1153. # nursery, and again added to 'old_objects_pointing_to_young'.
  1154. # All young raw-malloced object found are flagged GCFLAG_VISITED.
  1155. # We proceed until 'old_objects_pointing_to_young' is empty.
  1156. self.collect_oldrefs_to_nursery()
  1157. #
  1158. # We have to loop back if collect_oldrefs_to_nursery caused
  1159. # new objects to show up in old_objects_with_cards_set
  1160. if self.card_page_indices > 0:
  1161. if self.old_objects_with_cards_set.non_empty():
  1162. continue
  1163. break
  1164. #
  1165. # Now all live nursery objects should be out. Update the young
  1166. # weakrefs' targets.
  1167. if self.young_objects_with_weakrefs.non_empty():
  1168. self.invalidate_young_weakrefs()
  1169. if self.young_objects_with_light_finalizers.non_empty():
  1170. self.deal_with_young_objects_with_finalizers()
  1171. #
  1172. # Clear this mapping.
  1173. if self.nursery_objects_shadows.length() > 0:
  1174. self.nursery_objects_shadows.clear()
  1175. #
  1176. # Walk the list of young raw-malloced objects, and either free
  1177. # them or make them old.
  1178. if self.young_rawmalloced_objects:
  1179. self.free_young_rawmalloced_objects()
  1180. #
  1181. # All live nursery objects are out, and the rest dies. Fill
  1182. # the whole nursery with zero and reset the current nursery pointer.
  1183. llarena.arena_reset(self.nursery, self.nursery_size, 2)
  1184. self.debug_rotate_nursery()
  1185. self.nursery_free = self.nursery
  1186. #
  1187. debug_print("minor collect, total memory used:",
  1188. self.get_total_memory_used())
  1189. if self.DEBUG >= 2:
  1190. self.debug_check_consistency() # expensive!
  1191. debug_stop("gc-minor")
  1192. def collect_roots_in_nursery(self):
  1193. # we don't need to trace prebuilt GcStructs during a minor collect:
  1194. # if a prebuilt GcStruct contains a pointer to a young object,
  1195. # then the write_barrier must have ensured that the prebuilt
  1196. # GcStruct is in the list self.old_objects_pointing_to_young.
  1197. debug_start("gc-minor-walkroots")
  1198. self.root_walker.walk_roots(
  1199. MiniMarkGC._trace_drag_out1, # stack roots
  1200. MiniMarkGC._trace_drag_out1, # static in prebuilt non-gc
  1201. None) # static in prebuilt gc
  1202. debug_stop("gc-minor-walkroots")
  1203. def collect_cardrefs_to_nursery(self):
  1204. size_gc_header = self.gcheaderbuilder.size_gc_header
  1205. oldlist = self.old_objects_with_cards_set
  1206. while oldlist.non_empty():
  1207. obj = oldlist.pop()
  1208. #
  1209. # Remove the GCFLAG_CARDS_SET flag.
  1210. ll_assert(self.header(obj).tid & GCFLAG_CARDS_SET != 0,
  1211. "!GCFLAG_CARDS_SET but object in 'old_objects_with_cards_set'")
  1212. self.header(obj).tid &= ~GCFLAG_CARDS_SET
  1213. #
  1214. # Get the number of card marker bytes in the header.
  1215. typeid = self.get_type_id(obj)
  1216. offset_to_length = self.varsize_offset_to_length(typeid)
  1217. length = (obj + offset_to_length).signed[0]
  1218. bytes = self.card_marking_bytes_for_length(length)
  1219. p = llarena.getfakearenaaddress(obj - size_gc_header)
  1220. #
  1221. # If the object doesn't have GCFLAG_TRACK_YOUNG_PTRS, then it
  1222. # means that it is in 'old_objects_pointing_to_young' and
  1223. # will be fully traced by collect_oldrefs_to_nursery() just
  1224. # afterwards.
  1225. if self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1226. #
  1227. # In that case, we just have to reset all card bits.
  1228. while bytes > 0:
  1229. p -= 1
  1230. p.char[0] = '\x00'
  1231. bytes -= 1
  1232. #
  1233. else:
  1234. # Walk the bytes encoding the card marker bits, and for
  1235. # each bit set, call trace_and_drag_out_of_nursery_partial().
  1236. interval_start = 0
  1237. while bytes > 0:
  1238. p -= 1
  1239. cardbyte = ord(p.char[0])
  1240. p.char[0] = '\x00' # reset the bits
  1241. bytes -= 1
  1242. next_byte_start = interval_start + 8*self.card_page_indices
  1243. #
  1244. while cardbyte != 0:
  1245. interval_stop = interval_start + self.card_page_indices
  1246. #
  1247. if cardbyte & 1:
  1248. if interval_stop > length:
  1249. interval_stop = length
  1250. ll_assert(cardbyte <= 1 and bytes == 0,
  1251. "premature end of object")
  1252. self.trace_and_drag_out_of_nursery_partial(
  1253. obj, interval_start, interval_stop)
  1254. #
  1255. interval_start = interval_stop
  1256. cardbyte >>= 1
  1257. interval_start = next_byte_start
  1258. def collect_oldrefs_to_nursery(self):
  1259. # Follow the old_objects_pointing_to_young list and move the
  1260. # young objects they point to out of the nursery.
  1261. oldlist = self.old_objects_pointing_to_young
  1262. while oldlist.non_empty():
  1263. obj = oldlist.pop()
  1264. #
  1265. # Check that the flags are correct: we must not have
  1266. # GCFLAG_TRACK_YOUNG_PTRS so far.
  1267. ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS == 0,
  1268. "old_objects_pointing_to_young contains obj with "
  1269. "GCFLAG_TRACK_YOUNG_PTRS")
  1270. #
  1271. # Add the flag GCFLAG_TRACK_YOUNG_PTRS. All live objects should
  1272. # have this flag set after a nursery collection.
  1273. self.header(obj).tid |= GCFLAG_TRACK_YOUNG_PTRS
  1274. #
  1275. # Trace the 'obj' to replace pointers to nursery with pointers
  1276. # outside the nursery, possibly forcing nursery objects out
  1277. # and adding them to 'old_objects_pointing_to_young' as well.
  1278. self.trace_and_drag_out_of_nursery(obj)
  1279. def trace_and_drag_out_of_nursery(self, obj):
  1280. """obj must not be in the nursery. This copies all the
  1281. young objects it references out of the nursery.
  1282. """
  1283. self.trace(obj, self._trace_drag_out, None)
  1284. def trace_and_drag_out_of_nursery_partial(self, obj, start, stop):
  1285. """Like trace_and_drag_out_of_nursery(), but limited to the array
  1286. indices in range(start, stop).
  1287. """
  1288. ll_assert(start < stop, "empty or negative range "
  1289. "in trace_and_drag_out_of_nursery_partial()")
  1290. #print 'trace_partial:', start, stop, '\t', obj
  1291. self.trace_partial(obj, start, stop, self._trace_drag_out, None)
  1292. def _trace_drag_out1(self, root):
  1293. self._trace_drag_out(root, None)
  1294. def _trace_drag_out(self, root, ignored):
  1295. obj = root.address[0]
  1296. #print '_trace_drag_out(%x: %r)' % (hash(obj.ptr._obj), obj)
  1297. #
  1298. # If 'obj' is not in the nursery, nothing to change -- expect
  1299. # that we must set GCFLAG_VISITED on young raw-malloced objects.
  1300. if not self.is_in_nursery(obj):
  1301. # cache usage trade-off: I think that it is a better idea to
  1302. # check if 'obj' is in young_rawmalloced_objects with an access
  1303. # to this (small) dictionary, rather than risk a lot of cache
  1304. # misses by reading a flag in the header of all the 'objs' that
  1305. # arrive here.
  1306. if (bool(self.young_rawmalloced_objects)
  1307. and self.young_rawmalloced_objects.contains(obj)):
  1308. self._visit_young_rawmalloced_object(obj)
  1309. return
  1310. #
  1311. size_gc_header = self.gcheaderbuilder.size_gc_header
  1312. if self.header(obj).tid & GCFLAG_HAS_SHADOW == 0:
  1313. #
  1314. # Common case: 'obj' was not already forwarded (otherwise
  1315. # tid == -42, containing all flags), and it doesn't have the
  1316. # HAS_SHADOW flag either. We must move it out of the nursery,
  1317. # into a new nonmovable location.
  1318. totalsize = size_gc_header + self.get_size(obj)
  1319. newhdr = self._malloc_out_of_nursery(totalsize)
  1320. #
  1321. elif self.is_forwarded(obj):
  1322. #
  1323. # 'obj' was already forwarded. Change the original reference
  1324. # to point to its forwarding address, and we're done.
  1325. root.address[0] = self.get_forwarding_address(obj)
  1326. return
  1327. #
  1328. else:
  1329. # First visit to an object that has already a shadow.
  1330. newobj = self.nursery_objects_shadows.get(obj)
  1331. ll_assert(newobj != NULL, "GCFLAG_HAS_SHADOW but no shadow found")
  1332. newhdr = newobj - size_gc_header
  1333. #
  1334. # Remove the flag GCFLAG_HAS_SHADOW, so that it doesn't get
  1335. # copied to the shadow itself.
  1336. self.header(obj).tid &= ~GCFLAG_HAS_SHADOW
  1337. #
  1338. totalsize = size_gc_header + self.get_size(obj)
  1339. #
  1340. # Copy it. Note that references to other objects in the
  1341. # nursery are kept unchanged in this step.
  1342. llmemory.raw_memcopy(obj - size_gc_header, newhdr, totalsize)
  1343. #
  1344. # Set the old object's tid to -42 (containing all flags) and
  1345. # replace the old object's content with the target address.
  1346. # A bit of no-ops to convince llarena that we are changing
  1347. # the layout, in non-translated versions.
  1348. obj = llarena.getfakearenaaddress(obj)
  1349. llarena.arena_reset(obj - size_gc_header, totalsize, 0)
  1350. llarena.arena_reserve(obj - size_gc_header,
  1351. size_gc_header + llmemory.sizeof(FORWARDSTUB))
  1352. self.header(obj).tid = -42
  1353. newobj = newhdr + size_gc_header
  1354. llmemory.cast_adr_to_ptr(obj, FORWARDSTUBPTR).forw = newobj
  1355. #
  1356. # Change the original pointer to this object.
  1357. root.address[0] = newobj
  1358. #
  1359. # Add the newobj to the list 'old_objects_pointing_to_young',
  1360. # because it can contain further pointers to other young objects.
  1361. # We will fix such references to point to the copy of the young
  1362. # objects when we walk 'old_objects_pointing_to_young'.
  1363. self.old_objects_pointing_to_young.append(newobj)
  1364. _trace_drag_out._always_inline_ = True
  1365. def _visit_young_rawmalloced_object(self, obj):
  1366. # 'obj' points to a young, raw-malloced object.
  1367. # Any young rawmalloced object never seen by the code here
  1368. # will end up without GCFLAG_VISITED, and be freed at the
  1369. # end of the current minor collection. Note that there was
  1370. # a bug in which dying young arrays with card marks would
  1371. # still be scanned before being freed, keeping a lot of
  1372. # objects unnecessarily alive.
  1373. hdr = self.header(obj)
  1374. if hdr.tid & GCFLAG_VISITED:
  1375. return
  1376. hdr.tid |= GCFLAG_VISITED
  1377. #
  1378. # we just made 'obj' old, so we need to add it to the correct lists
  1379. added_somewhere = False
  1380. #
  1381. if hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1382. self.old_objects_pointing_to_young.append(obj)
  1383. added_somewhere = True
  1384. #
  1385. if hdr.tid & GCFLAG_HAS_CARDS != 0:
  1386. ll_assert(hdr.tid & GCFLAG_CARDS_SET != 0,
  1387. "young array: GCFLAG_HAS_CARDS without GCFLAG_CARDS_SET")
  1388. self.old_objects_with_cards_set.append(obj)
  1389. added_somewhere = True
  1390. #
  1391. ll_assert(added_somewhere, "wrong flag combination on young array")
  1392. def _malloc_out_of_nursery(self, totalsize):
  1393. """Allocate non-movable memory for an object of the given
  1394. 'totalsize' that lives so far in the nursery."""
  1395. if raw_malloc_usage(totalsize) <= self.small_request_threshold:
  1396. # most common path
  1397. return self.ac.malloc(totalsize)
  1398. else:
  1399. # for nursery objects that are not small
  1400. return self._malloc_out_of_nursery_nonsmall(totalsize)
  1401. _malloc_out_of_nursery._always_inline_ = True
  1402. def _malloc_out_of_nursery_nonsmall(self, totalsize):
  1403. # 'totalsize' should be aligned.
  1404. ll_assert(raw_malloc_usage(totalsize) & (WORD-1) == 0,
  1405. "misaligned totalsize in _malloc_out_of_nursery_nonsmall")
  1406. #
  1407. arena = llarena.arena_malloc(raw_malloc_usage(totalsize), False)
  1408. if not arena:
  1409. raise MemoryError("cannot allocate object")
  1410. llarena.arena_reserve(arena, totalsize)
  1411. #
  1412. size_gc_header = self.gcheaderbuilder.size_gc_header
  1413. self.rawmalloced_total_size += r_uint(raw_malloc_usage(totalsize))
  1414. self.old_rawmalloced_objects.append(arena + size_gc_header)
  1415. return arena
  1416. def free_young_rawmalloced_objects(self):
  1417. self.young_rawmalloced_objects.foreach(
  1418. self._free_young_rawmalloced_obj, None)
  1419. self.young_rawmalloced_objects.delete()
  1420. self.young_rawmalloced_objects = self.null_address_dict()
  1421. def _free_young_rawmalloced_obj(self, obj, ignored1, ignored2):
  1422. # If 'obj' has GCFLAG_VISITED, it was seen by _trace_drag_out
  1423. # and survives. Otherwise, it dies.
  1424. self.free_rawmalloced_object_if_unvisited(obj)
  1425. def remove_young_arrays_from_old_objects_pointing_to_young(self):
  1426. old = self.old_objects_pointing_to_young
  1427. new = self.AddressStack()
  1428. while old.non_empty():
  1429. obj = old.pop()
  1430. if not self.young_rawmalloced_objects.contains(obj):
  1431. new.append(obj)
  1432. # an extra copy, to avoid assignments to
  1433. # 'self.old_objects_pointing_to_young'
  1434. while new.non_empty():
  1435. old.append(new.pop())
  1436. new.delete()
  1437. # ----------
  1438. # Full collection
  1439. def major_collection(self, reserving_size=0):
  1440. """Do a major collection. Only for when the nursery is empty."""
  1441. #
  1442. debug_start("gc-collect")
  1443. debug_print()
  1444. debug_print(".----------- Full collection ------------------")
  1445. debug_print("| used before collection:")
  1446. debug_print("| in ArenaCollection: ",
  1447. self.ac.total_memory_used, "bytes")
  1448. debug_print("| raw_malloced: ",
  1449. self.rawmalloced_total_size, "bytes")
  1450. #
  1451. # Debugging checks
  1452. ll_assert(self.nursery_free == self.nursery,
  1453. "nursery not empty in major_collection()")
  1454. self.debug_check_consistency()
  1455. #
  1456. # Note that a major collection is non-moving. The goal is only to
  1457. # find and free some of the objects allocated by the ArenaCollection.
  1458. # We first visit all objects and toggle the flag GCFLAG_VISITED on
  1459. # them, starting from the roots.
  1460. self.objects_to_trace = self.AddressStack()
  1461. self.collect_roots()
  1462. self.visit_all_objects()
  1463. #
  1464. # Finalizer support: adds the flag GCFLAG_VISITED to all objects
  1465. # with a finalizer and all objects reachable from there (and also
  1466. # moves some objects from 'objects_with_finalizers' to
  1467. # 'run_finalizers').
  1468. if self.objects_with_finalizers.non_empty():
  1469. self.deal_with_objects_with_finalizers()
  1470. #
  1471. self.objects_to_trace.delete()
  1472. #
  1473. # Weakref support: clear the weak pointers to dying objects
  1474. if self.old_objects_with_weakrefs.non_empty():
  1475. self.invalidate_old_weakrefs()
  1476. if self.old_objects_with_light_finalizers.non_empty():
  1477. self.deal_with_old_objects_with_finalizers()
  1478. #
  1479. # Walk all rawmalloced objects and free the ones that don't
  1480. # have the GCFLAG_VISITED flag.
  1481. self.free_unvisited_rawmalloc_objects()
  1482. #
  1483. # Ask the ArenaCollection to visit all objects. Free the ones
  1484. # that have not been visited above, and reset GCFLAG_VISITED on
  1485. # the others.
  1486. self.ac.mass_free(self._free_if_unvisited)
  1487. #
  1488. # We also need to reset the GCFLAG_VISITED on prebuilt GC objects.
  1489. self.prebuilt_root_objects.foreach(self._reset_gcflag_visited, None)
  1490. #
  1491. self.debug_check_consistency()
  1492. #
  1493. self.num_major_collects += 1
  1494. debug_print("| used after collection:")
  1495. debug_print("| in ArenaCollection: ",
  1496. self.ac.total_memory_used, "bytes")
  1497. debug_print("| raw_malloced: ",
  1498. self.rawmalloced_total_size, "bytes")
  1499. debug_print("| number of major collects: ",
  1500. self.num_major_collects)
  1501. debug_print("`----------------------------------------------")
  1502. debug_stop("gc-collect")
  1503. #
  1504. # Set the threshold for the next major collection to be when we
  1505. # have allocated 'major_collection_threshold' times more than
  1506. # we currently have -- but no more than 'max_delta' more than
  1507. # we currently have.
  1508. total_memory_used = float(self.get_total_memory_used())
  1509. bounded = self.set_major_threshold_from(
  1510. min(total_memory_used * self.major_collection_threshold,
  1511. total_memory_used + self.max_delta),
  1512. reserving_size)
  1513. #
  1514. # Max heap size: gives an upper bound on the threshold. If we
  1515. # already have at least this much allocated, raise MemoryError.
  1516. if bounded and (float(self.get_total_memory_used()) + reserving_size >=
  1517. self.next_major_collection_initial):
  1518. #
  1519. # First raise MemoryError, giving the program a chance to
  1520. # quit cleanly. It might still allocate in the nursery,
  1521. # which might eventually be emptied, triggering another
  1522. # major collect and (possibly) reaching here again with an
  1523. # even higher memory consumption. To prevent it, if it's
  1524. # the second time we are here, then abort the program.
  1525. if self.max_heap_size_already_raised:
  1526. llop.debug_fatalerror(lltype.Void,
  1527. "Using too much memory, aborting")
  1528. self.max_heap_size_already_raised = True
  1529. raise MemoryError
  1530. #
  1531. # At the end, we can execute the finalizers of the objects
  1532. # listed in 'run_finalizers'. Note that this will typically do
  1533. # more allocations.
  1534. self.execute_finalizers()
  1535. def _free_if_unvisited(self, hdr):
  1536. size_gc_header = self.gcheaderbuilder.size_gc_header
  1537. obj = hdr + size_gc_header
  1538. if self.header(obj).tid & GCFLAG_VISITED:
  1539. self.header(obj).tid &= ~GCFLAG_VISITED
  1540. return False # survives
  1541. return True # dies
  1542. def _reset_gcflag_visited(self, obj, ignored):
  1543. self.header(obj).tid &= ~GCFLAG_VISITED
  1544. def free_rawmalloced_object_if_unvisited(self, obj):
  1545. if self.header(obj).tid & GCFLAG_VISITED:
  1546. self.header(obj).tid &= ~GCFLAG_VISITED # survives
  1547. self.old_rawmalloced_objects.append(obj)
  1548. else:
  1549. size_gc_header = self.gcheaderbuilder.size_gc_header
  1550. totalsize = size_gc_header + self.get_size(obj)
  1551. allocsize = raw_malloc_usage(totalsize)
  1552. arena = llarena.getfakearenaaddress(obj - size_gc_header)
  1553. #
  1554. # Must also include the card marker area, if any
  1555. if (self.card_page_indices > 0 # <- this is constant-folded
  1556. and self.header(obj).tid & GCFLAG_HAS_CARDS):
  1557. #
  1558. # Get the length and compute the number of extra bytes
  1559. typeid = self.get_type_id(obj)
  1560. ll_assert(self.has_gcptr_in_varsize(typeid),
  1561. "GCFLAG_HAS_CARDS but not has_gcptr_in_varsize")
  1562. offset_to_length = self.varsize_offset_to_length(typeid)
  1563. length = (obj + offset_to_length).signed[0]
  1564. extra_words = self.card_marking_words_for_length(length)
  1565. arena -= extra_words * WORD
  1566. allocsize += extra_words * WORD
  1567. #
  1568. llarena.arena_free(arena)
  1569. self.rawmalloced_total_size -= r_uint(allocsize)
  1570. def free_unvisited_rawmalloc_objects(self):
  1571. list = self.old_rawmalloced_objects
  1572. self.old_rawmalloced_objects = self.AddressStack()
  1573. #
  1574. while list.non_empty():
  1575. self.free_rawmalloced_object_if_unvisited(list.pop())
  1576. #
  1577. list.delete()
  1578. def collect_roots(self):
  1579. # Collect all roots. Starts from all the objects
  1580. # from 'prebuilt_root_objects'.
  1581. self.prebuilt_root_objects.foreach(self._collect_obj,
  1582. self.objects_to_trace)
  1583. #
  1584. # Add the roots from the other sources.
  1585. self.root_walker.walk_roots(
  1586. MiniMarkGC._collect_ref_stk, # stack roots
  1587. MiniMarkGC._collect_ref_stk, # static in prebuilt non-gc structures
  1588. None) # we don't need the static in all prebuilt gc objects
  1589. #
  1590. # If we are in an inner collection caused by a call to a finalizer,
  1591. # the 'run_finalizers' objects also need to be kept alive.
  1592. self.run_finalizers.foreach(self._collect_obj,
  1593. self.objects_to_trace)
  1594. def enumerate_all_roots(self, callback, arg):
  1595. self.prebuilt_root_objects.foreach(callback, arg)
  1596. MovingGCBase.enumerate_all_roots(self, callback, arg)
  1597. enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)'
  1598. @staticmethod
  1599. def _collect_obj(obj, objects_to_trace):
  1600. objects_to_trace.append(obj)
  1601. def _collect_ref_stk(self, root):
  1602. obj = root.address[0]
  1603. llop.debug_nonnull_pointer(lltype.Void, obj)
  1604. self.objects_to_trace.append(obj)
  1605. def _collect_ref_rec(self, root, ignored):
  1606. self.objects_to_trace.append(root.address[0])
  1607. def visit_all_objects(self):
  1608. pending = self.objects_to_trace
  1609. while pending.non_empty():
  1610. obj = pending.pop()
  1611. self.visit(obj)
  1612. def visit(self, obj):
  1613. #
  1614. # 'obj' is a live object. Check GCFLAG_VISITED to know if we
  1615. # have already seen it before.
  1616. #
  1617. # Moreover, we can ignore prebuilt objects with GCFLAG_NO_HEAP_PTRS.
  1618. # If they have this flag set, then they cannot point to heap
  1619. # objects, so ignoring them is fine. If they don't have this
  1620. # flag set, then the object should be in 'prebuilt_root_objects',
  1621. # and the GCFLAG_VISITED will be reset at the end of the
  1622. # collection.
  1623. hdr = self.header(obj)
  1624. if hdr.tid & (GCFLAG_VISITED | GCFLAG_NO_HEAP_PTRS):
  1625. return
  1626. #
  1627. # It's the first time. We set the flag.
  1628. hdr.tid |= GCFLAG_VISITED
  1629. #
  1630. # Trace the content of the object and put all objects it references
  1631. # into the 'objects_to_trace' list.
  1632. self.trace(obj, self._collect_ref_rec, None)
  1633. # ----------
  1634. # id() and identityhash() support
  1635. def id_or_identityhash(self, gcobj, is_hash):
  1636. """Implement the common logic of id() and identityhash()
  1637. of an object, given as a GCREF.
  1638. """
  1639. obj = llmemory.cast_ptr_to_adr(gcobj)
  1640. #
  1641. if self.is_valid_gc_object(obj):
  1642. if self.is_in_nursery(obj):
  1643. #
  1644. # The object is not a tagged pointer, and it is still in the
  1645. # nursery. Find or allocate a "shadow" object, which is
  1646. # where the object will be moved by the next minor
  1647. # collection
  1648. if self.header(obj).tid & GCFLAG_HAS_SHADOW:
  1649. shadow = self.nursery_objects_shadows.get(obj)
  1650. ll_assert(shadow != NULL,
  1651. "GCFLAG_HAS_SHADOW but no shadow found")
  1652. else:
  1653. size_gc_header = self.gcheaderbuilder.size_gc_header
  1654. size = self.get_size(obj)
  1655. shadowhdr = self._malloc_out_of_nursery(size_gc_header +
  1656. size)
  1657. # Initialize the shadow enough to be considered a
  1658. # valid gc object. If the original object stays
  1659. # alive at the next minor collection, it will anyway
  1660. # be copied over the shadow and overwrite the
  1661. # following fields. But if the object dies, then
  1662. # the shadow will stay around and only be freed at
  1663. # the next major collection, at which point we want
  1664. # it to look valid (but ready to be freed).
  1665. shadow = shadowhdr + size_gc_header
  1666. self.header(shadow).tid = self.header(obj).tid
  1667. typeid = self.get_type_id(obj)
  1668. if self.is_varsize(typeid):
  1669. lenofs = self.varsize_offset_to_length(typeid)
  1670. (shadow + lenofs).signed[0] = (obj + lenofs).signed[0]
  1671. #
  1672. self.header(obj).tid |= GCFLAG_HAS_SHADOW
  1673. self.nursery_objects_shadows.setitem(obj, shadow)
  1674. #
  1675. # The answer is the address of the shadow.
  1676. obj = shadow
  1677. #
  1678. elif is_hash:
  1679. if self.header(obj).tid & GCFLAG_HAS_SHADOW:
  1680. #
  1681. # For identityhash(), we need a special case for some
  1682. # prebuilt objects: their hash must be the same before
  1683. # and after translation. It is stored as an extra word
  1684. # after the object. But we cannot use it for id()
  1685. # because the stored value might clash with a real one.
  1686. size = self.get_size(obj)
  1687. i = (obj + size).signed[0]
  1688. # Important: the returned value is not mangle_hash()ed!
  1689. return i
  1690. #
  1691. i = llmemory.cast_adr_to_int(obj)
  1692. if is_hash:
  1693. i = mangle_hash(i)
  1694. return i
  1695. def id(self, gcobj):
  1696. return self.id_or_identityhash(gcobj, False)
  1697. def identityhash(self, gcobj):
  1698. return self.id_or_identityhash(gcobj, True)
  1699. # ----------
  1700. # Finalizers
  1701. def deal_with_young_objects_with_finalizers(self):
  1702. """ This is a much simpler version of dealing with finalizers
  1703. and an optimization - we can reasonably assume that those finalizers
  1704. don't do anything fancy and *just* call them. Among other things
  1705. they won't resurrect objects
  1706. """
  1707. while self.young_objects_with_light_finalizers.non_empty():
  1708. obj = self.young_objects_with_light_finalizers.pop()
  1709. if not self.is_forwarded(obj):
  1710. finalizer = self.getlightfinalizer(self.get_type_id(obj))
  1711. ll_assert(bool(finalizer), "no light finalizer found")
  1712. finalizer(obj, llmemory.NULL)
  1713. else:
  1714. obj = self.get_forwarding_address(obj)
  1715. self.old_objects_with_light_finalizers.append(obj)
  1716. def deal_with_old_objects_with_finalizers(self):
  1717. """ This is a much simpler version of dealing with finalizers
  1718. and an optimization - we can reasonably assume that those finalizers
  1719. don't do anything fancy and *just* call them. Among other things
  1720. they won't resurrect objects
  1721. """
  1722. new_objects = self.AddressStack()
  1723. while self.old_objects_with_light_finalizers.non_empty():
  1724. obj = self.old_objects_with_light_finalizers.pop()
  1725. if self.header(obj).tid & GCFLAG_VISITED:
  1726. # surviving
  1727. new_objects.append(obj)
  1728. else:
  1729. # dying
  1730. finalizer = self.getlightfinalizer(self.get_type_id(obj))
  1731. ll_assert(bool(finalizer), "no light finalizer found")
  1732. finalizer(obj, llmemory.NULL)
  1733. self.old_objects_with_light_finalizers.delete()
  1734. self.old_objects_with_light_finalizers = new_objects
  1735. def deal_with_objects_with_finalizers(self):
  1736. # Walk over list of objects with finalizers.
  1737. # If it is not surviving, add it to the list of to-be-called
  1738. # finalizers and make it survive, to make the finalizer runnable.
  1739. # We try to run the finalizers in a "reasonable" order, like
  1740. # CPython does. The details of this algorithm are in
  1741. # pypy/doc/discussion/finalizer-order.txt.
  1742. new_with_finalizer = self.AddressDeque()
  1743. marked = self.AddressDeque()
  1744. pending = self.AddressStack()
  1745. self.tmpstack = self.AddressStack()
  1746. while self.objects_with_finalizers.non_empty():
  1747. x = self.objects_with_finalizers.popleft()
  1748. ll_assert(self._finalization_state(x) != 1,
  1749. "bad finalization state 1")
  1750. if self.header(x).tid & GCFLAG_VISITED:
  1751. new_with_finalizer.append(x)
  1752. continue
  1753. marked.append(x)
  1754. pending.append(x)
  1755. while pending.non_empty():
  1756. y = pending.pop()
  1757. state = self._finalization_state(y)
  1758. if state == 0:
  1759. self._bump_finalization_state_from_0_to_1(y)
  1760. self.trace(y, self._append_if_nonnull, pending)
  1761. elif state == 2:
  1762. self._recursively_bump_finalization_state_from_2_to_3(y)
  1763. self._recursively_bump_finalization_state_from_1_to_2(x)
  1764. while marked.non_empty():
  1765. x = marked.popleft()
  1766. state = self._finalization_state(x)
  1767. ll_assert(state >= 2, "unexpected finalization state < 2")
  1768. if state == 2:
  1769. self.run_finalizers.append(x)
  1770. # we must also fix the state from 2 to 3 here, otherwise
  1771. # we leave the GCFLAG_FINALIZATION_ORDERING bit behind
  1772. # which will confuse the next collection
  1773. self._recursively_bump_finalization_state_from_2_to_3(x)
  1774. else:
  1775. new_with_finalizer.append(x)
  1776. self.tmpstack.delete()
  1777. pending.delete()
  1778. marked.delete()
  1779. self.objects_with_finalizers.delete()
  1780. self.objects_with_finalizers = new_with_finalizer
  1781. def _append_if_nonnull(pointer, stack):
  1782. stack.append(pointer.address[0])
  1783. _append_if_nonnull = staticmethod(_append_if_nonnull)
  1784. def _finalization_state(self, obj):
  1785. tid = self.header(obj).tid
  1786. if tid & GCFLAG_VISITED:
  1787. if tid & GCFLAG_FINALIZATION_ORDERING:
  1788. return 2
  1789. else:
  1790. return 3
  1791. else:
  1792. if tid & GCFLAG_FINALIZATION_ORDERING:
  1793. return 1
  1794. else:
  1795. return 0
  1796. def _bump_finalization_state_from_0_to_1(self, obj):
  1797. ll_assert(self._finalization_state(obj) == 0,
  1798. "unexpected finalization state != 0")
  1799. hdr = self.header(obj)
  1800. hdr.tid |= GCFLAG_FINALIZATION_ORDERING
  1801. def _recursively_bump_finalization_state_from_2_to_3(self, obj):
  1802. ll_assert(self._finalization_state(obj) == 2,
  1803. "unexpected finalization state != 2")
  1804. pending = self.tmpstack
  1805. ll_assert(not pending.non_empty(), "tmpstack not empty")
  1806. pending.append(obj)
  1807. while pending.non_empty():
  1808. y = pending.pop()
  1809. hdr = self.header(y)
  1810. if hdr.tid & GCFLAG_FINALIZATION_ORDERING: # state 2 ?
  1811. hdr.tid &= ~GCFLAG_FINALIZATION_ORDERING # change to state 3
  1812. self.trace(y, self._append_if_nonnull, pending)
  1813. def _recursively_bump_finalization_state_from_1_to_2(self, obj):
  1814. # recursively convert objects from state 1 to state 2.
  1815. # The call to visit_all_objects() will add the GCFLAG_VISITED
  1816. # recursively.
  1817. self.objects_to_trace.append(obj)
  1818. self.visit_all_objects()
  1819. # ----------
  1820. # Weakrefs
  1821. # The code relies on the fact that no weakref can be an old object
  1822. # weakly pointing to a young object. Indeed, weakrefs are immutable
  1823. # so they cannot point to an object that was created after it.
  1824. def invalidate_young_weakrefs(self):
  1825. """Called during a nursery collection."""
  1826. # walk over the list of objects that contain weakrefs and are in the
  1827. # nursery. if the object it references survives then update the
  1828. # weakref; otherwise invalidate the weakref
  1829. while self.young_objects_with_weakrefs.non_empty():
  1830. obj = self.young_objects_with_weakrefs.pop()
  1831. if not self.is_forwarded(obj):
  1832. continue # weakref itself dies
  1833. obj = self.get_forwarding_address(obj)
  1834. offset = self.weakpointer_offset(self.get_type_id(obj))
  1835. pointing_to = (obj + offset).address[0]
  1836. if self.is_in_nursery(pointing_to):
  1837. if self.is_forwarded(pointing_to):
  1838. (obj + offset).address[0] = self.get_forwarding_address(
  1839. pointing_to)
  1840. else:
  1841. (obj + offset).address[0] = llmemory.NULL
  1842. continue # no need to remember this weakref any longer
  1843. #
  1844. elif (bool(self.young_rawmalloced_objects) and
  1845. self.young_rawmalloced_objects.contains(pointing_to)):
  1846. # young weakref to a young raw-malloced object
  1847. if self.header(pointing_to).tid & GCFLAG_VISITED:
  1848. pass # survives, but does not move
  1849. else:
  1850. (obj + offset).address[0] = llmemory.NULL
  1851. continue # no need to remember this weakref any longer
  1852. #
  1853. self.old_objects_with_weakrefs.append(obj)
  1854. def invalidate_old_weakrefs(self):
  1855. """Called during a major collection."""
  1856. # walk over list of objects that contain weakrefs
  1857. # if the object it references does not survive, invalidate the weakref
  1858. new_with_weakref = self.AddressStack()
  1859. while self.old_objects_with_weakrefs.non_empty():
  1860. obj = self.old_objects_with_weakrefs.pop()
  1861. if self.header(obj).tid & GCFLAG_VISITED == 0:
  1862. continue # weakref itself dies
  1863. offset = self.weakpointer_offset(self.get_type_id(obj))
  1864. pointing_to = (obj + offset).address[0]
  1865. if self.header(pointing_to).tid & GCFLAG_VISITED:
  1866. new_with_weakref.append(obj)
  1867. else:
  1868. (obj + offset).address[0] = llmemory.NULL
  1869. self.old_objects_with_weakrefs.delete()
  1870. self.old_objects_with_weakrefs = new_with_weakref
  1871. # ____________________________________________________________
  1872. # For testing, a simple implementation of ArenaCollection.
  1873. # This version could be used together with obmalloc.c, but
  1874. # it requires an extra word per object in the 'all_objects'
  1875. # list.
  1876. class SimpleArenaCollection(object):
  1877. def __init__(self, arena_size, page_size, small_request_threshold):
  1878. self.arena_size = arena_size # ignored
  1879. self.page_size = page_size
  1880. self.small_request_threshold = small_request_threshold
  1881. self.all_objects = []
  1882. self.total_memory_used = 0
  1883. def malloc(self, size):
  1884. nsize = raw_malloc_usage(size)
  1885. ll_assert(nsize > 0, "malloc: size is null or negative")
  1886. ll_assert(nsize <= self.small_request_threshold,"malloc: size too big")
  1887. ll_assert((nsize & (WORD-1)) == 0, "malloc: size is not aligned")
  1888. #
  1889. result = llarena.arena_malloc(nsize, False)
  1890. llarena.arena_reserve(result, size)
  1891. self.all_objects.append((result, nsize))
  1892. self.total_memory_used += nsize
  1893. return result
  1894. def mass_free(self, ok_to_free_func):
  1895. objs = self.all_objects
  1896. self.all_objects = []
  1897. self.total_memory_used = 0
  1898. for rawobj, nsize in objs:
  1899. if ok_to_free_func(rawobj):
  1900. llarena.arena_free(rawobj)
  1901. else:
  1902. self.all_objects.append((rawobj, nsize))
  1903. self.total_memory_used += nsize