[pypy-commit] pypy incremental-gc: More fixes, trying to minimize the diff with minimark.py.
arigo
noreply at buildbot.pypy.org
Fri Oct 11 19:21:58 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: incremental-gc
Changeset: r67325:3fb6c1306302
Date: 2013-10-11 19:01 +0200
http://bitbucket.org/pypy/pypy/changeset/3fb6c1306302/
Log: More fixes, trying to minimize the diff with minimark.py.
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -227,7 +227,7 @@
# value of 128 means that card pages are 512 bytes (1024 on 64-bits)
# in regular arrays of pointers; more in arrays whose items are
# larger. A value of 0 disables card marking.
- "card_page_indices": 0, # XXX was 128,
+ "card_page_indices": 128,
# Objects whose total size is at least 'large_object' bytes are
# allocated out of the nursery immediately, as old objects. The
@@ -269,9 +269,6 @@
self.max_heap_size_already_raised = False
self.max_delta = float(r_uint(-1))
#
- if card_page_indices != 0:
- import py
- py.test.skip("cards unsupported")
self.card_page_indices = card_page_indices
if self.card_page_indices > 0:
self.card_page_shift = 0
@@ -642,16 +639,10 @@
def collect(self, gen=1):
"""Do a minor (gen=0) or full major (gen>0) collection."""
- self.minor_collection()
if gen > 0:
- #
- # First, finish the current major gc, if there is one in progress.
- # This is a no-op if the gc_state is already STATE_SCANNING.
- self.gc_step_until(STATE_SCANNING)
- #
- # Then do a complete collection again.
- self.gc_step_until(STATE_MARKING)
- self.gc_step_until(STATE_SCANNING)
+ self.minor_and_major_collection()
+ else:
+ self.minor_collection()
def move_nursery_top(self, totalsize):
size = self.nursery_cleanup
@@ -1000,7 +991,6 @@
"""
return self.ac.total_memory_used + self.rawmalloced_total_size
-
def card_marking_words_for_length(self, length):
# --- Unoptimized version:
#num_bits = ((length-1) >> self.card_page_shift) + 1
@@ -1061,7 +1051,9 @@
self.trace(obj, self._debug_check_not_white, None)
# During marking, all visited (black) objects should always have
# the GCFLAG_TRACK_YOUNG_PTRS flag set, for the write barrier to
- # trigger --- at least if they contain any gc ptr
+ # trigger --- at least if they contain any gc ptr. We are just
+ # after a minor or major collection here, so we can't see the
+ # object state VISITED & ~WRITE_BARRIER.
typeid = self.get_type_id(obj)
if self.has_gcptr(typeid):
ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
@@ -1167,7 +1159,10 @@
def write_barrier_from_array(self, addr_array, index):
if self.header(addr_array).tid & GCFLAG_TRACK_YOUNG_PTRS:
- self.remember_young_pointer(addr_array)
+ if self.card_page_indices > 0:
+ self.remember_young_pointer_from_array2(addr_array, index)
+ else:
+ self.remember_young_pointer(addr_array)
def _init_writebarrier_logic(self):
DEBUG = self.DEBUG
@@ -1286,19 +1281,6 @@
return llarena.getfakearenaaddress(addr_byte) + (~byteindex)
- def assume_young_pointers(self, addr_struct):
- """Called occasionally by the JIT to mean ``assume that 'addr_struct'
- may now contain young pointers.''
- """
- objhdr = self.header(addr_struct)
- if objhdr.tid & GCFLAG_TRACK_YOUNG_PTRS:
- self.old_objects_pointing_to_young.append(addr_struct)
- objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS
- #
- if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
- objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
- self.prebuilt_root_objects.append(addr_struct)
-
def writebarrier_before_copy(self, source_addr, dest_addr,
source_start, dest_start, length):
""" This has the same effect as calling writebarrier over
@@ -1313,8 +1295,6 @@
# ^^^ a fast path of write-barrier
#
if source_hdr.tid & GCFLAG_HAS_CARDS != 0:
- if self.card_page_indices == 0:
- return False # shouldn't have GCFLAG_HAS_CARDS then...
#
if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
# The source object may have random young pointers.
@@ -1349,6 +1329,7 @@
def manually_copy_card_bits(self, source_addr, dest_addr, length):
# manually copy the individual card marks from source to dest
+ assert self.card_page_indices > 0
bytes = self.card_marking_bytes_for_length(length)
#
anybyte = 0
@@ -1538,9 +1519,9 @@
# If the incremental major collection is currently at
# STATE_MARKING, then we must add to 'objects_to_trace' all
# black objects that go through 'old_objects_pointing_to_young'.
+ # This basically turns them gray again.
if state_is_marking and self.header(obj).tid & GCFLAG_VISITED != 0:
self.header(obj).tid &= ~GCFLAG_VISITED
- self.header(obj).tid |= GCFLAG_GRAY
self.objects_to_trace.append(obj)
#
# Trace the 'obj' to replace pointers to nursery with pointers
@@ -1721,6 +1702,15 @@
old.append(new.pop())
new.delete()
+ def minor_and_major_collection(self):
+ # First, finish the current major gc, if there is one in progress.
+ # This is a no-op if the gc_state is already STATE_SCANNING.
+ self.gc_step_until(STATE_SCANNING)
+ #
+ # Then do a complete collection again.
+ self.gc_step_until(STATE_MARKING)
+ self.gc_step_until(STATE_SCANNING)
+
def gc_step_until(self, state, reserving_size=0):
while self.gc_state != state:
self.minor_collection()
@@ -1854,16 +1844,16 @@
size_gc_header = self.gcheaderbuilder.size_gc_header
obj = hdr + size_gc_header
if self.header(obj).tid & GCFLAG_VISITED:
- self.header(obj).tid &= ~(GCFLAG_VISITED|GCFLAG_GRAY)
+ self.header(obj).tid &= ~GCFLAG_VISITED
return False # survives
return True # dies
def _reset_gcflag_visited(self, obj, ignored):
- self.header(obj).tid &= ~(GCFLAG_VISITED|GCFLAG_GRAY)
+ self.header(obj).tid &= ~GCFLAG_VISITED
def free_rawmalloced_object_if_unvisited(self, obj):
if self.header(obj).tid & GCFLAG_VISITED:
- self.header(obj).tid &= ~(GCFLAG_VISITED|GCFLAG_GRAY) # survives
+ self.header(obj).tid &= ~GCFLAG_VISITED # survives
self.old_rawmalloced_objects.append(obj)
else:
size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -1889,14 +1879,16 @@
self.rawmalloced_total_size -= r_uint(allocsize)
def start_free_rawmalloc_objects(self):
+ ll_assert(not self.raw_malloc_might_sweep.non_empty(),
+ "raw_malloc_might_sweep must be empty")
(self.raw_malloc_might_sweep, self.old_rawmalloced_objects) = (
self.old_rawmalloced_objects, self.raw_malloc_might_sweep)
# Returns true when finished processing objects
def free_unvisited_rawmalloc_objects_step(self, nobjects):
while self.raw_malloc_might_sweep.non_empty() and nobjects > 0:
- self.free_rawmalloced_object_if_unvisited(
- self.raw_malloc_might_sweep.pop())
+ obj = self.raw_malloc_might_sweep.pop()
+ self.free_rawmalloced_object_if_unvisited(obj)
nobjects -= 1
return nobjects
@@ -2191,6 +2183,8 @@
# The code relies on the fact that no weakref can be an old object
# weakly pointing to a young object. Indeed, weakrefs are immutable
# so they cannot point to an object that was created after it.
+ # Thanks to this, during a minor collection, we don't have to fix
+ # or clear the address stored in old weakrefs.
def invalidate_young_weakrefs(self):
"""Called during a nursery collection."""
# walk over the list of objects that contain weakrefs and are in the
More information about the pypy-commit
mailing list