1. pypyja
  2. pypy

Commits

Armin Rigo  committed 611a5fd

fixfixfix

  • Participants
  • Parent commits 7020fb4
  • Branches stm-thread-2

Comments (0)

Files changed (7)

File pypy/rpython/memory/gc/stmgc.py

View file
  • Ignore whitespace
 #   - GCFLAG_LOCAL_COPY: see stmimpl.rst.  Used by C.
 #
 #   - GCFLAG_VISITED: used temporarily to mark local objects found to be
-#     surviving during a collection.  Between collections, it can remain
-#     set on the LOCAL COPY objects, but only on them.
+#     surviving during a collection.  Between collections, it is set on
+#     the LOCAL COPY objects, but only on them.
 #
 #   - GCFLAG_HAS_SHADOW: set on nursery objects whose id() or identityhash()
 #     was taken.  Means that we already have a corresponding object allocated
         llmemory.raw_memcopy(obj - size_gc_header,
                              localobj - size_gc_header,
                              totalsize)
+        self.header(localobj).tid |= GCFLAG_VISITED
         return localobj
 
     # ----------

File pypy/rpython/memory/gc/stmtls.py

View file
  • Ignore whitespace
         debug_start("gc-local")
         #
         if end_of_transaction:
-            self.replace_pointers_following_revision = GCFLAG_LOCAL_COPY
+            self.detect_flag_combination = GCFLAG_LOCAL_COPY | GCFLAG_VISITED
         else:
-            self.replace_pointers_following_revision = 0
+            self.detect_flag_combination = -1
         #
         # Move away the previous sharedarea_tls and start a new one.
         from pypy.rpython.memory.gc.stmshared import StmGCThreadLocalAllocator
         while self.copied_local_objects.non_empty():
             obj = self.copied_local_objects.pop()
             hdr = self.gc.header(obj)
-            ll_assert(hdr.tid & GCFLAG_LOCAL_COPY != 0,"missing LOCAL_COPY [0]")
+            ll_assert(hdr.tid & GCFLAG_LOCAL_COPY, "missing LOCAL_COPY [0]")
             ll_assert(hdr.tid & GCFLAG_GLOBAL == 0, "already GLOBAL [0]")
+            ll_assert(hdr.tid & GCFLAG_VISITED, "missing VISITED [0]")
             hdr.tid |= GCFLAG_GLOBAL | GCFLAG_NOT_WRITTEN
+            hdr.tid &= ~(GCFLAG_VISITED | GCFLAG_LOCAL_COPY)
             # don't touch 'revision' in this case
 
     def _clear_version_for_global_object(self, hdr):
         if flag_combination == 0:
             return 0    # not marked as surviving, so far
 
-        if flag_combination & self.replace_pointers_following_revision:
-            # At a normal time, self.replace_pointers_following_revision
-            # is 0 and this case is never seen.  At end of transactions,
-            # detect_flag_combination is GCFLAG_LOCAL_COPY.
+        if flag_combination == self.detect_flag_combination:
+            # At a normal time, self.detect_flag_combination is -1
+            # and this case is never seen.  At end of transactions,
+            # detect_flag_combination is GCFLAG_LOCAL_COPY|GCFLAG_VISITED.
             # This case is to force pointers to the LOCAL copy to be
             # replaced with pointers to the GLOBAL copy.
             return 2
                   "in a root: unexpected GCFLAG_GLOBAL")
         ll_assert(localhdr.tid & GCFLAG_LOCAL_COPY != 0,
                   "in a root: missing GCFLAG_LOCAL_COPY")
-        # localhdr.tid & GCFLAG_VISITED may be set or not so far, with no
-        # particular consequence, but we force it to be set from now on (below)
+        ll_assert(localhdr.tid & GCFLAG_VISITED != 0,
+                  "in a root: missing GCFLAG_VISITED")
         globalhdr = self.gc.header(globalobj)
         ll_assert(globalhdr.tid & GCFLAG_GLOBAL != 0,
                   "in a root: GLOBAL: missing GCFLAG_GLOBAL")
                                    self.gc.get_type_id(globalobj))
         ll_assert(TL == TG, "in a root: type(LOCAL) != type(GLOBAL)")
         #
-        localhdr.tid |= GCFLAG_VISITED
-        self.pending.append(localobj)
+        self.trace_and_drag_out_of_nursery(localobj)
 
     def collect_flush_pending(self):
         # Follow the objects in the 'pending' stack and move the

File pypy/translator/stm/src_stm/et.c

View file
  • Ignore whitespace
   struct FXCache recent_reads_cache;
 };
 
-struct gcroot_s {
-    gcptr R, L;
-    revision_t v;
-};
-
 static volatile revision_t global_cur_time = 2;              /* always even */
 static volatile revision_t next_locked_value = LOCKED + 3;   /* always odd */
 static __thread struct tx_descriptor *thread_descriptor = NULL;
 
  not_found:
   L = pypy_g__stm_duplicate(R);
-  L->h_tid &= ~(GCFLAG_GLOBAL | GCFLAG_POSSIBLY_OUTDATED);
-  assert(L->h_tid & GCFLAG_NOT_WRITTEN);
-  L->h_tid |= GCFLAG_LOCAL_COPY;
+  assert(!(L->h_tid & GCFLAG_GLOBAL));   /* must be removed by stm_duplicate */
+  assert(!(L->h_tid & GCFLAG_POSSIBLY_OUTDATED));    /* must be removed by ^ */
+  assert(L->h_tid & GCFLAG_LOCAL_COPY);    /* must be added by stm_duplicate */
+  assert(L->h_tid & GCFLAG_NOT_WRITTEN); /* must not be set in the 1st place */
   L->h_revision = (revision_t)R;     /* back-reference to the original */
   g2l_insert(&d->global_to_local, R, L);
   return L;
   update_reads_size_limit(d);
 }
 
-#if 0
-static int compare_by_R(const void *a, const void *b)
-{
-    gcptr Ra = *(const gcptr *)a;
-    gcptr Rb = *(const gcptr *)b;
-    if (Ra < Rb)
-        return -1;
-    else if (Ra == Rb)
-        return 0;
-    else
-        return 1;
-}
-#endif
-
 static void AcquireLocks(struct tx_descriptor *d)
 {
   revision_t my_lock = d->my_lock;
-  struct gcroot_s *item = (struct gcroot_s *)d->gcroots.items;
-#if 0
+  gcptr *item = d->gcroots.items;
   // gcroots should be sorted in some deterministic order by construction
-  qsort(item, d->gcroots.size / 3, sizeof(struct gcroot_s), &compare_by_R);
-#endif
-  while (item->R != NULL)
+
+  while (item[0] != NULL)
     {
-      gcptr R = item->R;
+      gcptr R = (gcptr)item[0]->h_revision;
       revision_t v;
     retry:
       v = R->h_revision;
       if (!bool_cas((volatile revision_t *)&R->h_revision, v, my_lock))
         goto retry;
 
-      item->v = v;
-      item++;
+      item[1] = (gcptr)v;
+      item += 2;
     }
 }
 
 static void CancelLocks(struct tx_descriptor *d)
 {
-  long i, lastitem = d->gcroots.size - 3;
+  long i, lastitem = d->gcroots.size - 2;
   gcptr *items = d->gcroots.items;
-  for (i=0; i<=lastitem; i+=3)
+  for (i=0; i<=lastitem; i+=2)
     {
       gcptr R = items[i];
-      gcptr v = items[i+2];
+      revision_t v = (revision_t)items[i+1];
       if (v != 0)
         {
-          R->h_revision = (revision_t)v;
+          R->h_revision = v;
           // if we're going to retry later, and abort,
           // then we must not re-cancel the same entries
-          items[i+2] = 0;
+          items[i+1] = 0;
         }
     }
 }
 
 static void UpdateChainHeads(struct tx_descriptor *d, revision_t cur_time)
 {
-  struct gcroot_s *item, *itemstart = (struct gcroot_s *)d->gcroots.items;
+  gcptr *item, *itemstart = d->gcroots.items;
   revision_t new_revision = cur_time + 1;     // make an odd number
   assert(new_revision & 1);
 
-  for (item = itemstart; item->R != NULL; item++)
+  for (item = itemstart; item[0] != NULL; item += 2)
     {
-      gcptr L = item->L;
+      gcptr L = item[0];
       assert((L->h_tid & (GCFLAG_GLOBAL |
                           GCFLAG_NOT_WRITTEN |
                           GCFLAG_POSSIBLY_OUTDATED)) ==
               (GCFLAG_GLOBAL | GCFLAG_NOT_WRITTEN));
+      item[1] = (gcptr)L->h_revision;    /* old value: pointer to R */
       L->h_revision = new_revision;
     }
   smp_wmb();
-  for (item = itemstart; item->R != NULL; item++)
+  for (item = itemstart; item[0] != NULL; item += 2)
     {
-      gcptr L = item->L;
-      gcptr R = item->R;
+      gcptr L = item[0];
+      gcptr R = item[1];
       assert((R->h_tid & (GCFLAG_GLOBAL |
                           GCFLAG_NOT_WRITTEN |
                           GCFLAG_POSSIBLY_OUTDATED)) ==
     }
 }
 
-static struct gcroot_s *FindRootsForLocalCollect(void)
+static gcptr *FindRootsForLocalCollect(void)
 {
   struct tx_descriptor *d = thread_descriptor;
   wlog_t *item;
           L->h_tid |= GCFLAG_GLOBAL | GCFLAG_POSSIBLY_OUTDATED;
           continue;
         }
-      gcptrlist_insert3(&d->gcroots, R, L, (gcptr)0);
+      gcptrlist_insert2(&d->gcroots, L, (gcptr)0);
     } G2L_LOOP_END;
   gcptrlist_insert(&d->gcroots, NULL);
-  return (struct gcroot_s *)d->gcroots.items;
+  return d->gcroots.items;
 }
 
 int _FakeReach(gcptr P)

File pypy/translator/stm/src_stm/et.h

View file
  • Ignore whitespace
 
 
 extern void *pypy_g__stm_duplicate(void *);
-extern void pypy_g__stm_enum_callback(void *, void *, void *);
+extern void pypy_g__stm_enum_callback(void *, void *);
 void stm_set_tls(void *newtls);
 void *stm_get_tls(void);
 void stm_del_tls(void);

File pypy/translator/stm/src_stm/lists.c

View file
  • Ignore whitespace
   gcptrlist->items[gcptrlist->size++] = newitem;
 }
 
-static void gcptrlist_insert3(struct GcPtrList *gcptrlist, gcptr newitem1,
-                              gcptr newitem2, gcptr newitem3)
+static void gcptrlist_insert2(struct GcPtrList *gcptrlist, gcptr newitem1,
+                              gcptr newitem2)
 {
   gcptr *items;
   long i = gcptrlist->size;
-  if (__builtin_expect((gcptrlist->alloc - i) < 3, 0))
+  if (__builtin_expect((gcptrlist->alloc - i) < 2, 0))
     _gcptrlist_grow(gcptrlist);
   items = gcptrlist->items;
   items[i+0] = newitem1;
   items[i+1] = newitem2;
-  items[i+2] = newitem3;
-  gcptrlist->size = i + 3;
+  gcptrlist->size = i + 2;
 }
 
 /************************************************************/

File pypy/translator/stm/src_stm/rpyintf.c

View file
  • Ignore whitespace
   struct tx_descriptor *d = thread_descriptor;
   wlog_t *item;
   void *tls = stm_get_tls();
-  struct gcroot_s *gcroots = FindRootsForLocalCollect();
+  gcptr *gcroots = FindRootsForLocalCollect();
 
-  while (gcroots->R != NULL)
+  while (gcroots[0] != NULL)
     {
-      pypy_g__stm_enum_callback(tls, gcroots->R, gcroots->L);
-      gcroots++;
+      pypy_g__stm_enum_callback(tls, gcroots[0]);
+      gcroots += 2;
     }
 }
 
         abort();
     }
     memcpy(result, src, size);
+    ((gcptr)result)->h_tid &= ~(GCFLAG_GLOBAL | GCFLAG_POSSIBLY_OUTDATED);
+    ((gcptr)result)->h_tid |= GCFLAG_LOCAL_COPY;
     return result;
 }
-void pypy_g__stm_enum_callback(void *tlsaddr, void *R, void *L)
+void pypy_g__stm_enum_callback(void *tlsaddr, void *L)
 {
     abort();
 }

File pypy/translator/stm/test/test_stmgcintf.c

View file
  • Ignore whitespace
 
 
 gcptr (*cb_duplicate)(gcptr);
-void (*cb_enum_callback)(void *, gcptr, gcptr);
+void (*cb_enum_callback)(void *, gcptr);
 
 void *pypy_g__stm_duplicate(void *a) {
     assert(cb_duplicate != NULL);
     return cb_duplicate((gcptr)a);
 }
-void pypy_g__stm_enum_callback(void *a, void *b, void *c) {
+void pypy_g__stm_enum_callback(void *a, void *b) {
     assert(cb_enum_callback != NULL);
-    cb_enum_callback(a, (gcptr)b, (gcptr)c);
+    cb_enum_callback(a, (gcptr)b);
 }
 
 
 /************************************************************/
 
 struct pypy_header0 etldn1 = {GCFLAG_PREBUILT, REV_INITIAL};
-struct pypy_header0 etldn2 = {0, 0};
+struct pypy_header0 etldn2 = {GCFLAG_LOCAL_COPY, (revision_t)&etldn1};
 struct pypy_header0 etldn3 = {GCFLAG_PREBUILT, REV_INITIAL};
-struct pypy_header0 etldn4 = {0, 0};
+struct pypy_header0 etldn4 = {GCFLAG_LOCAL_COPY, (revision_t)&etldn3};
 
 int check_enum_1_found;
-void check_enum_1(void *tls, gcptr a, gcptr b)
+void check_enum_1(void *tls, gcptr b)
 {
     int n;
+    gcptr a = (gcptr)b->h_revision;
     assert(tls == (void *)742);
     if (a == &etldn1 && b == &etldn2)
         n = 1;
 }
 gcptr duplicator_cb(gcptr x)
 {
-    assert(x == &sg_global);
+    assert(x == &sg_global.header);
     sg_local = sg_global;
-    return &sg_local;
+    sg_local.header.h_tid &= ~(GCFLAG_GLOBAL | GCFLAG_POSSIBLY_OUTDATED);
+    sg_local.header.h_tid |= GCFLAG_LOCAL_COPY;
+    return &sg_local.header;
 }
 void test_duplicator(void)
 {