Author: Armin Rigo <[email protected]>
Branch: gc-minimark-pinning
Changeset: r55059:77b5c76b9bdd
Date: 2012-05-12 18:26 +0200
http://bitbucket.org/pypy/pypy/changeset/77b5c76b9bdd/
Log: - Separate the concerns of 'nursery_top' and a new 'nursery_limit'.
Fixes is_in_nursery() for example, which could return False.
- Comments and details.
- Fix test_gc.py.
diff --git a/pypy/rpython/memory/gc/base.py b/pypy/rpython/memory/gc/base.py
--- a/pypy/rpython/memory/gc/base.py
+++ b/pypy/rpython/memory/gc/base.py
@@ -18,7 +18,7 @@
needs_write_barrier = False
malloc_zero_filled = False
prebuilt_gc_objects_are_static_roots = True
- can_always_pin_objects = False
+ can_usually_pin_objects = False
object_minimal_size = 0
gcflag_extra = 0 # or a real GC flag that is always 0 when not collecting
diff --git a/pypy/rpython/memory/gc/minimark.py
b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -131,7 +131,7 @@
needs_write_barrier = True
prebuilt_gc_objects_are_static_roots = False
malloc_zero_filled = True # xxx experiment with False
- can_always_pin_objects = True
+ can_usually_pin_objects = True
gcflag_extra = GCFLAG_FINALIZATION_ORDERING
# All objects start with a HDR, i.e. with a field 'tid' which contains
@@ -248,9 +248,10 @@
# it gives a lower bound on the allowed size of the nursery.
self.nonlarge_max = large_object - 1
#
- self.nursery = NULL
- self.nursery_free = NULL
- self.nursery_top = NULL
+ self.nursery = NULL # start of the nursery
+ self.nursery_free = NULL # first free location, current ptr
+ self.nursery_limit= NULL # current limit up to which allocate
+ self.nursery_top = NULL # end of the nursery
self.debug_tiny_nursery = -1
self.debug_rotating_nurseries = None
#
@@ -311,7 +312,7 @@
# GCFLAG_HAS_SHADOW to their future location at the next
# minor collection.
self.nursery_objects_shadows = self.AddressDict()
- # all pinned objects that were in the nursery *before* last
+ # all surviving pinned objects that were in the nursery *before* last
# minor collect. This is a sorted deque that should be consulted when
# considering next nursery ceiling
self.nursery_barriers = self.AddressDeque()
@@ -404,6 +405,7 @@
self.nursery_free = self.nursery
# the end of the nursery:
self.nursery_top = self.nursery + self.nursery_size
+ self.nursery_limit = self.nursery_top
# initialize the threshold
self.min_heap_size = max(self.min_heap_size, self.nursery_size *
self.major_collection_threshold)
@@ -468,6 +470,7 @@
llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
self.nursery = newnurs
self.nursery_top = self.nursery + self.nursery_size
+ self.nursery_limit = self.nursery_top
debug_print("switching from nursery", oldnurs,
"to nursery", self.nursery,
"size", self.nursery_size)
@@ -509,7 +512,7 @@
# there, do a collect first.
result = self.nursery_free
self.nursery_free = result + totalsize
- if self.nursery_free > self.nursery_top:
+ if self.nursery_free > self.nursery_limit:
result = self.maybe_collect_and_reserve(totalsize)
#
# Build the object.
@@ -568,7 +571,7 @@
# there, do a collect first.
result = self.nursery_free
self.nursery_free = result + totalsize
- if self.nursery_free > self.nursery_top:
+ if self.nursery_free > self.nursery_limit:
result = self.maybe_collect_and_reserve(totalsize)
#
# Build the object.
@@ -588,10 +591,11 @@
self.major_collection()
def maybe_collect_and_reserve(self, totalsize):
- """To call when nursery_free overflows nursery_top.
- Do a minor collection, and possibly also a major collection,
- and finally reserve 'totalsize' bytes at the start of the
- now-empty nursery.
+ """To call when nursery_free overflows nursery_limit.
+ Walks to the next block of contiguous memory between pinned
+ objects. If there isn't any, do a minor collection, and
+ possibly also a major collection. Returns when it succeeded
+ in reserving 'totalsize' bytes in the nursery.
"""
count = 0
#
@@ -601,9 +605,9 @@
# blocks from pinned objects, move to the next one
size_gc_header = self.gcheaderbuilder.size_gc_header
pinned_obj_size = size_gc_header + self.get_size(
- self.nursery_top + size_gc_header)
- self.nursery_free = self.nursery_top + pinned_obj_size
- self.nursery_top = self.nursery_barriers.popleft()
+ self.nursery_limit + size_gc_header)
+ self.nursery_free = self.nursery_limit + pinned_obj_size
+ self.nursery_limit = self.nursery_barriers.popleft()
#
else:
# do a minor collection
@@ -629,7 +633,7 @@
# may fail again, and then we loop; but it's the uncommon case.
result = self.nursery_free
self.nursery_free = result + totalsize
- if self.nursery_free <= self.nursery_top:
+ if self.nursery_free <= self.nursery_limit:
break
#
if self.debug_tiny_nursery >= 0: # for debugging
@@ -789,7 +793,9 @@
if self.next_major_collection_threshold < 0:
# cannot trigger a full collection now, but we can ensure
# that one will occur very soon
- self.nursery_free = self.nursery_top
+ while self.nursery_barriers.non_empty():
+ self.nursery_barriers.popleft()
+ self.nursery_free = self.nursery_limit = self.nursery_top
def can_optimize_clean_setarrayitems(self):
if self.card_page_indices > 0:
@@ -1369,7 +1375,7 @@
self.debug_rotate_nursery()
self.nursery_free = self.nursery
self.nursery_barriers.append(self.nursery + self.nursery_size)
- self.nursery_top = self.nursery_barriers.popleft()
+ self.nursery_limit = self.nursery_barriers.popleft()
#
debug_print("minor collect, total memory used:",
self.get_total_memory_used())
diff --git a/pypy/rpython/memory/support.py b/pypy/rpython/memory/support.py
--- a/pypy/rpython/memory/support.py
+++ b/pypy/rpython/memory/support.py
@@ -196,6 +196,9 @@
got = next
def sort(self):
+ """Sorts the items in the AddressStack. They must not be more
+ than one chunk of them. This results in a **reverse** order,
+ so that the first pop()ped items are the smallest ones."""
ll_assert(self.chunk.next == null_chunk, "too big for sorting")
sort_chunk(self.chunk, self.used_in_last_chunk)
diff --git a/pypy/rpython/memory/test/test_gc.py
b/pypy/rpython/memory/test/test_gc.py
--- a/pypy/rpython/memory/test/test_gc.py
+++ b/pypy/rpython/memory/test/test_gc.py
@@ -722,14 +722,15 @@
s = str(i)
if not rgc.can_move(s):
return 13
- sum = int(rgc.pin(s))
- rgc.unpin(s)
- return sum
+ res = int(rgc.pin(s))
+ if res:
+ rgc.unpin(s)
+ return res
res = self.interpret(f, [10])
if not self.GCClass.moving_gc:
assert res == 13
- elif self.GCClass.can_always_pin_objects:
+ elif self.GCClass.can_usually_pin_objects:
assert res == 1
else:
assert res == 0 or res == 13
@@ -909,7 +910,7 @@
e = lltype.malloc(TP)
e.x = 3
prev = llmemory.cast_ptr_to_adr(e)
- rgc.pin(e)
+ assert rgc.pin(e)
for k in range(i):
lltype.malloc(TP)
res = int(llmemory.cast_ptr_to_adr(e) == prev)
@@ -937,8 +938,8 @@
lltype.malloc(TP)
e2 = lltype.malloc(TP)
e2.x = 5
- rgc.pin(e2)
- rgc.pin(e)
+ assert rgc.pin(e2)
+ assert rgc.pin(e)
prev = llmemory.cast_ptr_to_adr(e)
prev2 = llmemory.cast_ptr_to_adr(e2)
for k in range(i):
@@ -969,7 +970,7 @@
c = lltype.malloc(TP)
c.y = s
c.x = 3
- rgc.pin(c)
+ assert rgc.pin(c)
for k in range(i):
lltype.malloc(TP)
rgc.unpin(c)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit