[pypy-commit] stmgc c7-refactor: Actually implement surviving young_outside_nursery

arigo noreply at buildbot.pypy.org
Tue Feb 25 09:50:25 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r854:4302246a0ad0
Date: 2014-02-25 09:50 +0100
http://bitbucket.org/pypy/stmgc/changeset/4302246a0ad0/

Log:	Actually implement surviving young_outside_nursery

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -12,7 +12,7 @@
 void _stm_write_slowpath(object_t *obj)
 {
     assert(_running_transaction());
-    assert(!_is_in_nursery(obj));
+    assert(!_is_young(obj));
 
     /* is this an object from the same transaction, outside the nursery? */
     if ((obj->stm_flags & -GCFLAG_OVERFLOW_NUMBER_bit0) ==
@@ -225,7 +225,7 @@
 
 static void synchronize_overflow_object_now(object_t *obj)
 {
-    assert(!_is_in_nursery(obj));
+    assert(!_is_young(obj));
     assert((obj->stm_flags & GCFLAG_SMALL_UNIFORM) == 0);
 
     char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -42,6 +42,12 @@
     return (uintptr_t)obj < NURSERY_END;
 }
 
+static inline bool _is_young(object_t *obj)
+{
+    return (_is_in_nursery(obj) ||
+        tree_contains(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj));
+}
+
 bool _stm_in_nursery(object_t *obj)
 {
     return _is_in_nursery(obj);
@@ -54,6 +60,19 @@
 #define FLAG_SYNC_LARGE_NOW   0x01
 
 
+static void minor_young_outside_nursery(object_t *obj)
+{
+    tree_delete_item(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj);
+
+    uintptr_t nobj_sync_now = (uintptr_t)obj;
+    if (STM_PSEGMENT->minor_collect_will_commit_now)
+        nobj_sync_now |= FLAG_SYNC_LARGE_NOW;
+    else
+        LIST_APPEND(STM_PSEGMENT->large_overflow_objects, obj);
+
+    LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now);
+}
+
 static void minor_trace_if_young(object_t **pobj)
 {
     /* takes a normal pointer to a thread-local pointer to an object */
@@ -61,8 +80,13 @@
     if (obj == NULL)
         return;
     assert((uintptr_t)obj < NB_PAGES * 4096UL);
-    if (!_is_in_nursery(obj))
-        return;
+    if (!_is_in_nursery(obj)) {
+        if (UNLIKELY(tree_contains(STM_PSEGMENT->young_outside_nursery,
+                                   (uintptr_t)obj))) {
+            minor_young_outside_nursery(obj);
+        }
+        return;   /* else old object, nothing to do */
+    }
 
     /* If the object was already seen here, its first word was set
        to GCWORD_MOVED.  In that case, the forwarding location, i.e.
@@ -133,7 +157,7 @@
 
 static inline void _collect_now(object_t *obj)
 {
-    assert(!_is_in_nursery(obj));
+    assert(!_is_young(obj));
 
     /* We must not have GCFLAG_WRITE_BARRIER so far.  Add it now. */
     assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER));
diff --git a/c7/test/test_nursery.py b/c7/test/test_nursery.py
--- a/c7/test/test_nursery.py
+++ b/c7/test/test_nursery.py
@@ -81,7 +81,7 @@
         assert old
         assert young
 
-    def test_larger_than_limit_for_nursery(self):
+    def test_larger_than_limit_for_nursery_die(self):
         obj_size = lib._STM_FAST_ALLOC + 16
 
         self.start_transaction()
@@ -93,6 +93,28 @@
             seen.add(new)
         assert len(seen) < 5     # addresses are reused
 
+    def test_larger_than_limit_for_nursery_dont_die(self):
+        obj_nrefs = (lib._STM_FAST_ALLOC + 16) // 8
+
+        self.start_transaction()
+        lp1 = ffi.cast("object_t *", 0)
+        seen = set()
+        for i in range(100):
+            self.push_root(lp1)
+            stm_minor_collect()
+            lp1 = self.pop_root()
+            new = stm_allocate_refs(obj_nrefs)
+            assert not is_in_nursery(new)
+            seen.add(new)
+            stm_set_ref(new, i, lp1)
+            lp1 = new
+        assert len(seen) == 100     # addresses are not reused
+
+        for i in reversed(range(100)):
+            assert lp1
+            lp1 = stm_get_ref(lp1, i)
+        assert not lp1
+
     def test_reset_partial_alloc_pages(self):
         py.test.skip("a would-be-nice feature, but not actually needed: "
                      "the next major GC will take care of it")


More information about the pypy-commit mailing list