[pypy-commit] pypy stmgc-static-barrier: import stmgc/9dc18268f0da

arigo noreply at buildbot.pypy.org
Tue Aug 13 18:04:57 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-static-barrier
Changeset: r66122:82d9f20cc182
Date: 2013-08-13 16:29 +0200
http://bitbucket.org/pypy/pypy/changeset/82d9f20cc182/

Log:	import stmgc/9dc18268f0da

diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c
--- a/rpython/translator/stm/src_stm/et.c
+++ b/rpython/translator/stm/src_stm/et.c
@@ -7,6 +7,7 @@
  */
 #include "stmimpl.h"
 
+#ifdef _GC_DEBUG
 char tmp_buf[128];
 char* stm_dbg_get_hdr_str(gcptr obj)
 {
@@ -26,6 +27,7 @@
     cur += sprintf(cur, "tid=%ld", stm_get_tid(obj));
     return tmp_buf;
 }
+#endif
 
 
 
@@ -275,29 +277,81 @@
   /* 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)
+      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);
+
+  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;
+}
+
+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)
         {
-          P = (gcptr)P->h_revision;
-          assert(P->h_tid & GCFLAG_PUBLIC);
+          /* Same thread: dereference the pointer directly. */
+          dprintf(("immut_read_barrier: %p -> %p via stub\n  ", P,
+                   (gcptr)(v - 2)));
+          P = (gcptr)(v - 2);
         }
-      if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
+      else
         {
-          struct tx_descriptor *d = thread_descriptor;
-          wlog_t *item;
-          G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
-
-          P = item->val;
-          assert(!(P->h_tid & GCFLAG_PUBLIC));
-        no_private_obj:
-          ;
+          /* 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);
         }
     }
-  assert(!(P->h_tid & GCFLAG_STUB));
-  return P;
+  return stm_immut_read_barrier(P);   /* retry */
 }
 
 static gcptr _match_public_to_private(gcptr P, gcptr pubobj, gcptr privobj,
@@ -565,6 +619,16 @@
     }
 }
 
+gcptr stm_RepeatWriteBarrier(gcptr P)
+{
+  assert(!(P->h_tid & GCFLAG_IMMUTABLE));
+  assert(is_private(P));
+  assert(P->h_tid & GCFLAG_WRITE_BARRIER);
+  P->h_tid &= ~GCFLAG_WRITE_BARRIER;
+  gcptrlist_insert(&thread_descriptor->old_objects_to_trace, P);
+  return P;
+}
+
 gcptr stm_WriteBarrier(gcptr P)
 {
   assert(!(P->h_tid & GCFLAG_IMMUTABLE));
diff --git a/rpython/translator/stm/src_stm/et.h b/rpython/translator/stm/src_stm/et.h
--- a/rpython/translator/stm/src_stm/et.h
+++ b/rpython/translator/stm/src_stm/et.h
@@ -70,11 +70,11 @@
 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;
+// 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;
@@ -196,8 +196,10 @@
 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_RepeatWriteBarrier(gcptr);
 gcptr _stm_nonrecord_barrier(gcptr);  /* debugging: read barrier, but
                                          not recording anything */
 int _stm_is_private(gcptr);  /* debugging */
diff --git a/rpython/translator/stm/src_stm/extra.c b/rpython/translator/stm/src_stm/extra.c
--- a/rpython/translator/stm/src_stm/extra.c
+++ b/rpython/translator/stm/src_stm/extra.c
@@ -154,6 +154,19 @@
     return (p1 == p2);
 }
 
+_Bool stm_pointer_equal_prebuilt(gcptr p1, gcptr p2)
+{
+    assert(p2 != NULL);
+    assert(p2->h_tid & GCFLAG_PREBUILT_ORIGINAL);
+
+    if (p1 == p2)
+        return 1;
+
+    /* the only possible case to still get True is if p2 == p1->h_original */
+    return (p1 != NULL) && (p1->h_original == p2) &&
+        !(p1->h_tid & GCFLAG_PREBUILT_ORIGINAL);
+}
+
 /************************************************************/
 
 void stm_abort_info_push(gcptr obj, long fieldoffsets[])
@@ -205,7 +218,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/rpython/translator/stm/src_stm/revision b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-12cf412eb2d7+
+9dc18268f0da
diff --git a/rpython/translator/stm/src_stm/stmgc.h b/rpython/translator/stm/src_stm/stmgc.h
--- a/rpython/translator/stm/src_stm/stmgc.h
+++ b/rpython/translator/stm/src_stm/stmgc.h
@@ -42,6 +42,7 @@
 /* returns nonzero if the two object-copy pointers belong to the
 same original object */
 _Bool stm_pointer_equal(gcptr, gcptr);
+_Bool stm_pointer_equal_prebuilt(gcptr, gcptr); /* 2nd arg is known prebuilt */
 
 /* to push/pop objects into the local shadowstack */
 #if 0     // (optimized version below)
@@ -59,7 +60,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,
@@ -69,10 +70,28 @@
      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.
+
+   - a different optimization is to read immutable fields: in order
+     to do that, use stm_immut_read_barrier(), which only activates
+     on stubs.
+
+   - stm_repeat_write_barrier() can be used on an object on which
+     we already did stm_write_barrier(), but a potential collection
+     can have occurred.
 */
 #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);
+gcptr stm_repeat_write_barrier(gcptr);   /* <= always returns its argument */
 #endif
 
 /* start a new transaction, calls callback(), and when it returns
@@ -159,7 +178,10 @@
 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;
+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)  \
@@ -167,23 +189,6 @@
 
 #define UNLIKELY(test)  __builtin_expect(test, 0)
 
-
-static inline gcptr stm_read_barrier(gcptr obj) {
-    /* XXX optimize to get the smallest code */
-    if (UNLIKELY((obj->h_revision != stm_private_rev_num) &&
-                 (FXCACHE_AT(obj) != obj)))
-        obj = stm_DirectReadBarrier(obj);
-    return obj;
-}
- 
-static inline gcptr stm_write_barrier(gcptr obj) {
-    if (UNLIKELY((obj->h_revision != stm_private_rev_num) |
-                 ((obj->h_tid & GCFLAG_WRITE_BARRIER) != 0)))
-        obj = stm_WriteBarrier(obj);
-    return obj;
-}
-
-#if 0
 #define stm_read_barrier(obj)                                   \
     (UNLIKELY(((obj)->h_revision != stm_private_rev_num) &&     \
               (FXCACHE_AT(obj) != (obj))) ?                     \
@@ -195,6 +200,21 @@
               (((obj)->h_tid & GCFLAG_WRITE_BARRIER) != 0)) ?   \
         stm_WriteBarrier(obj)                                   \
      :  (obj))
-#endif
+
+#define stm_repeat_read_barrier(obj)                            \
+    (UNLIKELY((obj)->h_tid & (GCFLAG_PUBLIC_TO_PRIVATE | GCFLAG_MOVED)) ? \
+        stm_RepeatReadBarrier(obj)                              \
+     :  (obj))
+
+#define stm_immut_read_barrier(obj)                             \
+    (UNLIKELY((obj)->h_tid & GCFLAG_STUB) ?                     \
+        stm_ImmutReadBarrier(obj)                               \
+     :  (obj))
+
+#define stm_repeat_write_barrier(obj)                           \
+    (UNLIKELY((obj)->h_tid & GCFLAG_WRITE_BARRIER) ?            \
+        stm_RepeatWriteBarrier(obj)                             \
+     :  (obj))
+
 
 #endif


More information about the pypy-commit mailing list