PageRenderTime 77ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/pypy/pypy/
Python | 1416 lines | 969 code | 88 blank | 359 comment | 95 complexity | 22f56875ec171edc8caef98175ba0f2c MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """ MiniMark GC.
  2. Environment variables can be used to fine-tune the following parameters:
  3. PYPY_GC_NURSERY The nursery size. Defaults to '4MB'. Small values
  4. (like 1 or 1KB) are useful for debugging.
  5. PYPY_GC_MAJOR_COLLECT Major collection memory factor. Default is '1.82',
  6. which means trigger a major collection when the
  7. memory consumed equals 1.82 times the memory
  8. really used at the end of the previous major
  9. collection.
  10. PYPY_GC_GROWTH Major collection threshold's max growth rate.
  11. Default is '1.4'. Useful to collect more often
  12. than normally on sudden memory growth, e.g. when
  13. there is a temporary peak in memory usage.
  14. PYPY_GC_MAX The max heap size. If coming near this limit, it
  15. will first collect more often, then raise an
  16. RPython MemoryError, and if that is not enough,
  17. crash the program with a fatal error. Try values
  18. like '1.6GB'.
  19. PYPY_GC_MAX_DELTA The major collection threshold will never be set
  20. to more than PYPY_GC_MAX_DELTA the amount really
  21. used after a collection. Defaults to 1/8th of the
  22. total RAM size (which is constrained to be at most
  23. 2/3/4GB on 32-bit systems). Try values like '200MB'.
  24. PYPY_GC_MIN Don't collect while the memory size is below this
  25. limit. Useful to avoid spending all the time in
  26. the GC in very small programs. Defaults to 8
  27. times the nursery.
  28. PYPY_GC_DEBUG Enable extra checks around collections that are
  29. too slow for normal use. Values are 0 (off),
  30. 1 (on major collections) or 2 (also on minor
  31. collections).
  32. """
  33. # XXX Should find a way to bound the major collection threshold by the
  34. # XXX total addressable size. Maybe by keeping some minimarkpage arenas
  35. # XXX pre-reserved, enough for a few nursery collections? What about
  36. # XXX raw-malloced memory?
  37. import sys
  38. from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
  39. from pypy.rpython.lltypesystem.lloperation import llop
  40. from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
  41. from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
  42. from pypy.rpython.memory.gc import minimarkpage, env
  43. from pypy.rpython.memory.support import mangle_hash
  44. from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
  45. from pypy.rlib.rarithmetic import LONG_BIT_SHIFT
  46. from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
  47. from pypy.rlib.objectmodel import we_are_translated
  48. from pypy.tool.sourcetools import func_with_new_name
  49. #
  50. # Handles the objects in 2 generations:
  51. #
  52. # * young objects: allocated in the nursery if they are not too large, or
  53. # raw-malloced otherwise. The nursery is a fixed-size memory buffer of
  54. # 4MB by default. When full, we do a minor collection;
  55. # the surviving objects from the nursery are moved outside, and the
  56. # non-surviving raw-malloced objects are freed. All surviving objects
  57. # become old.
  58. #
  59. # * old objects: never move again. These objects are either allocated by
  60. # minimarkpage.py (if they are small), or raw-malloced (if they are not
  61. # small). Collected by regular mark-n-sweep during major collections.
  62. #
  63. WORD = LONG_BIT // 8
  64. NULL = llmemory.NULL
  65. first_gcflag = 1 << (LONG_BIT//2)
  66. # The following flag is set on objects if we need to do something to
  67. # track the young pointers that it might contain. The flag is not set
  68. # on young objects (unless they are large arrays, see below), and we
  69. # simply assume that any young object can point to any other young object.
  70. # For old and prebuilt objects, the flag is usually set, and is cleared
  71. # when we write a young pointer to it. For large arrays with
  72. # GCFLAG_HAS_CARDS, we rely on card marking to track where the
  73. # young pointers are; the flag GCFLAG_TRACK_YOUNG_PTRS is set in this
  74. # case too, to speed up the write barrier.
  75. GCFLAG_TRACK_YOUNG_PTRS = first_gcflag << 0
  76. # The following flag is set on some prebuilt objects. The flag is set
  77. # unless the object is already listed in 'prebuilt_root_objects'.
  78. # When a pointer is written inside an object with GCFLAG_NO_HEAP_PTRS
  79. # set, the write_barrier clears the flag and adds the object to
  80. # 'prebuilt_root_objects'.
  81. GCFLAG_NO_HEAP_PTRS = first_gcflag << 1
  82. # The following flag is set on surviving objects during a major collection,
  83. # and on surviving raw-malloced young objects during a minor collection.
  84. GCFLAG_VISITED = first_gcflag << 2
  85. # The following flag is set on nursery objects of which we asked the id
  86. # or the identityhash. It means that a space of the size of the object
  87. # has already been allocated in the nonmovable part. The same flag is
  88. # abused to mark prebuilt objects whose hash has been taken during
  89. # translation and is statically recorded.
  90. GCFLAG_HAS_SHADOW = first_gcflag << 3
  91. # The following flag is set temporarily on some objects during a major
  92. # collection. See pypy/doc/discussion/finalizer-order.txt
  93. GCFLAG_FINALIZATION_ORDERING = first_gcflag << 4
  94. # The following flag is set on externally raw_malloc'ed arrays of pointers.
  95. # They are allocated with some extra space in front of them for a bitfield,
  96. # one bit per 'card_page_indices' indices.
  97. GCFLAG_HAS_CARDS = first_gcflag << 5
  98. GCFLAG_CARDS_SET = first_gcflag << 6 # <- at least one card bit is set
  99. TID_MASK = (first_gcflag << 7) - 1
  100. FORWARDSTUB = lltype.GcStruct('forwarding_stub',
  101. ('forw', llmemory.Address))
  102. FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
  103. # ____________________________________________________________
  104. class MiniMarkGC(MovingGCBase):
  105. _alloc_flavor_ = "raw"
  106. inline_simple_malloc = True
  107. inline_simple_malloc_varsize = True
  108. needs_write_barrier = True
  109. prebuilt_gc_objects_are_static_roots = False
  110. malloc_zero_filled = True # xxx experiment with False
  111. gcflag_extra = GCFLAG_FINALIZATION_ORDERING
  112. # All objects start with a HDR, i.e. with a field 'tid' which contains
  113. # a word. This word is divided in two halves: the lower half contains
  114. # the typeid, and the upper half contains various flags, as defined
  115. # by GCFLAG_xxx above.
  116. HDR = lltype.Struct('header', ('tid', lltype.Signed))
  117. typeid_is_in_field = 'tid'
  118. withhash_flag_is_in_field = 'tid', GCFLAG_HAS_SHADOW
  119. # ^^^ prebuilt objects may have the flag GCFLAG_HAS_SHADOW;
  120. # then they are one word longer, the extra word storing the hash.
  121. # During a minor collection, the objects in the nursery that are
  122. # moved outside are changed in-place: their header is replaced with
  123. # the value -42, and the following word is set to the address of
  124. # where the object was moved. This means that all objects in the
  125. # nursery need to be at least 2 words long, but objects outside the
  126. # nursery don't need to.
  127. minimal_size_in_nursery = (
  128. llmemory.sizeof(HDR) + llmemory.sizeof(llmemory.Address))
  129. TRANSLATION_PARAMS = {
  130. # Automatically adjust the size of the nursery and the
  131. # 'major_collection_threshold' from the environment.
  132. # See docstring at the start of the file.
  133. "read_from_env": True,
  134. # The size of the nursery. Note that this is only used as a
  135. # fall-back number.
  136. "nursery_size": 896*1024,
  137. # The system page size. Like obmalloc.c, we assume that it is 4K
  138. # for 32-bit systems; unlike obmalloc.c, we assume that it is 8K
  139. # for 64-bit systems, for consistent results.
  140. "page_size": 1024*WORD,
  141. # The size of an arena. Arenas are groups of pages allocated
  142. # together.
  143. "arena_size": 65536*WORD,
  144. # The maximum size of an object allocated compactly. All objects
  145. # that are larger are just allocated with raw_malloc(). Note that
  146. # the size limit for being first allocated in the nursery is much
  147. # larger; see below.
  148. "small_request_threshold": 35*WORD,
  149. # Full collection threshold: after a major collection, we record
  150. # the total size consumed; and after every minor collection, if the
  151. # total size is now more than 'major_collection_threshold' times,
  152. # we trigger the next major collection.
  153. "major_collection_threshold": 1.82,
  154. # Threshold to avoid that the total heap size grows by a factor of
  155. # major_collection_threshold at every collection: it can only
  156. # grow at most by the following factor from one collection to the
  157. # next. Used e.g. when there is a sudden, temporary peak in memory
  158. # usage; this avoids that the upper bound grows too fast.
  159. "growth_rate_max": 1.4,
  160. # The number of array indices that are mapped to a single bit in
  161. # write_barrier_from_array(). Must be a power of two. The default
  162. # value of 128 means that card pages are 512 bytes (1024 on 64-bits)
  163. # in regular arrays of pointers; more in arrays whose items are
  164. # larger. A value of 0 disables card marking.
  165. "card_page_indices": 128,
  166. # Objects whose total size is at least 'large_object' bytes are
  167. # allocated out of the nursery immediately, as old objects. The
  168. # minimal allocated size of the nursery is 2x the following
  169. # number (by default, at least 132KB on 32-bit and 264KB on 64-bit).
  170. "large_object": (16384+512)*WORD,
  171. }
  172. def __init__(self, config,
  173. read_from_env=False,
  174. nursery_size=32*WORD,
  175. page_size=16*WORD,
  176. arena_size=64*WORD,
  177. small_request_threshold=5*WORD,
  178. major_collection_threshold=2.5,
  179. growth_rate_max=2.5, # for tests
  180. card_page_indices=0,
  181. large_object=8*WORD,
  182. ArenaCollectionClass=None,
  183. **kwds):
  184. MovingGCBase.__init__(self, config, **kwds)
  185. assert small_request_threshold % WORD == 0
  186. self.read_from_env = read_from_env
  187. self.nursery_size = nursery_size
  188. self.small_request_threshold = small_request_threshold
  189. self.major_collection_threshold = major_collection_threshold
  190. self.growth_rate_max = growth_rate_max
  191. self.num_major_collects = 0
  192. self.min_heap_size = 0.0
  193. self.max_heap_size = 0.0
  194. self.max_heap_size_already_raised = False
  195. self.max_delta = float(r_uint(-1))
  196. #
  197. self.card_page_indices = card_page_indices
  198. if self.card_page_indices > 0:
  199. self.card_page_shift = 0
  200. while (1 << self.card_page_shift) < self.card_page_indices:
  201. self.card_page_shift += 1
  202. #
  203. # 'large_object' limit how big objects can be in the nursery, so
  204. # it gives a lower bound on the allowed size of the nursery.
  205. self.nonlarge_max = large_object - 1
  206. #
  207. self.nursery = NULL
  208. self.nursery_free = NULL
  209. self.nursery_top = NULL
  210. self.debug_tiny_nursery = -1
  211. self.debug_rotating_nurseries = None
  212. #
  213. # The ArenaCollection() handles the nonmovable objects allocation.
  214. if ArenaCollectionClass is None:
  215. ArenaCollectionClass = minimarkpage.ArenaCollection
  216. self.ac = ArenaCollectionClass(arena_size, page_size,
  217. small_request_threshold)
  218. #
  219. # Used by minor collection: a list of (mostly non-young) objects that
  220. # (may) contain a pointer to a young object. Populated by
  221. # the write barrier: when we clear GCFLAG_TRACK_YOUNG_PTRS, we
  222. # add it to this list.
  223. # Note that young array objects may (by temporary "mistake") be added
  224. # to this list, but will be removed again at the start of the next
  225. # minor collection.
  226. self.old_objects_pointing_to_young = self.AddressStack()
  227. #
  228. # Similar to 'old_objects_pointing_to_young', but lists objects
  229. # that have the GCFLAG_CARDS_SET bit. For large arrays. Note
  230. # that it is possible for an object to be listed both in here
  231. # and in 'old_objects_pointing_to_young', in which case we
  232. # should just clear the cards and trace it fully, as usual.
  233. # Note also that young array objects are never listed here.
  234. self.old_objects_with_cards_set = self.AddressStack()
  235. #
  236. # A list of all prebuilt GC objects that contain pointers to the heap
  237. self.prebuilt_root_objects = self.AddressStack()
  238. #
  239. self._init_writebarrier_logic()
  240. def setup(self):
  241. """Called at run-time to initialize the GC."""
  242. #
  243. # Hack: MovingGCBase.setup() sets up stuff related to id(), which
  244. # we implement differently anyway. So directly call GCBase.setup().
  245. GCBase.setup(self)
  246. #
  247. # Two lists of all raw_malloced objects (the objects too large)
  248. self.young_rawmalloced_objects = self.null_address_dict()
  249. self.old_rawmalloced_objects = self.AddressStack()
  250. self.rawmalloced_total_size = r_uint(0)
  251. #
  252. # A list of all objects with finalizers (these are never young).
  253. self.objects_with_finalizers = self.AddressDeque()
  254. self.young_objects_with_light_finalizers = self.AddressStack()
  255. self.old_objects_with_light_finalizers = self.AddressStack()
  256. #
  257. # Two lists of the objects with weakrefs. No weakref can be an
  258. # old object weakly pointing to a young object: indeed, weakrefs
  259. # are immutable so they cannot point to an object that was
  260. # created after it.
  261. self.young_objects_with_weakrefs = self.AddressStack()
  262. self.old_objects_with_weakrefs = self.AddressStack()
  263. #
  264. # Support for id and identityhash: map nursery objects with
  265. # GCFLAG_HAS_SHADOW to their future location at the next
  266. # minor collection.
  267. self.nursery_objects_shadows = self.AddressDict()
  268. #
  269. # Allocate a nursery. In case of auto_nursery_size, start by
  270. # allocating a very small nursery, enough to do things like look
  271. # up the env var, which requires the GC; and then really
  272. # allocate the nursery of the final size.
  273. if not self.read_from_env:
  274. self.allocate_nursery()
  275. else:
  276. #
  277. defaultsize = self.nursery_size
  278. minsize = 2 * (self.nonlarge_max + 1)
  279. self.nursery_size = minsize
  280. self.allocate_nursery()
  281. #
  282. # From there on, the GC is fully initialized and the code
  283. # below can use it
  284. newsize = env.read_from_env('PYPY_GC_NURSERY')
  285. # PYPY_GC_NURSERY=smallvalue means that minor collects occur
  286. # very frequently; the extreme case is PYPY_GC_NURSERY=1, which
  287. # forces a minor collect for every malloc. Useful to debug
  288. # external factors, like trackgcroot or the handling of the write
  289. # barrier. Implemented by still using 'minsize' for the nursery
  290. # size (needed to handle mallocs just below 'large_objects') but
  291. # hacking at the current nursery position in collect_and_reserve().
  292. if newsize <= 0:
  293. newsize = 4*1024*1024 # fixed to 4MB by default
  294. # (it was env.estimate_best_nursery_size())
  295. if newsize <= 0:
  296. newsize = defaultsize
  297. if newsize < minsize:
  298. self.debug_tiny_nursery = newsize & ~(WORD-1)
  299. newsize = minsize
  300. #
  301. major_coll = env.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
  302. if major_coll > 1.0:
  303. self.major_collection_threshold = major_coll
  304. #
  305. growth = env.read_float_from_env('PYPY_GC_GROWTH')
  306. if growth > 1.0:
  307. self.growth_rate_max = growth
  308. #
  309. min_heap_size = env.read_uint_from_env('PYPY_GC_MIN')
  310. if min_heap_size > 0:
  311. self.min_heap_size = float(min_heap_size)
  312. else:
  313. # defaults to 8 times the nursery
  314. self.min_heap_size = newsize * 8
  315. #
  316. max_heap_size = env.read_uint_from_env('PYPY_GC_MAX')
  317. if max_heap_size > 0:
  318. self.max_heap_size = float(max_heap_size)
  319. #
  320. max_delta = env.read_uint_from_env('PYPY_GC_MAX_DELTA')
  321. if max_delta > 0:
  322. self.max_delta = float(max_delta)
  323. else:
  324. self.max_delta = 0.125 * env.get_total_memory()
  325. #
  326. self.minor_collection() # to empty the nursery
  327. llarena.arena_free(self.nursery)
  328. self.nursery_size = newsize
  329. self.allocate_nursery()
  330. def _nursery_memory_size(self):
  331. extra = self.nonlarge_max + 1
  332. return self.nursery_size + extra
  333. def _alloc_nursery(self):
  334. # the start of the nursery: we actually allocate a bit more for
  335. # the nursery than really needed, to simplify pointer arithmetic
  336. # in malloc_fixedsize_clear(). The few extra pages are never used
  337. # anyway so it doesn't even count.
  338. nursery = llarena.arena_malloc(self._nursery_memory_size(), 2)
  339. if not nursery:
  340. raise MemoryError("cannot allocate nursery")
  341. return nursery
  342. def allocate_nursery(self):
  343. debug_start("gc-set-nursery-size")
  344. debug_print("nursery size:", self.nursery_size)
  345. self.nursery = self._alloc_nursery()
  346. # the current position in the nursery:
  347. self.nursery_free = self.nursery
  348. # the end of the nursery:
  349. self.nursery_top = self.nursery + self.nursery_size
  350. # initialize the threshold
  351. self.min_heap_size = max(self.min_heap_size, self.nursery_size *
  352. self.major_collection_threshold)
  353. # the following two values are usually equal, but during raw mallocs
  354. # of arrays, next_major_collection_threshold is decremented to make
  355. # the next major collection arrive earlier.
  356. # See translator/c/test/test_newgc, test_nongc_attached_to_gc
  357. self.next_major_collection_initial = self.min_heap_size
  358. self.next_major_collection_threshold = self.min_heap_size
  359. self.set_major_threshold_from(0.0)
  360. debug_stop("gc-set-nursery-size")
  361. def set_major_threshold_from(self, threshold, reserving_size=0):
  362. # Set the next_major_collection_threshold.
  363. threshold_max = (self.next_major_collection_initial *
  364. self.growth_rate_max)
  365. if threshold > threshold_max:
  366. threshold = threshold_max
  367. #
  368. threshold += reserving_size
  369. if threshold < self.min_heap_size:
  370. threshold = self.min_heap_size
  371. #
  372. if self.max_heap_size > 0.0 and threshold > self.max_heap_size:
  373. threshold = self.max_heap_size
  374. bounded = True
  375. else:
  376. bounded = False
  377. #
  378. self.next_major_collection_initial = threshold
  379. self.next_major_collection_threshold = threshold
  380. return bounded
  381. def post_setup(self):
  382. # set up extra stuff for PYPY_GC_DEBUG.
  383. MovingGCBase.post_setup(self)
  384. if self.DEBUG and llarena.has_protect:
  385. # gc debug mode: allocate 23 nurseries instead of just 1,
  386. # and use them alternatively, while mprotect()ing the unused
  387. # ones to detect invalid access.
  388. debug_start("gc-debug")
  389. self.debug_rotating_nurseries = []
  390. for i in range(22):
  391. nurs = self._alloc_nursery()
  392. llarena.arena_protect(nurs, self._nursery_memory_size(), True)
  393. self.debug_rotating_nurseries.append(nurs)
  394. debug_print("allocated", len(self.debug_rotating_nurseries),
  395. "extra nurseries")
  396. debug_stop("gc-debug")
  397. def debug_rotate_nursery(self):
  398. if self.debug_rotating_nurseries is not None:
  399. debug_start("gc-debug")
  400. oldnurs = self.nursery
  401. llarena.arena_protect(oldnurs, self._nursery_memory_size(), True)
  402. self.debug_rotating_nurseries.append(oldnurs)
  403. #
  404. newnurs = self.debug_rotating_nurseries.pop(0)
  405. llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
  406. self.nursery = newnurs
  407. self.nursery_top = self.nursery + self.nursery_size
  408. debug_print("switching from nursery", oldnurs,
  409. "to nursery", self.nursery,
  410. "size", self.nursery_size)
  411. debug_stop("gc-debug")
  412. def malloc_fixedsize_clear(self, typeid, size,
  413. needs_finalizer=False,
  414. is_finalizer_light=False,
  415. contains_weakptr=False):
  416. size_gc_header = self.gcheaderbuilder.size_gc_header
  417. totalsize = size_gc_header + size
  418. rawtotalsize = raw_malloc_usage(totalsize)
  419. #
  420. # If the object needs a finalizer, ask for a rawmalloc.
  421. # The following check should be constant-folded.
  422. if needs_finalizer and not is_finalizer_light:
  423. ll_assert(not contains_weakptr,
  424. "'needs_finalizer' and 'contains_weakptr' both specified")
  425. obj = self.external_malloc(typeid, 0, can_make_young=False)
  426. self.objects_with_finalizers.append(obj)
  427. #
  428. # If totalsize is greater than nonlarge_max (which should never be
  429. # the case in practice), ask for a rawmalloc. The following check
  430. # should be constant-folded.
  431. elif rawtotalsize > self.nonlarge_max:
  432. ll_assert(not contains_weakptr,
  433. "'contains_weakptr' specified for a large object")
  434. obj = self.external_malloc(typeid, 0)
  435. #
  436. else:
  437. # If totalsize is smaller than minimal_size_in_nursery, round it
  438. # up. The following check should also be constant-folded.
  439. min_size = raw_malloc_usage(self.minimal_size_in_nursery)
  440. if rawtotalsize < min_size:
  441. totalsize = rawtotalsize = min_size
  442. #
  443. # Get the memory from the nursery. If there is not enough space
  444. # there, do a collect first.
  445. result = self.nursery_free
  446. self.nursery_free = result + totalsize
  447. if self.nursery_free > self.nursery_top:
  448. result = self.collect_and_reserve(totalsize)
  449. #
  450. # Build the object.
  451. llarena.arena_reserve(result, totalsize)
  452. obj = result + size_gc_header
  453. if is_finalizer_light:
  454. self.young_objects_with_light_finalizers.append(obj)
  455. self.init_gc_object(result, typeid, flags=0)
  456. #
  457. # If it is a weakref, record it (check constant-folded).
  458. if contains_weakptr:
  459. self.young_objects_with_weakrefs.append(obj)
  460. #
  461. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  462. def malloc_varsize_clear(self, typeid, length, size, itemsize,
  463. offset_to_length):
  464. size_gc_header = self.gcheaderbuilder.size_gc_header
  465. nonvarsize = size_gc_header + size
  466. #
  467. # Compute the maximal length that makes the object still
  468. # below 'nonlarge_max'. All the following logic is usually
  469. # constant-folded because self.nonlarge_max, size and itemsize
  470. # are all constants (the arguments are constant due to
  471. # inlining).
  472. maxsize = self.nonlarge_max - raw_malloc_usage(nonvarsize)
  473. if maxsize < 0:
  474. toobig = r_uint(0) # the nonvarsize alone is too big
  475. elif raw_malloc_usage(itemsize):
  476. toobig = r_uint(maxsize // raw_malloc_usage(itemsize)) + 1
  477. else:
  478. toobig = r_uint(sys.maxint) + 1
  479. if r_uint(length) >= r_uint(toobig):
  480. #
  481. # If the total size of the object would be larger than
  482. # 'nonlarge_max', then allocate it externally. We also
  483. # go there if 'length' is actually negative.
  484. obj = self.external_malloc(typeid, length)
  485. #
  486. else:
  487. # With the above checks we know now that totalsize cannot be more
  488. # than 'nonlarge_max'; in particular, the + and * cannot overflow.
  489. totalsize = nonvarsize + itemsize * length
  490. totalsize = llarena.round_up_for_allocation(totalsize)
  491. #
  492. # 'totalsize' should contain at least the GC header and
  493. # the length word, so it should never be smaller than
  494. # 'minimal_size_in_nursery'
  495. ll_assert(raw_malloc_usage(totalsize) >=
  496. raw_malloc_usage(self.minimal_size_in_nursery),
  497. "malloc_varsize_clear(): totalsize < minimalsize")
  498. #
  499. # Get the memory from the nursery. If there is not enough space
  500. # there, do a collect first.
  501. result = self.nursery_free
  502. self.nursery_free = result + totalsize
  503. if self.nursery_free > self.nursery_top:
  504. result = self.collect_and_reserve(totalsize)
  505. #
  506. # Build the object.
  507. llarena.arena_reserve(result, totalsize)
  508. self.init_gc_object(result, typeid, flags=0)
  509. #
  510. # Set the length and return the object.
  511. obj = result + size_gc_header
  512. (obj + offset_to_length).signed[0] = length
  513. #
  514. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  515. def collect(self, gen=1):
  516. """Do a minor (gen=0) or major (gen>0) collection."""
  517. self.minor_collection()
  518. if gen > 0:
  519. self.major_collection()
  520. def collect_and_reserve(self, totalsize):
  521. """To call when nursery_free overflows nursery_top.
  522. Do a minor collection, and possibly also a major collection,
  523. and finally reserve 'totalsize' bytes at the start of the
  524. now-empty nursery.
  525. """
  526. self.minor_collection()
  527. #
  528. if self.get_total_memory_used() > self.next_major_collection_threshold:
  529. self.major_collection()
  530. #
  531. # The nursery might not be empty now, because of
  532. # execute_finalizers(). If it is almost full again,
  533. # we need to fix it with another call to minor_collection().
  534. if self.nursery_free + totalsize > self.nursery_top:
  535. self.minor_collection()
  536. #
  537. result = self.nursery_free
  538. self.nursery_free = result + totalsize
  539. ll_assert(self.nursery_free <= self.nursery_top, "nursery overflow")
  540. #
  541. if self.debug_tiny_nursery >= 0: # for debugging
  542. if self.nursery_top - self.nursery_free > self.debug_tiny_nursery:
  543. self.nursery_free = self.nursery_top - self.debug_tiny_nursery
  544. #
  545. return result
  546. collect_and_reserve._dont_inline_ = True
  547. def external_malloc(self, typeid, length, can_make_young=True):
  548. """Allocate a large object using the ArenaCollection or
  549. raw_malloc(), possibly as an object with card marking enabled,
  550. if it has gc pointers in its var-sized part. 'length' should be
  551. specified as 0 if the object is not varsized. The returned
  552. object is fully initialized and zero-filled."""
  553. #
  554. # Compute the total size, carefully checking for overflows.
  555. size_gc_header = self.gcheaderbuilder.size_gc_header
  556. nonvarsize = size_gc_header + self.fixed_size(typeid)
  557. if length == 0:
  558. # this includes the case of fixed-size objects, for which we
  559. # should not even ask for the varsize_item_sizes().
  560. totalsize = nonvarsize
  561. elif length > 0:
  562. # var-sized allocation with at least one item
  563. itemsize = self.varsize_item_sizes(typeid)
  564. try:
  565. varsize = ovfcheck(itemsize * length)
  566. totalsize = ovfcheck(nonvarsize + varsize)
  567. except OverflowError:
  568. raise MemoryError
  569. else:
  570. # negative length! This likely comes from an overflow
  571. # earlier. We will just raise MemoryError here.
  572. raise MemoryError
  573. #
  574. # If somebody calls this function a lot, we must eventually
  575. # force a full collection.
  576. if (float(self.get_total_memory_used()) + raw_malloc_usage(totalsize) >
  577. self.next_major_collection_threshold):
  578. self.minor_collection()
  579. self.major_collection(raw_malloc_usage(totalsize))
  580. #
  581. # Check if the object would fit in the ArenaCollection.
  582. if raw_malloc_usage(totalsize) <= self.small_request_threshold:
  583. #
  584. # Yes. Round up 'totalsize' (it cannot overflow and it
  585. # must remain <= self.small_request_threshold.)
  586. totalsize = llarena.round_up_for_allocation(totalsize)
  587. ll_assert(raw_malloc_usage(totalsize) <=
  588. self.small_request_threshold,
  589. "rounding up made totalsize > small_request_threshold")
  590. #
  591. # Allocate from the ArenaCollection and clear the memory returned.
  592. result = self.ac.malloc(totalsize)
  593. llmemory.raw_memclear(result, totalsize)
  594. #
  595. # An object allocated from ArenaCollection is always old, even
  596. # if 'can_make_young'. The interesting case of 'can_make_young'
  597. # is for large objects, bigger than the 'large_objects' threshold,
  598. # which are raw-malloced but still young.
  599. extra_flags = GCFLAG_TRACK_YOUNG_PTRS
  600. #
  601. else:
  602. # No, so proceed to allocate it externally with raw_malloc().
  603. # Check if we need to introduce the card marker bits area.
  604. if (self.card_page_indices <= 0 # <- this check is constant-folded
  605. or not self.has_gcptr_in_varsize(typeid) or
  606. raw_malloc_usage(totalsize) <= self.nonlarge_max):
  607. #
  608. # In these cases, we don't want a card marker bits area.
  609. # This case also includes all fixed-size objects.
  610. cardheadersize = 0
  611. extra_flags = 0
  612. #
  613. else:
  614. # Reserve N extra words containing card bits before the object.
  615. extra_words = self.card_marking_words_for_length(length)
  616. cardheadersize = WORD * extra_words
  617. extra_flags = GCFLAG_HAS_CARDS | GCFLAG_TRACK_YOUNG_PTRS
  618. # if 'can_make_young', then we also immediately set
  619. # GCFLAG_CARDS_SET, but without adding the object to
  620. # 'old_objects_with_cards_set'. In this way it should
  621. # never be added to that list as long as it is young.
  622. if can_make_young:
  623. extra_flags |= GCFLAG_CARDS_SET
  624. #
  625. # Detect very rare cases of overflows
  626. if raw_malloc_usage(totalsize) > (sys.maxint - (WORD-1)
  627. - cardheadersize):
  628. raise MemoryError("rare case of overflow")
  629. #
  630. # Now we know that the following computations cannot overflow.
  631. # Note that round_up_for_allocation() is also needed to get the
  632. # correct number added to 'rawmalloced_total_size'.
  633. allocsize = (cardheadersize + raw_malloc_usage(
  634. llarena.round_up_for_allocation(totalsize)))
  635. #
  636. # Allocate the object using arena_malloc(), which we assume here
  637. # is just the same as raw_malloc(), but allows the extra
  638. # flexibility of saying that we have extra words in the header.
  639. # The memory returned is cleared by a raw_memclear().
  640. arena = llarena.arena_malloc(allocsize, 2)
  641. if not arena:
  642. raise MemoryError("cannot allocate large object")
  643. #
  644. # Reserve the card mark bits as a list of single bytes
  645. # (the loop is empty in C).
  646. i = 0
  647. while i < cardheadersize:
  648. llarena.arena_reserve(arena + i, llmemory.sizeof(lltype.Char))
  649. i += 1
  650. #
  651. # Reserve the actual object. (This is also a no-op in C).
  652. result = arena + cardheadersize
  653. llarena.arena_reserve(result, totalsize)
  654. #
  655. # Record the newly allocated object and its full malloced size.
  656. # The object is young or old depending on the argument.
  657. self.rawmalloced_total_size += r_uint(allocsize)
  658. if can_make_young:
  659. if not self.young_rawmalloced_objects:
  660. self.young_rawmalloced_objects = self.AddressDict()
  661. self.young_rawmalloced_objects.add(result + size_gc_header)
  662. else:
  663. self.old_rawmalloced_objects.append(result + size_gc_header)
  664. extra_flags |= GCFLAG_TRACK_YOUNG_PTRS
  665. #
  666. # Common code to fill the header and length of the object.
  667. self.init_gc_object(result, typeid, extra_flags)
  668. if self.is_varsize(typeid):
  669. offset_to_length = self.varsize_offset_to_length(typeid)
  670. (result + size_gc_header + offset_to_length).signed[0] = length
  671. return result + size_gc_header
  672. # ----------
  673. # Other functions in the GC API
  674. def set_max_heap_size(self, size):
  675. self.max_heap_size = float(size)
  676. if self.max_heap_size > 0.0:
  677. if self.max_heap_size < self.next_major_collection_initial:
  678. self.next_major_collection_initial = self.max_heap_size
  679. if self.max_heap_size < self.next_major_collection_threshold:
  680. self.next_major_collection_threshold = self.max_heap_size
  681. def raw_malloc_memory_pressure(self, sizehint):
  682. self.next_major_collection_threshold -= sizehint
  683. if self.next_major_collection_threshold < 0:
  684. # cannot trigger a full collection now, but we can ensure
  685. # that one will occur very soon
  686. self.nursery_free = self.nursery_top
  687. def can_malloc_nonmovable(self):
  688. return True
  689. def can_optimize_clean_setarrayitems(self):
  690. if self.card_page_indices > 0:
  691. return False
  692. return MovingGCBase.can_optimize_clean_setarrayitems(self)
  693. def can_move(self, obj):
  694. """Overrides the parent can_move()."""
  695. return self.is_in_nursery(obj)
  696. def shrink_array(self, obj, smallerlength):
  697. #
  698. # Only objects in the nursery can be "resized". Resizing them
  699. # means recording that they have a smaller size, so that when
  700. # moved out of the nursery, they will consume less memory.
  701. # In particular, an array with GCFLAG_HAS_CARDS is never resized.
  702. # Also, a nursery object with GCFLAG_HAS_SHADOW is not resized
  703. # either, as this would potentially loose part of the memory in
  704. # the already-allocated shadow.
  705. if not self.is_in_nursery(obj):
  706. return False
  707. if self.header(obj).tid & GCFLAG_HAS_SHADOW:
  708. return False
  709. #
  710. size_gc_header = self.gcheaderbuilder.size_gc_header
  711. typeid = self.get_type_id(obj)
  712. totalsmallersize = (
  713. size_gc_header + self.fixed_size(typeid) +
  714. self.varsize_item_sizes(typeid) * smallerlength)
  715. llarena.arena_shrink_obj(obj - size_gc_header, totalsmallersize)
  716. #
  717. offset_to_length = self.varsize_offset_to_length(typeid)
  718. (obj + offset_to_length).signed[0] = smallerlength
  719. return True
  720. def malloc_fixedsize_nonmovable(self, typeid):
  721. obj = self.external_malloc(typeid, 0)
  722. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  723. def malloc_varsize_nonmovable(self, typeid, length):
  724. obj = self.external_malloc(typeid, length)
  725. return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
  726. def malloc_nonmovable(self, typeid, length, zero):
  727. # helper for testing, same as GCBase.malloc
  728. return self.external_malloc(typeid, length or 0) # None -> 0
  729. # ----------
  730. # Simple helpers
  731. def get_type_id(self, obj):
  732. tid = self.header(obj).tid
  733. return llop.extract_ushort(llgroup.HALFWORD, tid)
  734. def combine(self, typeid16, flags):
  735. return llop.combine_ushort(lltype.Signed, typeid16, flags)
  736. def init_gc_object(self, addr, typeid16, flags=0):
  737. # The default 'flags' is zero. The flags GCFLAG_NO_xxx_PTRS
  738. # have been chosen to allow 'flags' to be zero in the common
  739. # case (hence the 'NO' in their name).
  740. hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
  741. hdr.tid = self.combine(typeid16, flags)
  742. def init_gc_object_immortal(self, addr, typeid16, flags=0):
  743. # For prebuilt GC objects, the flags must contain
  744. # GCFLAG_NO_xxx_PTRS, at least initially.
  745. flags |= GCFLAG_NO_HEAP_PTRS | GCFLAG_TRACK_YOUNG_PTRS
  746. self.init_gc_object(addr, typeid16, flags)
  747. def is_in_nursery(self, addr):
  748. ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0,
  749. "odd-valued (i.e. tagged) pointer unexpected here")
  750. return self.nursery <= addr < self.nursery_top
  751. def appears_to_be_young(self, addr):
  752. # "is a valid addr to a young object?"
  753. # but it's ok to occasionally return True accidentally.
  754. # Maybe the best implementation would be a bloom filter
  755. # of some kind instead of the dictionary lookup that is
  756. # sometimes done below. But the expected common answer
  757. # is "Yes" because addr points to the nursery, so it may
  758. # not be useful to optimize the other case too much.
  759. #
  760. # First, if 'addr' appears to be a pointer to some place within
  761. # the nursery, return True
  762. if not self.translated_to_c:
  763. # When non-translated, filter out tagged pointers explicitly.
  764. # When translated, it may occasionally give a wrong answer
  765. # of True if 'addr' is a tagged pointer with just the wrong value.
  766. if not self.is_valid_gc_object(addr):
  767. return False
  768. if self.nursery <= addr < self.nursery_top:
  769. return True # addr is in the nursery
  770. #
  771. # Else, it may be in the set 'young_rawmalloced_objects'
  772. return (bool(self.young_rawmalloced_objects) and
  773. self.young_rawmalloced_objects.contains(addr))
  774. appears_to_be_young._always_inline_ = True
  775. def debug_is_old_object(self, addr):
  776. return (self.is_valid_gc_object(addr)
  777. and not self.appears_to_be_young(addr))
  778. def is_forwarded(self, obj):
  779. """Returns True if the nursery obj is marked as forwarded.
  780. Implemented a bit obscurely by checking an unrelated flag
  781. that can never be set on a young object -- except if tid == -42.
  782. """
  783. assert self.is_in_nursery(obj)
  784. tid = self.header(obj).tid
  785. result = (tid & GCFLAG_FINALIZATION_ORDERING != 0)
  786. if result:
  787. ll_assert(tid == -42, "bogus header for young obj")
  788. else:
  789. ll_assert(bool(tid), "bogus header (1)")
  790. ll_assert(tid & ~TID_MASK == 0, "bogus header (2)")
  791. return result
  792. def get_forwarding_address(self, obj):
  793. return llmemory.cast_adr_to_ptr(obj, FORWARDSTUBPTR).forw
  794. def get_total_memory_used(self):
  795. """Return the total memory used, not counting any object in the
  796. nursery: only objects in the ArenaCollection or raw-malloced.
  797. """
  798. return self.ac.total_memory_used + self.rawmalloced_total_size
  799. def card_marking_words_for_length(self, length):
  800. # --- Unoptimized version:
  801. #num_bits = ((length-1) >> self.card_page_shift) + 1
  802. #return (num_bits + (LONG_BIT - 1)) >> LONG_BIT_SHIFT
  803. # --- Optimized version:
  804. return intmask(
  805. ((r_uint(length) + r_uint((LONG_BIT << self.card_page_shift) - 1)) >>
  806. (self.card_page_shift + LONG_BIT_SHIFT)))
  807. def card_marking_bytes_for_length(self, length):
  808. # --- Unoptimized version:
  809. #num_bits = ((length-1) >> self.card_page_shift) + 1
  810. #return (num_bits + 7) >> 3
  811. # --- Optimized version:
  812. return intmask(
  813. ((r_uint(length) + r_uint((8 << self.card_page_shift) - 1)) >>
  814. (self.card_page_shift + 3)))
  815. def debug_check_consistency(self):
  816. if self.DEBUG:
  817. ll_assert(not self.young_rawmalloced_objects,
  818. "young raw-malloced objects in a major collection")
  819. ll_assert(not self.young_objects_with_weakrefs.non_empty(),
  820. "young objects with weakrefs in a major collection")
  821. MovingGCBase.debug_check_consistency(self)
  822. def debug_check_object(self, obj):
  823. # after a minor or major collection, no object should be in the nursery
  824. ll_assert(not self.is_in_nursery(obj),
  825. "object in nursery after collection")
  826. # similarily, all objects should have this flag:
  827. ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS,
  828. "missing GCFLAG_TRACK_YOUNG_PTRS")
  829. # the GCFLAG_VISITED should not be set between collections
  830. ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0,
  831. "unexpected GCFLAG_VISITED")
  832. # the GCFLAG_FINALIZATION_ORDERING should not be set between coll.
  833. ll_assert(self.header(obj).tid & GCFLAG_FINALIZATION_ORDERING == 0,
  834. "unexpected GCFLAG_FINALIZATION_ORDERING")
  835. # the GCFLAG_CARDS_SET should not be set between collections
  836. ll_assert(self.header(obj).tid & GCFLAG_CARDS_SET == 0,
  837. "unexpected GCFLAG_CARDS_SET")
  838. # if the GCFLAG_HAS_CARDS is set, check that all bits are zero now
  839. if self.header(obj).tid & GCFLAG_HAS_CARDS:
  840. if self.card_page_indices <= 0:
  841. ll_assert(False, "GCFLAG_HAS_CARDS but not using card marking")
  842. return
  843. typeid = self.get_type_id(obj)
  844. ll_assert(self.has_gcptr_in_varsize(typeid),
  845. "GCFLAG_HAS_CARDS but not has_gcptr_in_varsize")
  846. ll_assert(self.header(obj).tid & GCFLAG_NO_HEAP_PTRS == 0,
  847. "GCFLAG_HAS_CARDS && GCFLAG_NO_HEAP_PTRS")
  848. offset_to_length = self.varsize_offset_to_length(typeid)
  849. length = (obj + offset_to_length).signed[0]
  850. extra_words = self.card_marking_words_for_length(length)
  851. #
  852. size_gc_header = self.gcheaderbuilder.size_gc_header
  853. p = llarena.getfakearenaaddress(obj - size_gc_header)
  854. i = extra_words * WORD
  855. while i > 0:
  856. p -= 1
  857. ll_assert(p.char[0] == '\x00',
  858. "the card marker bits are not cleared")
  859. i -= 1
  860. # ----------
  861. # Write barrier
  862. # for the JIT: a minimal description of the write_barrier() method
  863. # (the JIT assumes it is of the shape
  864. # "if addr_struct.int0 & JIT_WB_IF_FLAG: remember_young_pointer()")
  865. JIT_WB_IF_FLAG = GCFLAG_TRACK_YOUNG_PTRS
  866. # for the JIT to generate custom code corresponding to the array
  867. # write barrier for the simplest case of cards. If JIT_CARDS_SET
  868. # is already set on an object, it will execute code like this:
  869. # MOV eax, index
  870. # SHR eax, JIT_WB_CARD_PAGE_SHIFT
  871. # XOR eax, -8
  872. # BTS [object], eax
  873. if TRANSLATION_PARAMS['card_page_indices'] > 0:
  874. JIT_WB_CARDS_SET = GCFLAG_CARDS_SET
  875. JIT_WB_CARD_PAGE_SHIFT = 1
  876. while ((1 << JIT_WB_CARD_PAGE_SHIFT) !=
  877. TRANSLATION_PARAMS['card_page_indices']):
  878. JIT_WB_CARD_PAGE_SHIFT += 1
  879. @classmethod
  880. def JIT_max_size_of_young_obj(cls):
  881. return cls.TRANSLATION_PARAMS['large_object']
  882. @classmethod
  883. def JIT_minimal_size_in_nursery(cls):
  884. return cls.minimal_size_in_nursery
  885. def write_barrier(self, newvalue, addr_struct):
  886. if self.header(addr_struct).tid & GCFLAG_TRACK_YOUNG_PTRS:
  887. self.remember_young_pointer(addr_struct, newvalue)
  888. def write_barrier_from_array(self, newvalue, addr_array, index):
  889. if self.header(addr_array).tid & GCFLAG_TRACK_YOUNG_PTRS:
  890. if self.card_page_indices > 0: # <- constant-folded
  891. self.remember_young_pointer_from_array2(addr_array, index)
  892. else:
  893. self.remember_young_pointer(addr_array, newvalue)
  894. def _init_writebarrier_logic(self):
  895. DEBUG = self.DEBUG
  896. # The purpose of attaching remember_young_pointer to the instance
  897. # instead of keeping it as a regular method is to help the JIT call it.
  898. # Additionally, it makes the code in write_barrier() marginally smaller
  899. # (which is important because it is inlined *everywhere*).
  900. # For x86, there is also an extra requirement: when the JIT calls
  901. # remember_young_pointer(), it assumes that it will not touch the SSE
  902. # registers, so it does not save and restore them (that's a *hack*!).
  903. def remember_young_pointer(addr_struct, newvalue):
  904. # 'addr_struct' is the address of the object in which we write.
  905. # 'newvalue' is the address that we are going to write in there.
  906. # We know that 'addr_struct' has GCFLAG_TRACK_YOUNG_PTRS so far.
  907. #
  908. if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
  909. ll_assert(self.debug_is_old_object(addr_struct) or
  910. self.header(addr_struct).tid & GCFLAG_HAS_CARDS != 0,
  911. "young object with GCFLAG_TRACK_YOUNG_PTRS and no cards")
  912. #
  913. # If it seems that what we are writing is a pointer to a young obj
  914. # (as checked with appears_to_be_young()), then we need
  915. # to remove the flag GCFLAG_TRACK_YOUNG_PTRS and add the object
  916. # to the list 'old_objects_pointing_to_young'. We know that
  917. # 'addr_struct' cannot be in the nursery, because nursery objects
  918. # never have the flag GCFLAG_TRACK_YOUNG_PTRS to start with.
  919. objhdr = self.header(addr_struct)
  920. if self.appears_to_be_young(newvalue):
  921. self.old_objects_pointing_to_young.append(addr_struct)
  922. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  923. #
  924. # Second part: if 'addr_struct' is actually a prebuilt GC
  925. # object and it's the first time we see a write to it, we
  926. # add it to the list 'prebuilt_root_objects'. Note that we
  927. # do it even in the (rare?) case of 'addr' being NULL or another
  928. # prebuilt object, to simplify code.
  929. if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
  930. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  931. self.prebuilt_root_objects.append(addr_struct)
  932. remember_young_pointer._dont_inline_ = True
  933. self.remember_young_pointer = remember_young_pointer
  934. #
  935. if self.card_page_indices > 0:
  936. self._init_writebarrier_with_card_marker()
  937. def _init_writebarrier_with_card_marker(self):
  938. DEBUG = self.DEBUG
  939. def remember_young_pointer_from_array2(addr_array, index):
  940. # 'addr_array' is the address of the object in which we write,
  941. # which must have an array part; 'index' is the index of the
  942. # item that is (or contains) the pointer that we write.
  943. # We know that 'addr_array' has GCFLAG_TRACK_YOUNG_PTRS so far.
  944. #
  945. objhdr = self.header(addr_array)
  946. if objhdr.tid & GCFLAG_HAS_CARDS == 0:
  947. #
  948. if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
  949. ll_assert(self.debug_is_old_object(addr_array),
  950. "young array with no card but GCFLAG_TRACK_YOUNG_PTRS")
  951. #
  952. # no cards, use default logic. Mostly copied from above.
  953. self.old_objects_pointing_to_young.append(addr_array)
  954. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  955. if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
  956. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  957. self.prebuilt_root_objects.append(addr_array)
  958. return
  959. #
  960. # 'addr_array' is a raw_malloc'ed array with card markers
  961. # in front. Compute the index of the bit to set:
  962. bitindex = index >> self.card_page_shift
  963. byteindex = bitindex >> 3
  964. bitmask = 1 << (bitindex & 7)
  965. #
  966. # If the bit is already set, leave now.
  967. addr_byte = self.get_card(addr_array, byteindex)
  968. byte = ord(addr_byte.char[0])
  969. if byte & bitmask:
  970. return
  971. #
  972. # We set the flag (even if the newly written address does not
  973. # actually point to the nursery, which seems to be ok -- actually
  974. # it seems more important that remember_young_pointer_from_array2()
  975. # does not take 3 arguments).
  976. addr_byte.char[0] = chr(byte | bitmask)
  977. #
  978. if objhdr.tid & GCFLAG_CARDS_SET == 0:
  979. self.old_objects_with_cards_set.append(addr_array)
  980. objhdr.tid |= GCFLAG_CARDS_SET
  981. remember_young_pointer_from_array2._dont_inline_ = True
  982. assert self.card_page_indices > 0
  983. self.remember_young_pointer_from_array2 = (
  984. remember_young_pointer_from_array2)
  985. # xxx trying it out for the JIT: a 3-arguments version of the above
  986. def remember_young_pointer_from_array3(addr_array, index, newvalue):
  987. objhdr = self.header(addr_array)
  988. #
  989. # a single check for the common case of neither GCFLAG_HAS_CARDS
  990. # nor GCFLAG_NO_HEAP_PTRS
  991. if objhdr.tid & (GCFLAG_HAS_CARDS | GCFLAG_NO_HEAP_PTRS) == 0:
  992. # common case: fast path, jump to the end of the function
  993. pass
  994. elif objhdr.tid & GCFLAG_HAS_CARDS == 0:
  995. # no cards, but GCFLAG_NO_HEAP_PTRS is set.
  996. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  997. self.prebuilt_root_objects.append(addr_array)
  998. # jump to the end of the function
  999. else:
  1000. # case with cards.
  1001. #
  1002. # If the newly written address does not actually point to a
  1003. # young object, leave now.
  1004. if not self.appears_to_be_young(newvalue):
  1005. return
  1006. #
  1007. # 'addr_array' is a raw_malloc'ed array with card markers
  1008. # in front. Compute the index of the bit to set:
  1009. bitindex = index >> self.card_page_shift
  1010. byteindex = bitindex >> 3
  1011. bitmask = 1 << (bitindex & 7)
  1012. #
  1013. # If the bit is already set, leave now.
  1014. addr_byte = self.get_card(addr_array, byteindex)
  1015. byte = ord(addr_byte.char[0])
  1016. if byte & bitmask:
  1017. return
  1018. addr_byte.char[0] = chr(byte | bitmask)
  1019. #
  1020. if objhdr.tid & GCFLAG_CARDS_SET == 0:
  1021. self.old_objects_with_cards_set.append(addr_array)
  1022. objhdr.tid |= GCFLAG_CARDS_SET
  1023. return
  1024. #
  1025. # Logic for the no-cards case, put here to minimize the number
  1026. # of checks done at the start of the function
  1027. if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
  1028. ll_assert(self.debug_is_old_object(addr_array),
  1029. "young array with no card but GCFLAG_TRACK_YOUNG_PTRS")
  1030. #
  1031. if self.appears_to_be_young(newvalue):
  1032. self.old_objects_pointing_to_young.append(addr_array)
  1033. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  1034. remember_young_pointer_from_array3._dont_inline_ = True
  1035. assert self.card_page_indices > 0
  1036. self.remember_young_pointer_from_array3 = (
  1037. remember_young_pointer_from_array3)
  1038. def get_card(self, obj, byteindex):
  1039. size_gc_header = self.gcheaderbuilder.size_gc_header
  1040. addr_byte = obj - size_gc_header
  1041. return llarena.getfakearenaaddress(addr_byte) + (~byteindex)
  1042. def assume_young_pointers(self, addr_struct):
  1043. """Called occasionally by the JIT to mean ``assume that 'addr_struct'
  1044. may now contain young pointers.''
  1045. """
  1046. objhdr = self.header(addr_struct)
  1047. if objhdr.tid & GCFLAG_TRACK_YOUNG_PTRS:
  1048. self.old_objects_pointing_to_young.append(addr_struct)
  1049. objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  1050. #
  1051. if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
  1052. objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  1053. self.prebuilt_root_objects.append(addr_struct)
  1054. def writebarrier_before_copy(self, source_addr, dest_addr,
  1055. source_start, dest_start, length):
  1056. """ This has the same effect as calling writebarrier over
  1057. each element in dest copied from source, except it might reset
  1058. one of the following flags a bit too eagerly, which means we'll have
  1059. a bit more objects to track, but being on the safe side.
  1060. """
  1061. source_hdr = self.header(source_addr)
  1062. dest_hdr = self.header(dest_addr)
  1063. if dest_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1064. return True
  1065. # ^^^ a fast path of write-barrier
  1066. #
  1067. if source_hdr.tid & GCFLAG_HAS_CARDS != 0:
  1068. #
  1069. if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1070. # The source object may have random young pointers.
  1071. # Return False to mean "do it manually in ll_arraycopy".
  1072. return False
  1073. #
  1074. if source_hdr.tid & GCFLAG_CARDS_SET == 0:
  1075. # The source object has no young pointers at all. Done.
  1076. return True
  1077. #
  1078. if dest_hdr.tid & GCFLAG_HAS_CARDS == 0:
  1079. # The dest object doesn't have cards. Do it manually.
  1080. return False
  1081. #
  1082. if source_start != 0 or dest_start != 0:
  1083. # Misaligned. Do it manually.
  1084. return False
  1085. #
  1086. self.manually_copy_card_bits(source_addr, dest_addr, length)
  1087. return True
  1088. #
  1089. if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1090. # there might be in source a pointer to a young object
  1091. self.old_objects_pointing_to_young.append(dest_addr)
  1092. dest_hdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
  1093. #
  1094. if dest_hdr.tid & GCFLAG_NO_HEAP_PTRS:
  1095. if source_hdr.tid & GCFLAG_NO_HEAP_PTRS == 0:
  1096. dest_hdr.tid &= ~GCFLAG_NO_HEAP_PTRS
  1097. self.prebuilt_root_objects.append(dest_addr)
  1098. return True
  1099. def manually_copy_card_bits(self, source_addr, dest_addr, length):
  1100. # manually copy the individual card marks from source to dest
  1101. bytes = self.card_marking_bytes_for_length(length)
  1102. #
  1103. anybyte = 0
  1104. i = 0
  1105. while i < bytes:
  1106. addr_srcbyte = self.get_card(source_addr, i)
  1107. addr_dstbyte = self.get_card(dest_addr, i)
  1108. byte = ord(addr_srcbyte.char[0])
  1109. anybyte |= byte
  1110. addr_dstbyte.char[0] = chr(ord(addr_dstbyte.char[0]) | byte)
  1111. i += 1
  1112. #
  1113. if anybyte:
  1114. dest_hdr = self.header(dest_addr)
  1115. if dest_hdr.tid & GCFLAG_CARDS_SET == 0:
  1116. self.old_objects_with_cards_set.append(dest_addr)
  1117. dest_hdr.tid |= GCFLAG_CARDS_SET
  1118. # ----------
  1119. # Nursery collection
  1120. def minor_collection(self):
  1121. """Perform a minor collection: find the objects from the nursery
  1122. that remain alive and move them out."""
  1123. #
  1124. debug_start("gc-minor")
  1125. #
  1126. # Before everything else, remove from 'old_objects_pointing_to_young'
  1127. # the young arrays.
  1128. if self.young_rawmalloced_objects:
  1129. self.remove_young_arrays_from_old_objects_pointing_to_young()
  1130. #
  1131. # First, find the roots that point to young objects. All nursery
  1132. # objects found are copied out of the nursery, and the occasional
  1133. # young raw-malloced object is flagged with GCFLAG_VISITED.
  1134. # Note that during this step, we ignore references to further
  1135. # young objects; only objects directly referenced by roots
  1136. # are copied out or flagged. They are also added to the list
  1137. # 'old_objects_pointing_to_young'.
  1138. self.collect_roots_in_nursery()
  1139. #
  1140. while True:
  1141. # If we are using card marking, do a partial trace of the arrays
  1142. # that are flagged with GCFLAG_CARDS_SET.
  1143. if self.card_page_indices > 0:
  1144. self.collect_cardrefs_to_nursery()
  1145. #
  1146. # Now trace objects from 'old_objects_pointing_to_young'.
  1147. # All nursery objects they reference are copied out of the
  1148. # nursery, and again added to 'old_objects_pointing_to_young'.
  1149. # All young raw-malloced object found are flagged GCFLAG_VISITED.
  1150. # We proceed until 'old_objects_pointing_to_young' is empty.
  1151. self.collect_oldrefs_to_nursery()
  1152. #
  1153. # We have to loop back if collect_oldrefs_to_nursery caused
  1154. # new objects to show up in old_objects_with_cards_set
  1155. if self.card_page_indices > 0:
  1156. if self.old_objects_with_cards_set.non_empty():
  1157. continue
  1158. break
  1159. #
  1160. # Now all live nursery objects should be out. Update the young
  1161. # weakrefs' targets.
  1162. if self.young_objects_with_weakrefs.non_empty():
  1163. self.invalidate_young_weakrefs()
  1164. if self.young_objects_with_light_finalizers.non_empty():
  1165. self.deal_with_young_objects_with_finalizers()
  1166. #
  1167. # Clear this mapping.
  1168. if self.nursery_objects_shadows.length() > 0:
  1169. self.nursery_objects_shadows.clear()
  1170. #
  1171. # Walk the list of young raw-malloced objects, and either free
  1172. # them or make them old.
  1173. if self.young_rawmalloced_objects:
  1174. self.free_young_rawmalloced_objects()
  1175. #
  1176. # All live nursery objects are out, and the rest dies. Fill
  1177. # the whole nursery with zero and reset the current nursery pointer.
  1178. llarena.arena_reset(self.nursery, self.nursery_size, 2)
  1179. self.debug_rotate_nursery()
  1180. self.nursery_free = self.nursery
  1181. #
  1182. debug_print("minor collect, total memory used:",
  1183. self.get_total_memory_used())
  1184. if self.DEBUG >= 2:
  1185. self.debug_check_consistency() # expensive!
  1186. debug_stop("gc-minor")
  1187. def collect_roots_in_nursery(self):
  1188. # we don't need to trace prebuilt GcStructs during a minor collect:
  1189. # if a prebuilt GcStruct contains a pointer to a young object,
  1190. # then the write_barrier must have ensured that the prebuilt
  1191. # GcStruct is in the list self.old_objects_pointing_to_young.
  1192. debug_start("gc-minor-walkroots")
  1193. self.root_walker.walk_roots(
  1194. MiniMarkGC._trace_drag_out1, # stack roots
  1195. MiniMarkGC._trace_drag_out1, # static in prebuilt non-gc
  1196. None) # static in prebuilt gc
  1197. debug_stop("gc-minor-walkroots")
  1198. def collect_cardrefs_to_nursery(self):
  1199. size_gc_header = self.gcheaderbuilder.size_gc_header
  1200. oldlist = self.old_objects_with_cards_set
  1201. while oldlist.non_empty():
  1202. obj = oldlist.pop()
  1203. #
  1204. # Remove the GCFLAG_CARDS_SET flag.
  1205. ll_assert(self.header(obj).tid & GCFLAG_CARDS_SET != 0,
  1206. "!GCFLAG_CARDS_SET but object in 'old_objects_with_cards_set'")
  1207. self.header(obj).tid &= ~GCFLAG_CARDS_SET
  1208. #
  1209. # Get the number of card marker bytes in the header.
  1210. typeid = self.get_type_id(obj)
  1211. offset_to_length = self.varsize_offset_to_length(typeid)
  1212. length = (obj + offset_to_length).signed[0]
  1213. bytes = self.card_marking_bytes_for_length(length)
  1214. p = llarena.getfakearenaaddress(obj - size_gc_header)
  1215. #
  1216. # If the object doesn't have GCFLAG_TRACK_YOUNG_PTRS, then it
  1217. # means that it is in 'old_objects_pointing_to_young' and
  1218. # will be fully traced by collect_oldrefs_to_nursery() just
  1219. # afterwards.
  1220. if self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
  1221. #
  1222. # In that case, we just have to reset all card bits.
  1223. while bytes > 0:
  1224. p -= 1
  1225. p.char[0] = '\x00'
  1226. bytes -= 1
  1227. #
  1228. else:
  1229. # Walk the bytes encoding the card marker bits, and for
  1230. # each bit set, call trace_and_drag_out_of_nursery_partial().
  1231. interval_start = 0
  1232. while bytes > 0:
  1233. p -= 1
  1234. cardbyte = ord(p.char[0])
  1235. p.char[0] = '\x00' # reset the bits
  1236. bytes -= 1
  1237. next_byte_start = interval_start + 8*self.card_page_indices
  1238. #
  1239. while cardbyte != 0:
  1240. interval_stop = interval_start + self.card_page_indices
  1241. #
  1242. if cardbyte & 1:
  1243. if interval_stop > length:
  1244. interval_stop = length
  1245. ll_assert(cardbyte <= 1 and bytes == 0,
  1246. "premature end of object")
  1247. self.trace_and_drag_out_of_nursery_partial(
  1248. obj, interval_start, interval_stop)
  1249. #
  1250. interval_start = interval_stop
  1251. cardbyte >>= 1
  1252. interval_start = next_byte_start
  1253. def collect_oldrefs_to_nursery(self):
  1254. # Follow the old_objects_pointing_to_young list and move the
  1255. # young objects they point to out of the nursery.
  1256. oldlist = self.old_objects_pointing_to_young
  1257. while oldlist.non_empty():
  1258. obj = oldlist.pop()
  1259. #
  1260. # Check that the flags are correct: we must not have
  1261. # GCFLAG_TRACK_YOUNG_PTRS so far.
  1262. ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS == 0,
  1263. "old_objects_pointing_to_young contains obj with "
  1264. "GCFLAG_TRACK_YOUNG_PTRS")
  1265. #
  1266. # Add the flag GCFLAG_TRACK_YOUNG_PTRS. All live objects should
  1267. # have this flag set after a nursery collection.
  1268. self.header(obj).tid |= GCFLAG_TRACK_YOUNG_PTRS
  1269. #
  1270. # Trace the 'obj' to replace pointers to nursery with pointers
  1271. # outside the nursery, possibly forcing nursery objects out
  1272. # and adding them to 'old_objects_pointing_to_young' as well.
  1273. self.trace_and_drag_out_of_nursery(obj)
  1274. def trace_and_drag_out_of_nursery(self, obj):
  1275. """obj must not be in the nursery. This copies all the
  1276. young objects it references out of the nursery.
  1277. """
  1278. self.trace(obj, self._trace_drag_out, None)
  1279. def trace_and_drag_out_of_nursery_partial(self, obj, start, stop):
  1280. """Like trace_and_drag_out_of_nursery(), but limited to the array
  1281. indices in range(start, stop).
  1282. """
  1283. ll_assert(start < stop, "empty or negative range "
  1284. "in trace_and_drag_out_of_nursery_partial()")
  1285. #print 'trace_partial:', start, stop, '\t', obj
  1286. self.trace_partial(obj, start, stop, self._trace_drag_out, None)
  1287. def _trace_drag_out1(self, root):
  1288. self._trace_drag_out(root, None)
  1289. def _trace_drag_out(self, root, ignored):
  1290. obj = root.address[0]
  1291. #print '_trace_drag_out(%x: %r)' % (hash(obj.ptr._obj), obj)
  1292. #
  1293. # If 'obj' is not in the nursery, nothing to change -- expect
  1294. # that we must set GCFLAG_VISITED on young raw-malloced objects.
  1295. if not self.is_in_nursery(obj):
  1296. # cache usage trade-off: I think that it is a better idea to
  1297. # check if 'obj' is in young_rawmalloced_objects with an access
  1298. # to t