PageRenderTime 68ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/memory/gc/minimark.py

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

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