[pypy-commit] stmgc default: Fix the two previous tests.

arigo noreply at buildbot.pypy.org
Sun May 26 18:56:52 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r22:1dd1331ec33e
Date: 2013-05-26 18:56 +0200
http://bitbucket.org/pypy/stmgc/changeset/1dd1331ec33e/

Log:	Fix the two previous tests.

diff --git a/c3/lists.c b/c3/lists.c
--- a/c3/lists.c
+++ b/c3/lists.c
@@ -22,6 +22,19 @@
   memset(g2l, 0, sizeof(struct G2L));
 }
 
+struct G2L *g2l_malloc(void)
+{
+  struct G2L *g2l = malloc(sizeof(struct G2L));
+  memset(g2l, 0, sizeof(struct G2L));
+  return g2l;
+}
+
+void g2l_free(struct G2L *g2l)
+{
+  free(g2l->raw_start);
+  free(g2l);
+}
+
 wlog_t *_g2l_find(char *entry, gcptr addr)
 {
   revision_t key = (revision_t)addr;
@@ -172,6 +185,16 @@
   gcptrlist->size = i + 3;
 }
 
+void gcptrlist_insert_at_index(struct GcPtrList *gcptrlist, long index,
+                               gcptr newitem)
+{
+    long lastitem = gcptrlist->size;
+    assert(index <= lastitem);
+    gcptrlist_insert(gcptrlist, NULL);
+    gcptrlist->items[lastitem] = gcptrlist->items[index];
+    gcptrlist->items[index] = newitem;
+}
+
 void gcptrlist_merge(struct GcPtrList *gcptrlist,
                      struct GcPtrList *gcptrlist_source)
 {
diff --git a/c3/lists.h b/c3/lists.h
--- a/c3/lists.h
+++ b/c3/lists.h
@@ -35,6 +35,8 @@
 
 void g2l_clear(struct G2L *g2l);
 void g2l_delete(struct G2L *g2l);
+struct G2L *g2l_malloc(void);
+void g2l_free(struct G2L *g2l);
 
 static inline int g2l_any_entry(struct G2L *g2l) {
     return g2l->raw_current != g2l->raw_start;
@@ -133,14 +135,20 @@
 void gcptrlist_insert3(struct GcPtrList *gcptrlist, gcptr newitem1,
                        gcptr newitem2, gcptr newitem3);
 
-static inline void gcptrlist_insert(struct GcPtrList *gcptrlist, gcptr newitem) {
+/* items[size++] = items[index]; items[index] = newitem; */
+void gcptrlist_insert_at_index(struct GcPtrList *gcptrlist, long index,
+                               gcptr newitem);
+
+static inline void gcptrlist_insert(struct GcPtrList *gcptrlist, gcptr newitem)
+{
     if (UNLIKELY(gcptrlist->size == gcptrlist->alloc))
         _gcptrlist_grow(gcptrlist);
     gcptrlist->items[gcptrlist->size++] = newitem;
 }
 
-static inline void gcptrlist_reduce_size(struct GcPtrList *gcptrlist, long newsize) {
-    gcptrlist->size = newsize;
+static inline void gcptrlist_reduce_size(struct GcPtrList *gcptrlist, long nsz)
+{
+    gcptrlist->size = nsz;
 }
 
 static inline long gcptrlist_size(struct GcPtrList *gcptrlist)
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -661,19 +661,54 @@
     spinlock_release(d->collection_lock);
 }
 
+static __thread struct G2L *yo_stubs;   /* { protected: public_stub } */
+
 static void create_yo_stubs(gcptr *pobj)
 {
-    gcptr obj = *pobj;
+    gcptr stub, obj = *pobj;
     if (obj == NULL || (obj->h_tid & GCFLAG_OLD) != 0)
         return;
 
-    /* xxx try to avoid duplicate stubs for the same object */
-    gcptr stub = stmgcpage_malloc(sizeof(*stub));
+    /* we use 'yo_stubs', a dictionary, in order to try to avoid
+       duplicate stubs for the same object */
+    if (yo_stubs == NULL) {
+        yo_stubs = g2l_malloc();
+    }
+    else {
+        wlog_t *item;
+        G2L_FIND(*yo_stubs, obj, item, goto not_found);
+        /* found already */
+        stub = item->val;
+        assert(stub->h_revision == (((revision_t)obj) | 2));
+        *pobj = stub;
+        return;
+    }
+
+ not_found:
+    stub = stmgcpage_malloc(sizeof(*stub));
     stub->h_tid = GCFLAG_OLD | GCFLAG_STUB;    /* with type_id == 0 */
     stub->h_revision = ((revision_t)obj) | 2;
+    g2l_insert(yo_stubs, obj, stub);
     *pobj = stub;
 }
 
+static long done_creating_yo_stubs(struct GcPtrList *add_to_list, long index)
+{
+    wlog_t *item;
+    struct G2L *stubs = yo_stubs;
+    if (stubs == NULL)
+        return index;
+
+    G2L_LOOP_FORWARD(*stubs, item) {
+        gcptrlist_insert_at_index(add_to_list, index, item->val);
+        index++;
+    } G2L_LOOP_END;
+
+    g2l_free(stubs);
+    yo_stubs = NULL;
+    return index;
+}
+
 static void fix_new_public_to_protected_references(struct tx_descriptor *d)
 {
     long i, size = d->private_old_pointing_to_young.size;
@@ -683,6 +718,8 @@
         stmcb_trace(items[i], &create_yo_stubs);
     }
     gcptrlist_clear(&d->private_old_pointing_to_young);
+    d->num_public_to_protected = done_creating_yo_stubs(
+            &d->public_to_young, d->num_public_to_protected);
 }
 
 static void free_unvisited_young_objects_outside_nursery(
@@ -900,12 +937,20 @@
     /* R is now the protected object to move outside, with revision v. */
     N = create_old_object_copy(R  _REASON("**stolen copy"));
     N->h_revision = v;
-    gcptrlist_insert2(&source_d->stolen_objects, R, N);
+    gcptrlist_insert3(&source_d->stolen_objects, R, N, NULL);
 
     /* there might be references in N going to protected objects.  We
        must fix them with stubs. */
     stmcb_trace(N, &create_yo_stubs);
 
+    /* Cannot insert them here into the 'public_to_young' list, because
+       it might be accessed concurrently by the thread 'source_d'.
+       Instead we put them into stolen_objects.  They are inserted
+       at position 'size - 1', which means just before the final NULL
+       that was already pushed by the above gcptrlist_insert3(). */
+    done_creating_yo_stubs(&source_d->stolen_objects,
+                           source_d->stolen_objects.size - 1);
+
     return N;
 }
 
@@ -980,7 +1025,7 @@
     gcptr *items = d->stolen_objects.items;
     assert(d == thread_descriptor);
 
-    for (i = 0; i < size; i += 2) {
+    for (i = 0; i < size; ) {
         gcptr R = items[i];
         gcptr N = items[i + 1];
 
@@ -1007,6 +1052,17 @@
             gcptrlist_insert(&d->public_to_young, N);
         }
         recdump1("STOLEN", R);
+
+        /* then all items from i+2 up to the first NULL are new stubs
+           that must be added to d->public_to_young, in the first part
+           (i.e. before d->num_public_to_protected) */
+        i += 2;
+        long ptp = d->num_public_to_protected;
+        while ((N = items[i++]) != NULL) {
+            gcptrlist_insert_at_index(&d->public_to_young, ptp, N);
+            ptp++;
+        }
+        d->num_public_to_protected = ptp;
     }
     gcptrlist_clear(&d->stolen_objects);
 }


More information about the pypy-commit mailing list