Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r472:b7b44751111b
Date: 2013-08-03 14:11 +0200
http://bitbucket.org/pypy/stmgc/changeset/b7b44751111b/

Log:    stm_immut_read_barrier()

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -318,6 +318,41 @@
   return P;
 }
 
+gcptr stm_ImmutReadBarrier(gcptr P)
+{
+  assert(P->h_tid & GCFLAG_STUB);
+  assert(P->h_tid & GCFLAG_PUBLIC);
+
+  revision_t v = ACCESS_ONCE(P->h_revision);
+  assert(IS_POINTER(v));  /* "is a pointer", "has a more recent revision" */
+
+  if (!(v & 2))
+    {
+      P = (gcptr)v;
+    }
+  else
+    {
+      /* follow a stub reference */
+      struct tx_descriptor *d = thread_descriptor;
+      struct tx_public_descriptor *foreign_pd = STUB_THREAD(P);
+      if (foreign_pd == d->public_descriptor)
+        {
+          /* Same thread: dereference the pointer directly. */
+          dprintf(("immut_read_barrier: %p -> %p via stub\n  ", P,
+                   (gcptr)(v - 2)));
+          P = (gcptr)(v - 2);
+        }
+      else
+        {
+          /* stealing: needed because accessing v - 2 from this thread
+             is forbidden (the target might disappear under our feet) */
+          dprintf(("immut_read_barrier: %p -> stealing...\n  ", P));
+          stm_steal_stub(P);
+        }
+    }
+  return stm_immut_read_barrier(P);   /* retry */
+}
+
 static gcptr _match_public_to_private(gcptr P, gcptr pubobj, gcptr privobj,
                                       int from_stolen)
 {
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -73,7 +73,7 @@
 // in stmgc.h:          GCFLAG_WRITE_BARRIER          = STM_FIRST_GCFLAG << 5;
 // in stmgc.h:          GCFLAG_MOVED                  = STM_FIRST_GCFLAG << 6;
 static const revision_t GCFLAG_BACKUP_COPY  /*debug*/ = STM_FIRST_GCFLAG << 7;
-static const revision_t GCFLAG_STUB         /*debug*/ = STM_FIRST_GCFLAG << 8;
+// in stmgc.h:          GCFLAG_STUB                   = STM_FIRST_GCFLAG << 8;
 static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG << 9;
 static const revision_t GCFLAG_HAS_ID                 = STM_FIRST_GCFLAG << 10;
 static const revision_t GCFLAG_IMMUTABLE              = STM_FIRST_GCFLAG << 11;
@@ -195,8 +195,9 @@
 void SpinLoop(int);
 
 gcptr stm_DirectReadBarrier(gcptr);
+gcptr stm_WriteBarrier(gcptr);
 gcptr stm_RepeatReadBarrier(gcptr);
-gcptr stm_WriteBarrier(gcptr);
+gcptr stm_ImmutReadBarrier(gcptr);
 gcptr _stm_nonrecord_barrier(gcptr);  /* debugging: read barrier, but
                                          not recording anything */
 int _stm_is_private(gcptr);  /* debugging */
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -75,11 +75,16 @@
      The only thing that may have occurred is that a
      stm_write_barrier() on the same object could have made it
      invalid.
+
+   - a different optimization is to read immutable fields: in order
+     to do that, use stm_immut_read_barrier(), which only activates
+     on stubs.
 */
 #if 0     // (optimized version below)
 gcptr stm_read_barrier(gcptr);
 gcptr stm_write_barrier(gcptr);
 gcptr stm_repeat_read_barrier(gcptr);
+gcptr stm_immut_read_barrier(gcptr);
 #endif
 
 /* start a new transaction, calls callback(), and when it returns
@@ -169,6 +174,7 @@
 static const revision_t GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
 static const revision_t GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG << 5;
 static const revision_t GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
+static const revision_t GCFLAG_STUB = STM_FIRST_GCFLAG << 8;
 extern __thread char *stm_read_barrier_cache;
 #define FX_MASK 65535
 #define FXCACHE_AT(obj)  \
@@ -193,5 +199,10 @@
         stm_RepeatReadBarrier(obj)                              \
      :  (obj))
 
+#define stm_immut_read_barrier(obj)                             \
+    (UNLIKELY((obj)->h_tid & GCFLAG_STUB) ?                     \
+        stm_ImmutReadBarrier(obj)                               \
+     :  (obj))
+
 
 #endif
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -58,6 +58,7 @@
     gcptr stm_read_barrier(gcptr);
     gcptr stm_write_barrier(gcptr);
     gcptr stm_repeat_read_barrier(gcptr);
+    gcptr stm_immut_read_barrier(gcptr);
     void stm_perform_transaction(gcptr arg, int (*callback)(gcptr, int));
     void stm_commit_transaction(void);
     void stm_begin_inevitable_transaction(void);
diff --git a/c4/test/test_et.py b/c4/test/test_et.py
--- a/c4/test/test_et.py
+++ b/c4/test/test_et.py
@@ -729,3 +729,19 @@
     assert q != p
     assert lib.stm_repeat_read_barrier(q) == q
     assert lib.stm_repeat_read_barrier(p) == q
+
+def test_immut_read_barrier():
+    p = palloc(HDR + WORD)
+    p2 = lib.stm_write_barrier(p)
+    lib.stm_commit_transaction()
+    lib.stm_begin_inevitable_transaction()
+    assert classify(p) == "public"
+    assert classify(p2) == "protected"
+    pstub = ffi.cast("gcptr", p.h_revision)
+    assert classify(pstub) == "stub"
+    assert lib.stm_immut_read_barrier(p) == p
+    assert lib.stm_immut_read_barrier(pstub) == p2
+    assert lib.stm_immut_read_barrier(p2) == p2
+    assert lib.stm_read_barrier(p2) == p2
+    assert lib.stm_read_barrier(pstub) == p2
+    assert lib.stm_read_barrier(p) == p2
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to