[pypy-commit] stmgc default: Read barrier on public objects

arigo noreply at buildbot.pypy.org
Wed Jun 5 18:23:08 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r72:b9dfe1e2b66e
Date: 2013-06-05 18:22 +0200
http://bitbucket.org/pypy/stmgc/changeset/b9dfe1e2b66e/

Log:	Read barrier on public objects

diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -65,78 +65,6 @@
 
 /************************************************************/
 
-static gcptr HeadOfRevisionChainList(struct tx_descriptor *d, gcptr G)
-{
-  abort();
-#if 0
-  gcptr R = G;
-  revision_t v;
-
- retry:
-  v = ACCESS_ONCE(R->h_revision);
-  if (!(v & 1))  // "is a pointer", i.e.
-    {            //      "has a more recent revision"
-      if (v & 2)
-        {
-        old_to_young:
-          v &= ~2;
-          if (UNLIKELY(!stmgc_is_young_in(d, (gcptr)v)))
-            {
-              stmgc_public_to_foreign_protected(R);
-              goto retry;
-            }
-          R = (gcptr)v;
-          goto retry;
-        }
-
-      gcptr R_prev = R;
-      R = (gcptr)v;
-
-    retry_threelevels:
-      v = ACCESS_ONCE(R->h_revision);
-      if (!(v & 1))  // "is a pointer", i.e.
-        {            //      "has a more recent revision"
-          if (v & 2)
-            goto old_to_young;
-
-          /* we update R_prev->h_revision as a shortcut */
-          /* XXX check if this really gives a worse performance than only
-             doing this write occasionally based on a counter in d */
-          gcptr R_next = (gcptr)v;
-          if (R_next->h_revision == stm_local_revision)
-            {
-              /* must not update an older h_revision to go directly to
-                 the private copy at the end of a chain of protected
-                 objects! */
-              return R_next;
-            }
-          if (R_prev->h_tid & GCFLAG_STOLEN)
-            {
-              /* must not update the h_revision of a stolen object! */
-              R_prev = R;
-              R = R_next;
-              goto retry_threelevels;
-            }
-          R_prev->h_revision = v;
-          R = R_next;
-          goto retry;
-        }
-    }
-
-  if (UNLIKELY(v > d->start_time))   // object too recent?
-    {
-      if (v >= LOCKED)
-        {
-          SpinLoop(SPLP_LOCKED_INFLIGHT);
-          goto retry;                // spinloop until it is no longer LOCKED
-        }
-      ValidateNow(d);                  // try to move start_time forward
-      goto retry;                      // restart searching from R
-    }
-  return R;
-#endif
-}
-
 #if 0
 static inline gcptr AddInReadSet(struct tx_descriptor *d, gcptr R)
 {
@@ -163,12 +91,57 @@
 
   if (P->h_tid & GCFLAG_PUBLIC)
     {
-      abort();
-      /*...*/
+      /* follow the chained list of h_revision's as long as they are
+         regular pointers */
+      revision_t v;
+
+    retry:
+      v = ACCESS_ONCE(P->h_revision);
+      if (!(v & 1))  // "is a pointer", i.e.
+        {            //      "has a more recent revision"
+          if (v & 2)
+            {
+            old_to_young:
+              abort();
+            }
+          assert(P->h_tid & GCFLAG_PUBLIC);
+
+          gcptr P_prev = P;
+          P = (gcptr)v;
+
+          /* if we land on a P in read_barrier_cache: just return it */
+          if (FXCACHE_AT(P) == P)
+            return P;
+
+          v = ACCESS_ONCE(P->h_revision);
+          if (!(v & 1))  // "is a pointer", i.e.
+            {            //      "has a more recent revision"
+              if (v & 2)
+                goto old_to_young;
+              assert(P->h_tid & GCFLAG_PUBLIC);
+
+              /* we update P_prev->h_revision as a shortcut */
+              /* XXX check if this really gives a worse performance than only
+                 doing this write occasionally based on a counter in d */
+              P_prev->h_revision = v;
+              P = (gcptr)v;
+              goto retry;
+            }
+        }
+
+      if (UNLIKELY(v > d->start_time))   // object too recent?
+        {
+          if (v >= LOCKED)
+            {
+              SpinLoop(SPLP_LOCKED_INFLIGHT);
+              goto retry;           // spinloop until it is no longer LOCKED
+            }
+          ValidateNow(d);                  // try to move start_time forward
+          goto retry;                      // restart searching from P
+        }
     }
-
+  fxcache_add(&d->recent_reads_cache, P);
   gcptrlist_insert(&d->list_of_read_objects, P);
-  fxcache_add(&d->recent_reads_cache, P);
   return P;
 }
 
diff --git a/c3/test/test_et.py b/c3/test/test_et.py
--- a/c3/test/test_et.py
+++ b/c3/test/test_et.py
@@ -156,3 +156,25 @@
     assert list_of_read_objects() == []
     assert lib.stm_read_barrier(p) == p     # record as a read object
     assert list_of_read_objects() == [p]
+
+def test_read_barrier_public():
+    p = palloc(HDR)
+    assert lib.stm_read_barrier(p) == p
+    assert list_of_read_objects() == [p]
+
+def test_read_barrier_public_outdated():
+    p1 = palloc(HDR)
+    p2 = palloc(HDR)
+    p1.h_revision = ffi.cast("revision_t", p2)
+    assert lib.stm_read_barrier(p1) == p2
+    assert list_of_read_objects() == [p2]
+
+def test_read_barrier_public_shortcut():
+    p1 = palloc(HDR)
+    p2 = palloc(HDR)
+    p3 = palloc(HDR)
+    p1.h_revision = ffi.cast("revision_t", p2)
+    p2.h_revision = ffi.cast("revision_t", p3)
+    assert lib.stm_read_barrier(p1) == p3
+    assert list_of_read_objects() == [p3]
+    assert p1.h_revision == int(ffi.cast("revision_t", p3))   # shortcutted


More information about the pypy-commit mailing list