Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r471:b57de4359eea
Date: 2013-08-03 10:02 +0200
http://bitbucket.org/pypy/stmgc/changeset/b57de4359eea/

Log:    Implement the repeat read barrier (actually mostly just expose it to
        the user, with a fast-path logic).

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -276,28 +276,45 @@
   /* Version of stm_DirectReadBarrier() that doesn't abort and assumes
    * that 'P' was already an up-to-date result of a previous
    * stm_DirectReadBarrier().  We only have to check if we did in the
-   * meantime a stm_write_barrier().
+   * meantime a stm_write_barrier().  Should only be called if we
+   * have the flag PUBLIC_TO_PRIVATE or on MOVED objects.  This version
+   * should never abort (it is used in stm_decode_abort_info()).
    */
-  if (P->h_tid & GCFLAG_PUBLIC)
+  assert(P->h_tid & GCFLAG_PUBLIC);
+  assert(!(P->h_tid & GCFLAG_STUB));
+
+  if (P->h_tid & GCFLAG_MOVED)
     {
-      if (P->h_tid & GCFLAG_MOVED)
-        {
-          P = (gcptr)P->h_revision;
-          assert(P->h_tid & GCFLAG_PUBLIC);
-        }
-      if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
-        {
-          struct tx_descriptor *d = thread_descriptor;
-          wlog_t *item;
-          G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
+      dprintf(("repeat_read_barrier: %p -> %p moved\n", P,
+               (gcptr)P->h_revision));
+      P = (gcptr)P->h_revision;
+      assert(P->h_tid & GCFLAG_PUBLIC);
+      assert(!(P->h_tid & GCFLAG_STUB));
+      assert(!(P->h_tid & GCFLAG_MOVED));
+      if (!(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE))
+        return P;
+    }
+  assert(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE);
 
-          P = item->val;
-          assert(!(P->h_tid & GCFLAG_PUBLIC));
-        no_private_obj:
-          ;
-        }
-    }
+  struct tx_descriptor *d = thread_descriptor;
+  wlog_t *item;
+  G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
+
+  /* We have a key in 'public_to_private'.  The value is the
+     corresponding private object. */
+  dprintf(("repeat_read_barrier: %p -> %p public_to_private\n", P, item->val));
+  P = item->val;
+  assert(!(P->h_tid & GCFLAG_PUBLIC));
   assert(!(P->h_tid & GCFLAG_STUB));
+  assert(is_private(P));
+  return P;
+
+ no_private_obj:
+  /* Key not found.  It should not be waiting in 'stolen_objects',
+     because this case from steal.c applies to objects to were originally
+     backup objects.  'P' cannot be a backup object if it was obtained
+     earlier as a result of stm_read_barrier().
+  */
   return P;
 }
 
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -69,9 +69,9 @@
 static const revision_t GCFLAG_VISITED                = STM_FIRST_GCFLAG << 1;
 static const revision_t GCFLAG_PUBLIC                 = STM_FIRST_GCFLAG << 2;
 static const revision_t GCFLAG_PREBUILT_ORIGINAL      = STM_FIRST_GCFLAG << 3;
-static const revision_t GCFLAG_PUBLIC_TO_PRIVATE      = STM_FIRST_GCFLAG << 4;
+// in stmgc.h:          GCFLAG_PUBLIC_TO_PRIVATE      = STM_FIRST_GCFLAG << 4;
 // in stmgc.h:          GCFLAG_WRITE_BARRIER          = STM_FIRST_GCFLAG << 5;
-static const revision_t GCFLAG_MOVED                  = STM_FIRST_GCFLAG << 6;
+// 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;
 static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG << 9;
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -204,7 +204,7 @@
     WRITE_BUF(buffer, res_size);
     WRITE('e');
     for (i=0; i<d->abortinfo.size; i+=2) {
-        char *object = (char *)stm_RepeatReadBarrier(d->abortinfo.items[i+0]);
+        char *object = (char*)stm_repeat_read_barrier(d->abortinfo.items[i+0]);
         long *fieldoffsets = (long*)d->abortinfo.items[i+1];
         long kind, offset;
         size_t rps_size;
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -58,7 +58,7 @@
 int stm_enter_callback_call(void);
 void stm_leave_callback_call(int);
 
-/* read/write barriers (the most general versions only for now).
+/* read/write barriers.
 
    - the read barrier must be applied before reading from an object.
      the result is valid as long as we're in the same transaction,
@@ -68,10 +68,18 @@
      the result is valid for a shorter period of time: we have to
      do stm_write_barrier() again if we ended the transaction, or
      if we did a potential collection (e.g. stm_allocate()).
+
+   - as an optimization, stm_repeat_read_barrier() can be used
+     instead of stm_read_barrier() if the object was already
+     obtained by a stm_read_barrier() in the same transaction.
+     The only thing that may have occurred is that a
+     stm_write_barrier() on the same object could have made it
+     invalid.
 */
 #if 0     // (optimized version below)
 gcptr stm_read_barrier(gcptr);
 gcptr stm_write_barrier(gcptr);
+gcptr stm_repeat_read_barrier(gcptr);
 #endif
 
 /* start a new transaction, calls callback(), and when it returns
@@ -158,7 +166,9 @@
 extern __thread revision_t stm_private_rev_num;
 gcptr stm_DirectReadBarrier(gcptr);
 gcptr stm_WriteBarrier(gcptr);
+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;
 extern __thread char *stm_read_barrier_cache;
 #define FX_MASK 65535
 #define FXCACHE_AT(obj)  \
@@ -178,5 +188,10 @@
         stm_WriteBarrier(obj)                                   \
      :  (obj))
 
+#define stm_repeat_read_barrier(obj)                            \
+    (UNLIKELY((obj)->h_tid & (GCFLAG_PUBLIC_TO_PRIVATE | GCFLAG_MOVED)) ? \
+        stm_RepeatReadBarrier(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
@@ -57,6 +57,7 @@
     int stm_in_transaction(void);
     gcptr stm_read_barrier(gcptr);
     gcptr stm_write_barrier(gcptr);
+    gcptr stm_repeat_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
@@ -713,3 +713,19 @@
     assert x == 1
     lib.stm_leave_callback_call(x)
     lib.stm_initialize_tests(0)
+
+def test_repeat_read_barrier():
+    p = nalloc(HDR + WORD)
+    assert lib.stm_repeat_read_barrier(p) == p
+    lib.stm_commit_transaction()
+    lib.stm_begin_inevitable_transaction()
+    assert lib.stm_repeat_read_barrier(p) == p
+    #
+    p = palloc(HDR + WORD)
+    assert classify(p) == "public"
+    assert lib.stm_read_barrier(p) == p
+    q = lib.stm_write_barrier(p)
+    assert classify(q) == "private"
+    assert q != p
+    assert lib.stm_repeat_read_barrier(q) == q
+    assert lib.stm_repeat_read_barrier(p) == q
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to