PageRenderTime 58ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/rpython/memory/gc/incminimark.py

https://bitbucket.org/pypy/pypy/
Python | 3111 lines | 2202 code | 146 blank | 763 comment | 207 complexity | e029fbba75bdd25239b5ec74432415f0 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. """Incremental version of the MiniMark GC.
  2. Environment variables can be used to fine-tune the following parameters:
  3. PYPY_GC_NURSERY The nursery size. Defaults to 1/2 of your cache or
  4. '4M'. Small values
  5. (like 1 or 1KB) are useful for debugging.
  6. PYPY_GC_NURSERY_DEBUG If set to non-zero, will fill nursery with garbage,
  7. to help debugging.
  8. PYPY_GC_INCREMENT_STEP The size of memory marked during the marking step.
  9. Default is size of nursery * 2. If you mark it too high
  10. your GC is not incremental at all. The minimum is set
  11. to size that survives minor collection * 1.5 so we
  12. reclaim anything all the time.
  13. PYPY_GC_MAJOR_COLLECT Major collection memory factor. Default is '1.82',
  14. which means trigger a major collection when the
  15. memory consumed equals 1.82 times the memory
  16. really used at the end of the previous major
  17. collection.
  18. PYPY_GC_GROWTH Major collection threshold's max growth rate.
  19. Default is '1.4'. Useful to collect more often
  20. than normally on sudden memory growth, e.g. when
  21. there is a temporary peak in memory usage.
  22. PYPY_GC_MAX The max heap size. If coming near this limit, it
  23. will first collect more often, then raise an
  24. RPython MemoryError, and if that is not enough,
  25. crash the program with a fatal error. Try values
  26. like '1.6GB'.
  27. PYPY_GC_MAX_DELTA The major collection threshold will never be set
  28. to more than PYPY_GC_MAX_DELTA the amount really
  29. used after a collection. Defaults to 1/8th of the
  30. total RAM size (which is constrained to be at most
  31. 2/3/4GB on 32-bit systems). Try values like '200MB'.
  32. PYPY_GC_MIN Don't collect while the memory size is below this
  33. limit. Useful to avoid spending all the time in
  34. the GC in very small programs. Defaults to 8
  35. times the nursery.
  36. PYPY_GC_DEBUG Enable extra checks around collections that are
  37. too slow for normal use. Values are 0 (off),
  38. 1 (on major collections) or 2 (also on minor
  39. collections).
  40. PYPY_GC_MAX_PINNED The maximal number of pinned objects at any point
  41. in time. Defaults to a conservative value depending
  42. on nursery size and maximum object size inside the
  43. nursery. Useful for debugging by setting it to 0.
  44. """
  45. # XXX Should find a way to bound the major collection threshold by the
  46. # XXX total addressable size. Maybe by keeping some minimarkpage arenas
  47. # XXX pre-reserved, enough for a few nursery collections? What about
  48. # XXX raw-malloced memory?
  49. # XXX try merging old_objects_pointing_to_pinned into
  50. # XXX old_objects_pointing_to_young (IRC 2014-10-22, fijal and gregor_w)
  51. import sys
  52. import os
  53. from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, llgroup
  54. from rpython.rtyper.lltypesystem.lloperation import llop
  55. from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage
  56. from rpython.memory.gc.base import GCBase, MovingGCBase
  57. from rpython.memory.gc import env
  58. from rpython.memory.support import mangle_hash
  59. from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
  60. from rpython.rlib.rarithmetic import LONG_BIT_SHIFT
  61. from rpython.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
  62. from rpython.rlib.objectmodel import specialize
  63. from rpython.memory.gc.minimarkpage import out_of_memory
  64. #
  65. # Handles the objects in 2 generations:
  66. #
  67. # * young objects: allocated in the nursery if they are not too large, or
  68. # raw-malloced otherwise. The nursery is a fixed-size memory buffer of
  69. # 4MB by default. When full, we do a minor collection;
  70. # - surviving objects from the nursery are moved outside and become old,
  71. # - non-surviving raw-malloced objects are freed,
  72. # - and pinned objects are kept at their place inside the nursery and stay
  73. # young.
  74. #
  75. # * old objects: never move again. These objects are either allocated by
  76. # minimarkpage.py (if they are small), or raw-malloced (if they are not
  77. # small). Collected by regular mark-n-sweep during major collections.
  78. #
  79. WORD = LONG_BIT // 8
  80. first_gcflag = 1 << (LONG_BIT//2)
  81. # The following flag is set on objects if we need to do something to
  82. # track the young pointers that it might contain. The flag is not set
  83. # on young objects (unless they are large arrays, see below), and we
  84. # simply assume that any young object can point to any other young object.
  85. # For old and prebuilt objects, the flag is usually set, and is cleared
  86. # when we write any pointer to it. For large arrays with
  87. # GCFLAG_HAS_CARDS, we rely on card marking to track where the
  88. # young pointers are; the flag GCFLAG_TRACK_YOUNG_PTRS is set in this
  89. # case too, to speed up the write barrier.
  90. GCFLAG_TRACK_YOUNG_PTRS = first_gcflag << 0
  91. # The following flag is set on some prebuilt objects. The flag is set
  92. # unless the object is already listed in 'prebuilt_root_objects'.
  93. # When a pointer is written inside an object with GCFLAG_NO_HEAP_PTRS
  94. # set, the write_barrier clears the flag and adds the object to
  95. # 'prebuilt_root_objects'.
  96. GCFLAG_NO_HEAP_PTRS = first_gcflag << 1
  97. # The following flag is set on surviving objects during a major collection.
  98. GCFLAG_VISITED = first_gcflag << 2
  99. # The following flag is set on nursery objects of which we asked the id
  100. # or the identityhash. It means that a space of the size of the object
  101. # has already been allocated in the nonmovable part. The same flag is
  102. # abused to mark prebuilt objects whose hash has been taken during
  103. # translation and is statically recorded.
  104. GCFLAG_HAS_SHADOW = first_gcflag << 3
  105. # The following flag is set temporarily on some objects during a major
  106. # collection. See pypy/doc/discussion/finalizer-order.txt
  107. GCFLAG_FINALIZATION_ORDERING = first_gcflag << 4
  108. # This flag is reserved for RPython.
  109. GCFLAG_EXTRA = first_gcflag << 5
  110. # The following flag is set on externally raw_malloc'ed arrays of pointers.
  111. # They are allocated with some extra space in front of them for a bitfield,
  112. # one bit per 'card_page_indices' indices.
  113. GCFLAG_HAS_CARDS = first_gcflag << 6
  114. GCFLAG_CARDS_SET = first_gcflag << 7 # <- at least one card bit is set
  115. # note that GCFLAG_CARDS_SET is the most significant bit of a byte:
  116. # this is required for the JIT (x86)
  117. # The following flag is set on surviving raw-malloced young objects during
  118. # a minor collection.
  119. GCFLAG_VISITED_RMY = first_gcflag << 8
  120. # The following flag is set on nursery objects to keep them in the nursery.
  121. # This means that a young object with this flag is not moved out
  122. # of the nursery during a minor collection. See pin()/unpin() for further
  123. # details.
  124. GCFLAG_PINNED = first_gcflag << 9
  125. # The following flag is set only on objects outside the nursery
  126. # (i.e. old objects). Therefore we can reuse GCFLAG_PINNED as it is used for
  127. # the same feature (object pinning) and GCFLAG_PINNED is only used on nursery
  128. # objects.
  129. # If this flag is set, the flagged object is already an element of
  130. # 'old_objects_pointing_to_pinned' and doesn't have to be added again.
  131. GCFLAG_PINNED_OBJECT_PARENT_KNOWN = GCFLAG_PINNED
  132. _GCFLAG_FIRST_UNUSED = first_gcflag << 10 # the first unused bit
  133. # States for the incremental GC
  134. # The scanning phase, next step call will scan the current roots
  135. # This state must complete in a single step
  136. STATE_SCANNING = 0
  137. # The marking phase. We walk the list 'objects_to_trace' of all gray objects
  138. # and mark all of the things they point to gray. This step lasts until there
  139. # are no more gray objects. ('objects_to_trace' never contains pinned objs.)
  140. STATE_MARKING = 1
  141. # here we kill all the unvisited objects
  142. STATE_SWEEPING = 2
  143. # here we call all the finalizers
  144. STATE_FINALIZING = 3
  145. GC_STATES = ['SCANNING', 'MARKING', 'SWEEPING', 'FINALIZING']
  146. FORWARDSTUB = lltype.GcStruct('forwarding_stub',
  147. ('forw', llmemory.Address))
  148. FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
  149. NURSARRAY = lltype.Array(llmemory.Address)
  150. # ____________________________________________________________
  151. class IncrementalMiniMarkGC(MovingGCBase):
  152. _alloc_flavor_ = "raw"
  153. inline_simple_malloc = True
  154. inline_simple_malloc_varsize = True
  155. needs_write_barrier = True
  156. prebuilt_gc_objects_are_static_roots = False
  157. can_usually_pin_objects = True
  158. malloc_zero_filled = False
  159. gcflag_extra = GCFLAG_EXTRA
  160. # All objects start with a HDR, i.e. with a field 'tid' which contains
  161. # a word. This word is divided in two halves: the lower half contains
  162. # the typeid, and the upper half contains various flags, as defined
  163. # by GCFLAG_xxx above.
  164. HDR = lltype.Struct('header', ('tid', lltype.Signed))
  165. typeid_is_in_field = 'tid'
  166. withhash_flag_is_in_field = 'tid', GCFLAG_HAS_SHADOW
  167. # ^^^ prebuilt objects may have the flag GCFLAG_HAS_SHADOW;
  168. # then they are one word longer, the extra word storing the hash.
  169. # During a minor collection, the objects in the nursery that are
  170. # moved outside are changed in-place: their header is replaced with
  171. # the value -42, and the following word is set to the address of
  172. # where the object was moved. This means that all objects in the
  173. # nursery need to be at least 2 words long, but objects outside the
  174. # nursery don't need to.
  175. minimal_size_in_nursery = (
  176. llmemory.sizeof(HDR) + llmemory.sizeof(llmemory.Address))
  177. TRANSLATION_PARAMS = {
  178. # Automatically adjust the size of the nursery and the
  179. # 'major_collection_threshold' from the environment.
  180. # See docstring at the start of the file.
  181. "read_from_env": True,
  182. # The size of the nursery. Note that this is only used as a
  183. # fall-back number.
  184. "nursery_size": 896*1024,
  185. # The system page size. Like malloc, we assume that it is 4K
  186. # for 32-bit systems; unlike malloc, we assume that it is 8K
  187. # for 64-bit systems, for consistent results.
  188. "page_size": 1024*WORD,
  189. # The size of an arena. Arenas are groups of pages allocated
  190. # together.
  191. "arena_size": 65536*WORD,
  192. # The maximum size of an object allocated compactly. All objects
  193. # that are larger are just allocated with raw_malloc(). Note that
  194. # the size limit for being first allocated in the nursery is much
  195. # larger; see below.
  196. "small_request_threshold": 35*WORD,
  197. # Full collection threshold: after a major collection, we record
  198. # the total size consumed; and after every minor collection, if the
  199. # total size is now more than 'major_collection_threshold' times,
  200. # we trigger the next major collection.
  201. "major_collection_threshold": 1.82,
  202. # Threshold to avoid that the total heap size grows by a factor of
  203. # major_collection_threshold at every collection: it can only
  204. # grow at most by the following factor from one collection to the
  205. # next. Used e.g. when there is a sudden, temporary peak in memory
  206. # usage; this avoids that the upper bound grows too fast.
  207. "growth_rate_max": 1.4,
  208. # The number of array indices that are mapped to a single bit in
  209. # write_barrier_from_array(). Must be a power of two. The default
  210. # value of 128 means that card pages are 512 bytes (1024 on 64-bits)
  211. # in regular arrays of pointers; more in arrays whose items are
  212. # larger. A value of 0 disables card marking.
  213. "card_page_indices": 128,
  214. # Objects whose total size is at least 'large_object' bytes are
  215. # allocated out of the nursery immediately, as old objects. The
  216. # minimal allocated size of the nursery is 2x the following
  217. # number (by default, at least 132KB on 32-bit and 264KB on 64-bit).
  218. "large_object": (16384+512)*WORD,
  219. }
  220. def __init__(self, config,
  221. read_from_env=False,
  222. nursery_size=32*WORD,
  223. nursery_cleanup=9*WORD,
  224. page_size=16*WORD,
  225. arena_size=64*WORD,
  226. small_request_threshold=5*WORD,
  227. major_collection_threshold=2.5,
  228. growth_rate_max=2.5, # for tests
  229. card_page_indices=0,
  230. large_object=8*WORD,
  231. ArenaCollectionClass=None,
  232. **kwds):
  233. "NOT_RPYTHON"
  234. MovingGCBase.__init__(self, config, **kwds)
  235. assert small_request_threshold % WORD == 0
  236. self.read_from_env = read_from_env
  237. self.nursery_size = nursery_size
  238. self.small_request_threshold = small_request_threshold
  239. self.major_collection_threshold = major_collection_threshold
  240. self.growth_rate_max = growth_rate_max
  241. self.num_major_collects = 0
  242. self.min_heap_size = 0.0
  243. self.max_heap_size = 0.0
  244. self.max_heap_size_already_raised = False
  245. self.max_delta = float(r_uint(-1))
  246. self.max_number_of_pinned_objects = 0 # computed later
  247. #
  248. self.card_page_indices = card_page_indices
  249. if self.card_page_indices > 0:
  250. self.card_page_shift = 0
  251. while (1 << self.card_page_shift) < self.card_page_indices:
  252. self.card_page_shift += 1
  253. #
  254. # 'large_object' limit how big objects can be in the nursery, so
  255. # it gives a lower bound on the allowed size of the nursery.
  256. self.nonlarge_max = large_object - 1
  257. #
  258. self.nursery = llmemory.NULL
  259. self.nursery_free = llmemory.NULL
  260. self.nursery_top = llmemory.NULL
  261. self.debug_tiny_nursery = -1
  262. self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY)
  263. self.extra_threshold = 0
  264. #
  265. # The ArenaCollection() handles the nonmovable objects allocation.
  266. if ArenaCollectionClass is None:
  267. from rpython.memory.gc import minimarkpage
  268. ArenaCollectionClass = minimarkpage.ArenaCollection
  269. self.ac = ArenaCollectionClass(arena_size, page_size,
  270. small_request_threshold)
  271. #
  272. # Used by minor collection: a list of (mostly non-young) objects that
  273. # (may) contain a pointer to a young object. Populated by
  274. # the write barrier: when we clear GCFLAG_TRACK_YOUNG_PTRS, we
  275. # add it to this list.
  276. # Note that young array objects may (by temporary "mistake") be added
  277. # to this list, but will be removed again at the start of the next
  278. # minor collection.
  279. self.old_objects_pointing_to_young = self.AddressStack()
  280. #
  281. # Similar to 'old_objects_pointing_to_young', but lists objects
  282. # that have the GCFLAG_CARDS_SET bit. For large arrays. Note
  283. # that it is possible for an object to be listed both in here
  284. # and in 'old_objects_pointing_to_young', in which case we
  285. # should just clear the cards and trace it fully, as usual.
  286. # Note also that young array objects are never listed here.
  287. self.old_objects_with_cards_set = self.AddressStack()
  288. #
  289. # A list of all prebuilt GC objects that contain pointers to the heap
  290. self.prebuilt_root_objects = self.AddressStack()
  291. #
  292. self._init_writebarrier_logic()
  293. #
  294. # The size of all the objects turned from 'young' to 'old'
  295. # since we started the last major collection cycle. This is
  296. # used to track progress of the incremental GC: normally, we
  297. # run one major GC step after each minor collection, but if a
  298. # lot of objects are made old, we need run two or more steps.
  299. # Otherwise the risk is that we create old objects faster than
  300. # we're collecting them. The 'threshold' is incremented after
  301. # each major GC step at a fixed rate; the idea is that as long
  302. # as 'size_objects_made_old > threshold_objects_made_old' then
  303. # we must do more major GC steps. See major_collection_step()
  304. # for more details.
  305. self.size_objects_made_old = r_uint(0)
  306. self.threshold_objects_made_old = r_uint(0)
  307. def setup(self):
  308. """Called at run-time to initialize the GC."""
  309. #
  310. # Hack: MovingGCBase.setup() sets up stuff related to id(), which
  311. # we implement differently anyway. So directly call GCBase.setup().
  312. GCBase.setup(self)
  313. #
  314. # Two lists of all raw_malloced objects (the objects too large)
  315. self.young_rawmalloced_objects = self.null_address_dict()
  316. self.old_rawmalloced_objects = self.AddressStack()
  317. self.raw_malloc_might_sweep = self.AddressStack()
  318. self.rawmalloced_total_size = r_uint(0)
  319. self.gc_state = STATE_SCANNING
  320. #
  321. # Two lists of all objects with finalizers. Actually they are lists
  322. # of pairs (finalization_queue_nr, object). "probably young objects"
  323. # are all traced and moved to the "old" list by the next minor
  324. # collection.
  325. self.probably_young_objects_with_finalizers = self.AddressDeque()
  326. self.old_objects_with_finalizers = self.AddressDeque()
  327. p = lltype.malloc(self._ADDRARRAY, 1, flavor='raw',
  328. track_allocation=False)
  329. self.singleaddr = llmemory.cast_ptr_to_adr(p)
  330. #
  331. # Two lists of all objects with destructors.
  332. self.young_objects_with_destructors = self.AddressStack()
  333. self.old_objects_with_destructors = self.AddressStack()
  334. #
  335. # Two lists of the objects with weakrefs. No weakref can be an
  336. # old object weakly pointing to a young object: indeed, weakrefs
  337. # are immutable so they cannot point to an object that was
  338. # created after it.
  339. self.young_objects_with_weakrefs = self.AddressStack()
  340. self.old_objects_with_weakrefs = self.AddressStack()
  341. #
  342. # Support for id and identityhash: map nursery objects with
  343. # GCFLAG_HAS_SHADOW to their future location at the next
  344. # minor collection.
  345. self.nursery_objects_shadows = self.AddressDict()
  346. #
  347. # A sorted deque containing addresses of pinned objects.
  348. # This collection is used to make sure we don't overwrite pinned objects.
  349. # Each minor collection creates a new deque containing the active pinned
  350. # objects. The addresses are used to set the next 'nursery_top'.
  351. self.nursery_barriers = self.AddressDeque()
  352. #
  353. # Counter tracking how many pinned objects currently reside inside
  354. # the nursery.
  355. self.pinned_objects_in_nursery = 0
  356. #
  357. # This flag is set if the previous minor collection found at least
  358. # one pinned object alive.
  359. self.any_pinned_object_kept = False
  360. #
  361. # Keeps track of old objects pointing to pinned objects. These objects
  362. # must be traced every minor collection. Without tracing them the
  363. # referenced pinned object wouldn't be visited and therefore collected.
  364. self.old_objects_pointing_to_pinned = self.AddressStack()
  365. self.updated_old_objects_pointing_to_pinned = False
  366. #
  367. # Allocate a nursery. In case of auto_nursery_size, start by
  368. # allocating a very small nursery, enough to do things like look
  369. # up the env var, which requires the GC; and then really
  370. # allocate the nursery of the final size.
  371. if not self.read_from_env:
  372. self.allocate_nursery()
  373. self.gc_increment_step = self.nursery_size * 4
  374. self.gc_nursery_debug = False
  375. else:
  376. #
  377. defaultsize = self.nursery_size
  378. minsize = 2 * (self.nonlarge_max + 1)
  379. self.nursery_size = minsize
  380. self.allocate_nursery()
  381. #
  382. # From there on, the GC is fully initialized and the code
  383. # below can use it
  384. newsize = env.read_from_env('PYPY_GC_NURSERY')
  385. # PYPY_GC_NURSERY=smallvalue means that minor collects occur
  386. # very frequently; the extreme case is PYPY_GC_NURSERY=1, which
  387. # forces a minor collect for every malloc. Useful to debug
  388. # external factors, like trackgcroot or the handling of the write
  389. # barrier. Implemented by still using 'minsize' for the nursery
  390. # size (needed to handle mallocs just below 'large_objects') but
  391. # hacking at the current nursery position in collect_and_reserve().
  392. if newsize <= 0:
  393. newsize = env.estimate_best_nursery_size()
  394. if newsize <= 0:
  395. newsize = defaultsize
  396. if newsize < minsize:
  397. self.debug_tiny_nursery = newsize & ~(WORD-1)
  398. newsize = minsize
  399. #
  400. major_coll = env.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
  401. if major_coll > 1.0:
  402. self.major_collection_threshold = major_coll
  403. #
  404. growth = env.read_float_from_env('PYPY_GC_GROWTH')
  405. if growth > 1.0:
  406. self.growth_rate_max = growth
  407. #
  408. min_heap_size = env.read_uint_from_env('PYPY_GC_MIN')
  409. if min_heap_size > 0:
  410. self.min_heap_size = float(min_heap_size)
  411. else:
  412. # defaults to 8 times the nursery
  413. self.min_heap_size = newsize * 8
  414. #
  415. max_heap_size = env.read_uint_from_env('PYPY_GC_MAX')
  416. if max_heap_size > 0:
  417. self.max_heap_size = float(max_heap_size)
  418. #
  419. max_delta = env.read_uint_from_env('PYPY_GC_MAX_DELTA')
  420. if max_delta > 0:
  421. self.max_delta = float(max_delta)
  422. else:
  423. self.max_delta = 0.125 * env.get_total_memory()
  424. gc_increment_step = env.read_uint_from_env('PYPY_GC_INCREMENT_STEP')
  425. if gc_increment_step > 0:
  426. self.gc_increment_step = gc_increment_step
  427. else:
  428. self.gc_increment_step = newsize * 4
  429. #
  430. nursery_debug = env.read_uint_from_env('PYPY_GC_NURSERY_DEBUG')
  431. if nursery_debug > 0:
  432. self.gc_nursery_debug = True
  433. else:
  434. self.gc_nursery_debug = False
  435. self._minor_collection() # to empty the nursery
  436. llarena.arena_free(self.nursery)
  437. self.nursery_size = newsize
  438. self.allocate_nursery()
  439. #
  440. env_max_number_of_pinned_objects = os.environ.get('PYPY_GC_MAX_PINNED')
  441. if env_max_number_of_pinned_objects:
  442. try:
  443. env_max_number_of_pinned_objects = int(env_max_number_of_pinned_objects)
  444. except ValueError:
  445. env_max_number_of_pinned_objects = 0
  446. #
  447. if env_max_number_of_pinned_objects >= 0: # 0 allows to disable pinning completely
  448. self.max_number_of_pinned_objects = env_max_number_of_pinned_objects
  449. else:
  450. # Estimate this number conservatively
  451. bigobj = self.nonlarge_max + 1
  452. self.max_number_of_pinned_objects = self.nursery_size / (bigobj * 2)
  453. def _nursery_memory_size(self):
  454. extra = self.nonlarge_max + 1
  455. return self.nursery_size + extra
  456. def _alloc_nursery(self):
  457. # the start of the nursery: we actually allocate a bit more for
  458. # the nursery than really needed, to simplify pointer arithmetic
  459. # in malloc_fixedsize(). The few extra pages are never used
  460. # anyway so it doesn't even count.
  461. nursery = llarena.arena_malloc(self._nursery_memory_size(), 0)
  462. if not nursery:
  463. out_of_memory("cannot allocate nursery")
  464. return nursery
  465. def allocate_nursery(self):
  466. debug_start("gc-set-nursery-size")
  467. debug_print("nursery size:", self.nursery_size)
  468. self.nursery = self._alloc_nursery()
  469. # the current position in the nursery:
  470. self.nursery_free = self.nursery
  471. # the end of the nursery:
  472. self.nursery_top = self.nursery + self.nursery_size
  473. # initialize the threshold
  474. self.min_heap_size = max(self.min_heap_size, self.nursery_size *
  475. self.major_collection_threshold)
  476. # the following two values are usually equal, but during raw mallocs
  477. # with memory pressure accounting, next_major_collection_threshold
  478. # is decremented to make the next major collection arrive earlier.
  479. # See translator/c/test/test_newgc, test_nongc_attached_to_gc
  480. self.next_major_collection_initial = self.min_heap_size
  481. self.next_major_collection_threshold = self.min_heap_size
  482. self.set_major_threshold_from(0.0)
  483. ll_assert(self.extra_threshold == 0, "extra_threshold set too early")
  484. debug_stop("gc-set-nursery-size")
  485. def set_major_threshold_from(self, threshold, reserving_size=0):
  486. # Set the next_major_collection_threshold.
  487. threshold_max = (self.next_major_collection_initial *
  488. self.growth_rate_max)
  489. if threshold > threshold_max:
  490. threshold = threshold_max
  491. #
  492. threshold += reserving_size
  493. if threshold < self.min_heap_size:
  494. threshold = self.min_heap_size
  495. #
  496. if self.max_heap_size > 0.0 and threshold > self.max_heap_size:
  497. threshold = self.max_heap_size
  498. bounded = True
  499. else:
  500. bounded = False
  501. #
  502. self.next_major_collection_initial = threshold
  503. self.next_major_collection_threshold = threshold
  504. return bounded
  505. def post_setup(self):
  506. # set up extra stuff for PYPY_GC_DEBUG.
  507. MovingGCBase.post_setup(self)
  508. if self.DEBUG and llarena.has_protect:
  509. # gc debug mode: allocate 7 nurseries instead of just 1,
  510. # and use them alternatively, while mprotect()ing the unused
  511. # ones to detect invalid access.
  512. debug_start("gc-debug")
  513. self.debug_rotating_nurseries = lltype.malloc(
  514. NURSARRAY, 6, flavor='raw', track_allocation=False)
  515. i = 0
  516. while i < 6:
  517. nurs = self._alloc_nursery()
  518. llarena.arena_protect(nurs, self._nursery_memory_size(), True)
  519. self.debug_rotating_nurseries[i] = nurs
  520. i += 1
  521. debug_print("allocated", len(self.debug_rotating_nurseries),
  522. "extra nurseries")
  523. debug_stop("gc-debug")
  524. def debug_rotate_nursery(self):
  525. if self.debug_rotating_nurseries:
  526. debug_start("gc-debug")
  527. oldnurs = self.nursery
  528. llarena.arena_protect(oldnurs, self._nursery_memory_size(), True)
  529. #
  530. newnurs = self.debug_rotating_nurseries[0]
  531. i = 0
  532. while i < len(self.debug_rotating_nurseries) - 1:
  533. self.debug_rotating_nurseries[i] = (
  534. self.debug_rotating_nurseries[i + 1])
  535. i += 1
  536. self.debug_rotating_nurseries[i] = oldnurs
  537. #
  538. llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
  539. self.nursery = newnurs
  540. self.nursery_top = self.nursery + self.nursery_size
  541. debug_print("switching from nursery", oldnurs,
  542. "to nursery", self.nursery,
  543. "size", self.nursery_size)
  544. debug_stop("gc-debug")
  545. def malloc_fixedsize(self, typeid, size,
  546. needs_finalizer=False,
  547. is_finalizer_light=False,
  548. contains_weakptr=False):
  549. size_gc_header = self.gcheaderbuilder.size_gc_header
  550. totalsize = size_gc_header + size
  551. rawtotalsize = raw_malloc_usage(totalsize)
  552. #
  553. # If the object needs a finalizer, ask for a rawmalloc.
  554. # The following check should be constant-folded.
  555. if needs_finalizer and not is_finalizer_light:
  556. # old-style finalizers only!
  557. ll_assert(not contains_weakptr,
  558. "'needs_finalizer' and 'contains_weakptr' both specified")
  559. obj = self.external_malloc(typeid, 0, alloc_young=False)
  560. res = llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  561. self.register_finalizer(-1, res)
  562. return res
  563. #
  564. # If totalsize is greater than nonlarge_max (which should never be
  565. # the case in practice), ask for a rawmalloc. The following check
  566. # should be constant-folded.
  567. if rawtotalsize > self.nonlarge_max:
  568. ll_assert(not contains_weakptr,
  569. "'contains_weakptr' specified for a large object")
  570. obj = self.external_malloc(typeid, 0, alloc_young=True)
  571. #
  572. else:
  573. # If totalsize is smaller than minimal_size_in_nursery, round it
  574. # up. The following check should also be constant-folded.
  575. min_size = raw_malloc_usage(self.minimal_size_in_nursery)
  576. if rawtotalsize < min_size:
  577. totalsize = rawtotalsize = min_size
  578. #
  579. # Get the memory from the nursery. If there is not enough space
  580. # there, do a collect first.
  581. result = self.nursery_free
  582. ll_assert(result != llmemory.NULL, "uninitialized nursery")
  583. self.nursery_free = new_free = result + totalsize
  584. if new_free > self.nursery_top:
  585. result = self.collect_and_reserve(totalsize)
  586. #
  587. # Build the object.
  588. llarena.arena_reserve(result, totalsize)
  589. obj = result + size_gc_header
  590. self.init_gc_object(result, typeid, flags=0)
  591. #
  592. # If it is a weakref or has a lightweight destructor, record it
  593. # (checks constant-folded).
  594. if needs_finalizer:
  595. self.young_objects_with_destructors.append(obj)
  596. if contains_weakptr:
  597. self.young_objects_with_weakrefs.append(obj)
  598. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  599. def malloc_varsize(self, typeid, length, size, itemsize,
  600. offset_to_length):
  601. size_gc_header = self.gcheaderbuilder.size_gc_header
  602. nonvarsize = size_gc_header + size
  603. #
  604. # Compute the maximal length that makes the object still
  605. # below 'nonlarge_max'. All the following logic is usually
  606. # constant-folded because self.nonlarge_max, size and itemsize
  607. # are all constants (the arguments are constant due to
  608. # inlining).
  609. maxsize = self.nonlarge_max - raw_malloc_usage(nonvarsize)
  610. if maxsize < 0:
  611. toobig = r_uint(0) # the nonvarsize alone is too big
  612. elif raw_malloc_usage(itemsize):
  613. toobig = r_uint(maxsize // raw_malloc_usage(itemsize)) + 1
  614. else:
  615. toobig = r_uint(sys.maxint) + 1
  616. if r_uint(length) >= r_uint(toobig):
  617. #
  618. # If the total size of the object would be larger than
  619. # 'nonlarge_max', then allocate it externally. We also
  620. # go there if 'length' is actually negative.
  621. obj = self.external_malloc(typeid, length, alloc_young=True)
  622. #
  623. else:
  624. # With the above checks we know now that totalsize cannot be more
  625. # than 'nonlarge_max'; in particular, the + and * cannot overflow.
  626. totalsize = nonvarsize + itemsize * length
  627. totalsize = llarena.round_up_for_allocation(totalsize)
  628. #
  629. # 'totalsize' should contain at least the GC header and
  630. # the length word, so it should never be smaller than
  631. # 'minimal_size_in_nursery'
  632. ll_assert(raw_malloc_usage(totalsize) >=
  633. raw_malloc_usage(self.minimal_size_in_nursery),
  634. "malloc_varsize(): totalsize < minimalsize")
  635. #
  636. # Get the memory from the nursery. If there is not enough space
  637. # there, do a collect first.
  638. result = self.nursery_free
  639. ll_assert(result != llmemory.NULL, "uninitialized nursery")
  640. self.nursery_free = new_free = result + totalsize
  641. if new_free > self.nursery_top:
  642. result = self.collect_and_reserve(totalsize)
  643. #
  644. # Build the object.
  645. llarena.arena_reserve(result, totalsize)
  646. self.init_gc_object(result, typeid, flags=0)
  647. #
  648. # Set the length and return the object.
  649. obj = result + size_gc_header
  650. (obj + offset_to_length).signed[0] = length
  651. #
  652. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  653. def malloc_fixed_or_varsize_nonmovable(self, typeid, length):
  654. # length==0 for fixedsize
  655. obj = self.external_malloc(typeid, length, alloc_young=True)
  656. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  657. def collect(self, gen=2):
  658. """Do a minor (gen=0), start a major (gen=1), or do a full
  659. major (gen>=2) collection."""
  660. if gen < 0:
  661. self._minor_collection() # dangerous! no major GC cycle progress
  662. elif gen <= 1:
  663. self.minor_collection_with_major_progress()
  664. if gen == 1 and self.gc_state == STATE_SCANNING:
  665. self.major_collection_step()
  666. else:
  667. self.minor_and_major_collection()
  668. self.rrc_invoke_callback()
  669. def minor_collection_with_major_progress(self, extrasize=0):
  670. """Do a minor collection. Then, if there is already a major GC
  671. in progress, run at least one major collection step. If there is
  672. no major GC but the threshold is reached, start a major GC.
  673. """
  674. self._minor_collection()
  675. # If the gc_state is STATE_SCANNING, we're not in the middle
  676. # of an incremental major collection. In that case, wait
  677. # until there is too much garbage before starting the next
  678. # major collection. But if we are in the middle of an
  679. # incremental major collection, then always do (at least) one
  680. # step now.
  681. #
  682. # Within a major collection cycle, every call to
  683. # major_collection_step() increments
  684. # 'threshold_objects_made_old' by nursery_size/2.
  685. if self.gc_state != STATE_SCANNING or self.threshold_reached(extrasize):
  686. self.major_collection_step(extrasize)
  687. # See documentation in major_collection_step() for target invariants
  688. while self.gc_state != STATE_SCANNING: # target (A1)
  689. threshold = self.threshold_objects_made_old
  690. if threshold >= r_uint(extrasize):
  691. threshold -= r_uint(extrasize) # (*)
  692. if self.size_objects_made_old <= threshold: # target (A2)
  693. break
  694. # Note that target (A2) is tweaked by (*); see
  695. # test_gc_set_max_heap_size in translator/c, test_newgc.py
  696. self._minor_collection()
  697. self.major_collection_step(extrasize)
  698. self.rrc_invoke_callback()
  699. def collect_and_reserve(self, totalsize):
  700. """To call when nursery_free overflows nursery_top.
  701. First check if pinned objects are in front of nursery_top. If so,
  702. jump over the pinned object and try again to reserve totalsize.
  703. Otherwise do a minor collection, and possibly some steps of a
  704. major collection, and finally reserve totalsize bytes.
  705. """
  706. minor_collection_count = 0
  707. while True:
  708. self.nursery_free = llmemory.NULL # debug: don't use me
  709. # note: no "raise MemoryError" between here and the next time
  710. # we initialize nursery_free!
  711. if self.nursery_barriers.non_empty():
  712. # Pinned object in front of nursery_top. Try reserving totalsize
  713. # by jumping into the next, yet unused, area inside the
  714. # nursery. "Next area" in this case is the space between the
  715. # pinned object in front of nusery_top and the pinned object
  716. # after that. Graphically explained:
  717. #
  718. # |- allocating totalsize failed in this area
  719. # | |- nursery_top
  720. # | | |- pinned object in front of nursery_top,
  721. # v v v jump over this
  722. # +---------+--------+--------+--------+-----------+ }
  723. # | used | pinned | empty | pinned | empty | }- nursery
  724. # +---------+--------+--------+--------+-----------+ }
  725. # ^- try reserving totalsize in here next
  726. #
  727. # All pinned objects are represented by entries in
  728. # nursery_barriers (see minor_collection). The last entry is
  729. # always the end of the nursery. Therefore if nursery_barriers
  730. # contains only one element, we jump over a pinned object and
  731. # the "next area" (the space where we will try to allocate
  732. # totalsize) starts at the end of the pinned object and ends at
  733. # nursery's end.
  734. #
  735. # find the size of the pinned object after nursery_top
  736. size_gc_header = self.gcheaderbuilder.size_gc_header
  737. pinned_obj_size = size_gc_header + self.get_size(
  738. self.nursery_top + size_gc_header)
  739. #
  740. # update used nursery space to allocate objects
  741. self.nursery_free = self.nursery_top + pinned_obj_size
  742. self.nursery_top = self.nursery_barriers.popleft()
  743. else:
  744. minor_collection_count += 1
  745. if minor_collection_count == 1:
  746. self.minor_collection_with_major_progress()
  747. else:
  748. # Nursery too full again. This is likely because of
  749. # execute_finalizers() or rrc_invoke_callback().
  750. # we need to fix it with another call to minor_collection()
  751. # ---this time only the minor part so that we are sure that
  752. # the nursery is empty (apart from pinned objects).
  753. #
  754. # Note that this still works with the counters:
  755. # 'size_objects_made_old' will be increased by
  756. # the _minor_collection() below. We don't
  757. # immediately restore the target invariant that
  758. # 'size_objects_made_old <= threshold_objects_made_old'.
  759. # But we will do it in the next call to
  760. # minor_collection_with_major_progress().
  761. #
  762. ll_assert(minor_collection_count == 2,
  763. "Calling minor_collection() twice is not "
  764. "enough. Too many pinned objects?")
  765. self._minor_collection()
  766. #
  767. # Tried to do something about nursery_free overflowing
  768. # nursery_top before this point. Try to reserve totalsize now.
  769. # If this succeeds break out of loop.
  770. result = self.nursery_free
  771. if self.nursery_free + totalsize <= self.nursery_top:
  772. self.nursery_free = result + totalsize
  773. ll_assert(self.nursery_free <= self.nursery_top, "nursery overflow")
  774. break
  775. #
  776. #
  777. if self.debug_tiny_nursery >= 0: # for debugging
  778. if self.nursery_top - self.nursery_free > self.debug_tiny_nursery:
  779. self.nursery_free = self.nursery_top - self.debug_tiny_nursery
  780. #
  781. return result
  782. collect_and_reserve._dont_inline_ = True
  783. # XXX kill alloc_young and make it always True
  784. def external_malloc(self, typeid, length, alloc_young):
  785. """Allocate a large object using the ArenaCollection or
  786. raw_malloc(), possibly as an object with card marking enabled,
  787. if it has gc pointers in its var-sized part. 'length' should be
  788. specified as 0 if the object is not varsized. The returned
  789. object is fully initialized, but not zero-filled."""
  790. #
  791. # Here we really need a valid 'typeid', not 0 (as the JIT might
  792. # try to send us if there is still a bug).
  793. ll_assert(bool(self.combine(typeid, 0)),
  794. "external_malloc: typeid == 0")
  795. #
  796. # Compute the total size, carefully checking for overflows.
  797. size_gc_header = self.gcheaderbuilder.size_gc_header
  798. nonvarsize = size_gc_header + self.fixed_size(typeid)
  799. if length == 0:
  800. # this includes the case of fixed-size objects, for which we
  801. # should not even ask for the varsize_item_sizes().
  802. totalsize = nonvarsize
  803. elif length > 0:
  804. # var-sized allocation with at least one item
  805. itemsize = self.varsize_item_sizes(typeid)
  806. try:
  807. varsize = ovfcheck(itemsize * length)
  808. totalsize = ovfcheck(nonvarsize + varsize)
  809. except OverflowError:
  810. raise MemoryError
  811. else:
  812. # negative length! This likely comes from an overflow
  813. # earlier. We will just raise MemoryError here.
  814. raise MemoryError
  815. #
  816. # If somebody calls this function a lot, we must eventually
  817. # force a collection. We use threshold_reached(), which might
  818. # be true now but become false at some point after a few calls
  819. # to major_collection_step(). If there is really no memory,
  820. # then when the major collection finishes it will raise
  821. # MemoryError.
  822. if self.threshold_reached(raw_malloc_usage(totalsize)):
  823. self.minor_collection_with_major_progress(
  824. raw_malloc_usage(totalsize) + self.nursery_size // 2)
  825. #
  826. # Check if the object would fit in the ArenaCollection.
  827. # Also, an object allocated from ArenaCollection must be old.
  828. if (raw_malloc_usage(totalsize) <= self.small_request_threshold
  829. and not alloc_young):
  830. #
  831. # Yes. Round up 'totalsize' (it cannot overflow and it
  832. # must remain <= self.small_request_threshold.)
  833. totalsize = llarena.round_up_for_allocation(totalsize)
  834. ll_assert(raw_malloc_usage(totalsize) <=
  835. self.small_request_threshold,
  836. "rounding up made totalsize > small_request_threshold")
  837. #
  838. # Allocate from the ArenaCollection. Don't clear it.
  839. result = self.ac.malloc(totalsize)
  840. #
  841. extra_flags = GCFLAG_TRACK_YOUNG_PTRS
  842. #
  843. else:
  844. # No, so proceed to allocate it externally with raw_malloc().
  845. # Check if we need to introduce the card marker bits area.
  846. if (self.card_page_indices <= 0 # <- this check is constant-folded
  847. or not self.has_gcptr_in_varsize(typeid) or
  848. raw_malloc_usage(totalsize) <= self.nonlarge_max):
  849. #
  850. # In these cases, we don't want a card marker bits area.
  851. # This case also includes all fixed-size objects.
  852. cardheadersize = 0
  853. extra_flags = 0
  854. #
  855. else:
  856. # Reserve N extra words containing card bits before the object.
  857. extra_words = self.card_marking_words_for_length(length)
  858. cardheadersize = WORD * extra_words
  859. extra_flags = GCFLAG_HAS_CARDS | GCFLAG_TRACK_YOUNG_PTRS
  860. # if 'alloc_young', then we also immediately set
  861. # GCFLAG_CARDS_SET, but without adding the object to
  862. # 'old_objects_with_cards_set'. In this way it should
  863. # never be added to that list as long as it is young.
  864. if alloc_young:
  865. extra_flags |= GCFLAG_CARDS_SET
  866. #
  867. # Detect very rare cases of overflows
  868. if raw_malloc_usage(totalsize) > (sys.maxint - (WORD-1)
  869. - cardheadersize):
  870. raise MemoryError("rare case of overflow")
  871. #
  872. # Now we know that the following computations cannot overflow.
  873. # Note that round_up_for_allocation() is also needed to get the
  874. # correct number added to 'rawmalloced_total_size'.
  875. allocsize = (cardheadersize + raw_malloc_usage(
  876. llarena.round_up_for_allocation(totalsize)))
  877. #
  878. # Allocate the object using arena_malloc(), which we assume here
  879. # is just the same as raw_malloc(), but allows the extra
  880. # flexibility of saying that we have extra words in the header.
  881. # The memory returned is not cleared.
  882. arena = llarena.arena_malloc(allocsize, 0)
  883. if not arena:
  884. raise MemoryError("cannot allocate large object")
  885. #
  886. # Reserve the card mark bits as a list of single bytes,
  887. # and clear these bytes.
  888. i = 0
  889. while i < cardheadersize:
  890. p = arena + i
  891. llarena.arena_reserve(p, llmemory.sizeof(lltype.Char))
  892. p.char[0] = '\x00'
  893. i += 1
  894. #
  895. # Reserve the actual object. (This is a no-op in C).
  896. result = arena + cardheadersize
  897. llarena.arena_reserve(result, totalsize)
  898. #
  899. # Record the newly allocated object and its full malloced size.
  900. # The object is young or old depending on the argument.
  901. self.rawmalloced_total_size += r_uint(allocsize)
  902. if alloc_young:
  903. if not self.young_rawmalloced_objects:
  904. self.young_rawmalloced_objects = self.AddressDict()
  905. self.young_rawmalloced_objects.add(result + size_gc_header)
  906. else:
  907. self.old_rawmalloced_objects.append(result + size_gc_header)
  908. extra_flags |= GCFLAG_TRACK_YOUNG_PTRS
  909. #
  910. # Common code to fill the header and length of the object.
  911. self.init_gc_object(result, typeid, extra_flags)
  912. if self.is_varsize(typeid):
  913. offset_to_length = self.varsize_offset_to_length(typeid)
  914. (result + size_gc_header + offset_to_length).signed[0] = length
  915. return result + size_gc_header
  916. # ----------
  917. # Other functions in the GC API
  918. def set_max_heap_size(self, size):
  919. self.max_heap_size = float(size)
  920. if self.max_heap_size > 0.0:
  921. if self.max_heap_size < self.next_major_collection_initial:
  922. self.next_major_collection_initial = self.max_heap_size
  923. if self.max_heap_size < self.next_major_collection_threshold:
  924. self.next_major_collection_threshold = self.max_heap_size
  925. def raw_malloc_memory_pressure(self, sizehint):
  926. # Decrement by 'sizehint' plus a very little bit extra. This
  927. # is needed e.g. for _rawffi, which may allocate a lot of tiny
  928. # arrays.
  929. self.next_major_collection_threshold -= (sizehint + 2 * WORD)
  930. if self.next_major_collection_threshold < 0:
  931. # cannot trigger a full collection now, but we can ensure
  932. # that one will occur very soon
  933. self.nursery_free = self.nursery_top
  934. def can_optimize_clean_setarrayitems(self):
  935. if self.card_page_indices > 0:
  936. return False
  937. return MovingGCBase.can_optimize_clean_setarrayitems(self)
  938. def can_move(self, obj):
  939. """Overrides the parent can_move()."""
  940. return self.is_in_nursery(obj)
  941. def pin(self, obj):
  942. if self.pinned_objects_in_nursery >= self.max_number_of_pinned_objects:
  943. return False
  944. if not self.is_in_nursery(obj):
  945. # old objects are already non-moving, therefore pinning
  946. # makes no sense. If you run into this case, you may forgot
  947. # to check can_move(obj).
  948. return False
  949. if self._is_pinned(obj):
  950. # already pinned, we do not allow to pin it again.
  951. # Reason: It would be possible that the first caller unpins
  952. # while the second caller thinks it's still pinned.
  953. return False
  954. #
  955. obj_type_id = self.get_type_id(obj)
  956. if self.cannot_pin(obj_type_id):
  957. # objects containing GC pointers can't be pinned. If we would add
  958. # it, we would have to track all pinned objects and trace them
  959. # every minor collection to make sure the referenced object are
  960. # kept alive. Right now this is not a use case that's needed.
  961. # The check above also tests for being a less common kind of
  962. # object: a weakref, or one with any kind of finalizer.
  963. return False
  964. #
  965. self.header(obj).tid |= GCFLAG_PINNED
  966. self.pinned_objects_in_nursery += 1
  967. return True
  968. def unpin(self, obj):
  969. ll_assert

Large files files are truncated, but you can click here to view the full file