Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r141:337b49208d45
Date: 2013-06-16 11:15 +0200
http://bitbucket.org/pypy/stmgc/changeset/337b49208d45/

Log:    Fix, going in another direction than cb8059368058: stmgc_duplicate()
        should not cause any minor collection --- the write barrier should
        not.

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -414,7 +414,7 @@
   return P;   /* always returns its arg: the object is converted in-place */
 }
 
-static gcptr LocalizePublic(struct tx_descriptor *d, gcptr R, gcptr L)
+static gcptr LocalizePublic(struct tx_descriptor *d, gcptr R)
 {
   assert(R->h_tid & GCFLAG_PUBLIC);
 
@@ -427,11 +427,13 @@
 
   R->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
 
+  /* note that stmgc_duplicate() usually returns a young object, but may
+     return an old one if the nursery is full at this moment. */
+  gcptr L = stmgc_duplicate(R);
   assert(!(L->h_tid & GCFLAG_BACKUP_COPY));
   assert(!(L->h_tid & GCFLAG_STUB));
   assert(!(L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
-  L->h_tid &= ~(GCFLAG_OLD               |
-                GCFLAG_VISITED           |
+  L->h_tid &= ~(GCFLAG_VISITED           |
                 GCFLAG_PUBLIC            |
                 GCFLAG_PREBUILT_ORIGINAL |
                 GCFLAG_PUBLIC_TO_PRIVATE |
@@ -471,7 +473,7 @@
       return P;
     }
 
-  gcptr R, L, W;
+  gcptr R, W;
   R = stm_read_barrier(P);
 
   if (is_private(R))
@@ -483,13 +485,6 @@
   struct tx_descriptor *d = thread_descriptor;
   assert(d->active >= 1);
 
-  L = NULL;
-  if (R->h_tid & GCFLAG_PUBLIC)
-    {
-    retry:
-      L = stmgc_duplicate(R);
-    }
-
   /* We need the collection_lock for the sequel; this is required notably
      because we're about to edit flags on a protected object.
   */
@@ -499,20 +494,21 @@
 
   if (R->h_tid & GCFLAG_PUBLIC)
     {
-      if (L == NULL)
-        {
-          /* Oups, the flags on R changed while we where waiting for
-             the collection_lock. */
-          spinlock_release(d->public_descriptor->collection_lock);
-          goto retry;
-        }
       /* Make and return a new (young) private copy of the public R.
-         Add R into the list 'public_with_young_copy'.
+         Add R into the list 'public_with_young_copy', unless W is
+         actually an old object, in which case we need to record W.
       */
       assert(R->h_tid & GCFLAG_OLD);
-      gcptrlist_insert(&d->public_with_young_copy, R);
-      W = LocalizePublic(d, R, L);
+      W = LocalizePublic(d, R);
       assert(is_private(W));
+
+      if (W->h_tid & GCFLAG_OLD)
+        {
+          W->h_tid |= GCFLAG_WRITE_BARRIER;
+          record_write_barrier(W);
+        }
+      else
+        gcptrlist_insert(&d->public_with_young_copy, R);
     }
   else
     {
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -31,14 +31,20 @@
 
 static char *collect_and_allocate_size(size_t size);  /* forward */
 
-inline static char *allocate_nursery(size_t size)
+inline static char *allocate_nursery(size_t size, int can_collect)
 {
     struct tx_descriptor *d = thread_descriptor;
     char *cur = d->nursery_current;
     char *end = cur + size;
     d->nursery_current = end;
     if (end > d->nursery_end) {
-        cur = collect_and_allocate_size(size);
+        if (can_collect) {
+            cur = collect_and_allocate_size(size);
+        }
+        else {
+            d->nursery_current = cur;
+            cur = NULL;
+        }
     }
     return cur;
 }
@@ -46,7 +52,7 @@
 gcptr stm_allocate(size_t size, unsigned long tid)
 {
     /* XXX inline the fast path */
-    gcptr P = (gcptr)allocate_nursery(size);
+    gcptr P = (gcptr)allocate_nursery(size, 1);
     assert(tid == (tid & STM_USER_TID_MASK));
     P->h_tid = tid;
     P->h_revision = stm_private_rev_num;
@@ -56,7 +62,10 @@
 gcptr stmgc_duplicate(gcptr P)
 {
     size_t size = stmcb_size(P);
-    gcptr L = (gcptr)allocate_nursery(size);
+    gcptr L = (gcptr)allocate_nursery(size, 0);
+    if (L == NULL)
+        return stmgc_duplicate_old(P);
+
     memcpy(L, P, size);
     L->h_tid &= ~GCFLAG_OLD;
     return L;
@@ -290,7 +299,14 @@
     teardown_minor_collect(d);
 
     /* clear the nursery */
+#if defined(_GC_DEBUG) && _GC_DEBUG >= 2
+    stm_free(d->nursery_base, GC_NURSERY);
+    d->nursery_base = stm_malloc(GC_NURSERY);
     memset(d->nursery_base, 0, GC_NURSERY);
+    d->nursery_end = d->nursery_base + GC_NURSERY;
+#else
+    memset(d->nursery_base, 0, GC_NURSERY);
+#endif
     d->nursery_current = d->nursery_base;
 
     assert(!stmgc_minor_collect_anything_to_do(d));
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -464,7 +464,8 @@
     assert 42 < (p.h_tid & 0xFFFF) < 521
 
 def check_nursery_free(p):
-    assert p.h_tid == p.h_revision == 0
+    #assert p.h_tid == p.h_revision == 0
+    assert not lib._stm_can_access_memory(p)
 
 def check_inaccessible(p):
     assert not lib._stm_can_access_memory(p)
diff --git a/c4/test/test_nursery.py b/c4/test/test_nursery.py
--- a/c4/test/test_nursery.py
+++ b/c4/test/test_nursery.py
@@ -2,6 +2,9 @@
 from support import *
 
 
+COLLECT_MOVES_NURSERY = True
+
+
 def setup_function(f):
     lib.stm_clear_between_tests()
     lib.stm_initialize_tests(getattr(f, 'max_aborts', 0))
@@ -30,7 +33,8 @@
         p1 = lib.stm_pop_root()
         check_not_free(p1)
         check_not_free(p3)
-    assert p2 in seen    # the pointer location was reused
+    if not COLLECT_MOVES_NURSERY:
+        assert p2 in seen    # the pointer location was reused
 
 def test_nursery_follows():
     p1 = nalloc_refs(1)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to