Author: Gregor Wegberg <[email protected]>
Branch: gc-incminimark-pinning
Changeset: r71813:f5617eea321d
Date: 2014-05-12 12:12 +0200
http://bitbucket.org/pypy/pypy/changeset/f5617eea321d/
Log: started with object pinning implementation inside incminimark.
Implemented the pin()/unpin() methods. This work is based on the
`gc-minimark-pinning` branch.
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
@@ -83,6 +83,7 @@
# minimarkpage.py (if they are small), or raw-malloced (if they are not
# small). Collected by regular mark-n-sweep during major collections.
#
+# XXX update doc string to contain object pinning (groggi)
WORD = LONG_BIT // 8
NULL = llmemory.NULL
@@ -136,7 +137,13 @@
# a minor collection.
GCFLAG_VISITED_RMY = first_gcflag << 8
-_GCFLAG_FIRST_UNUSED = first_gcflag << 9 # the first unused bit
+# The following flag is set on nursery objects of which we expect not to
+# move. This means that a young object with this flag is not moved out
+# of the nursery during a minor collection. See pin()/unpin() for further
+# details.
+GCFLAG_PINNED = first_gcflag << 9
+
+_GCFLAG_FIRST_UNUSED = first_gcflag << 10 # the first unused bit
# States for the incremental GC
@@ -361,6 +368,15 @@
# minor collection.
self.nursery_objects_shadows = self.AddressDict()
#
+ # A sorted deque containing all pinned objects *before* the last
+ # minor collection. This deque must be consulted when considering
+ # next nursery ceiling.
+ self.nursery_barriers = self.AddressDeque()
+ #
+ # Counter tracking how many pinned objects currently reside inside
+ # the nursery.
+ self.pinned_objects_in_nursery = 0
+ #
# Allocate a nursery. In case of auto_nursery_size, start by
# allocating a very small nursery, enough to do things like look
# up the env var, which requires the GC; and then really
@@ -896,12 +912,42 @@
def pin(self, obj):
debug_start("groggi-incminimark-pin")
+ # Tries to pin the given 'obj'. On success this method returns True,
+ # otherwise False. There are multiple reasons why a call returns False
+ # and it should be always expected that pinning is likely to fail
+ # (return False).
+
+ # XXX what happens if nursery is full of pinned objects? (groggi)
+ # XXX what happens if pinned object references movable data? (groggi)
+
+ if not self.is_in_nursery(obj):
+ # Old objects are already non-moving, therefore pinning
+ # makes no sense. If you run into this case, you may forgot
+ # to check if can_move(obj) already returns True in which
+ # case a call to pin() is unnecessary.
+ return False
+ if self.header(obj).tid & GCFLAG_PINNED:
+ # Already pinned, we do not allow to pin it again.
+ # Reason: It would be possible that the first caller unpins
+ # while the second caller thinks it's still pinned.
+ return False
+
+ self.header(obj).tid |= GCFLAG_PINNED
+ self.pinned_objects_in_nursery += 1
+ debug_print("pinned_objects_in_nursery: ",
self.pinned_objects_in_nursery)
debug_stop("groggi-incminimark-pin")
- return False
+ return True
def unpin(self, obj):
+ # Unpins a previously pinned 'obj'. This should only be called
+ # after a pin(obj).
debug_start("groggi-incminimark-unpin")
+ ll_assert(self.header(obj) & GCFLAG_PINNED != 0,
+ "unpin: object is already not pinned")
+ self.header(obj).tid &= ~GCFLAG_PINNED
+ self.pinned_objects_in_nursery -= 1
+ debug_print("pinned_objects_in_nursery: ",
self.pinned_objects_in_nursery)
debug_stop("groggi-incminimark-unpin")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit