Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r321:7c03d107c940
Date: 2013-06-30 19:11 +0200
http://bitbucket.org/pypy/stmgc/changeset/7c03d107c940/

Log:    Redo the hack about END_MARKERs in the shadowstack.

diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -320,13 +320,20 @@
 
 static void mark_roots(gcptr *root, gcptr *end)
 {
-    //assert(*root == END_MARKER);
-    //root++;
+    assert(*root == END_MARKER_ON);
+    root++;
+
     while (root != end) {
-        gcptr o = *root;
-        visit(root);
-        dprintf(("visit stack root: %p -> %p\n", o, *root));
-        (void)o;   /* silence "warning: unused variable 'o'" */
+        gcptr item = *root;
+        if (((revision_t)item) & ~((revision_t)END_MARKER_OFF |
+                                   (revision_t)END_MARKER_ON)) {
+            /* 'item' is a regular, non-null pointer */
+            visit(root);
+            dprintf(("visit stack root: %p -> %p\n", item, *root));
+        }
+        else if (item == END_MARKER_OFF) {
+            *root = END_MARKER_ON;
+        }
         root++;
     }
 }
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -323,12 +323,30 @@
 
 static void mark_young_roots(struct tx_descriptor *d)
 {
-    gcptr *root = d->shadowstack;
+    /* we walk the shadowstack from the end, replacing any END_MARKER_OFF
+       found with END_MARKER_ON.  When we reach an END_MARKER_ON, we know
+       that we have already seen the rest of the stack in the previous
+       nursery collection, so we stop.
+    */
     gcptr *end = *d->shadowstack_end_ref;
 
-    /* XXX use a way to avoid walking all roots again and again */
-    for (; root != end; root++) {
-        visit_if_young(root);
+    while (1) {
+        assert(end > d->shadowstack);
+        gcptr item = *--end;
+
+        if (((revision_t)item) & ~((revision_t)END_MARKER_OFF |
+                                   (revision_t)END_MARKER_ON)) {
+            /* 'item' is a regular, non-null pointer */
+            visit_if_young(end);
+        }
+        else if (item != NULL) {
+            if (item == END_MARKER_OFF)
+                *end = END_MARKER_ON;
+            else {
+                assert(item == END_MARKER_ON);
+                break;
+            }
+        }
     }
 }
 
diff --git a/c4/nursery.h b/c4/nursery.h
--- a/c4/nursery.h
+++ b/c4/nursery.h
@@ -18,6 +18,9 @@
 # error "GC_NURSERY must be a multiple of GC_NURSERY_SECTION"
 #endif
 
+#define END_MARKER_OFF  ((gcptr) 16)
+#define END_MARKER_ON   ((gcptr) 24)
+
 
 #define NURSERY_FIELDS_DECL                                             \
     /* the nursery */                                                   \
diff --git a/c4/stmsync.c b/c4/stmsync.c
--- a/c4/stmsync.c
+++ b/c4/stmsync.c
@@ -25,14 +25,14 @@
     }
     stm_shadowstack = d->shadowstack;
     d->shadowstack_end_ref = &stm_shadowstack;
-    //stm_push_root(END_MARKER);
+    stm_push_root(END_MARKER_ON);
 }
 
 static void done_shadowstack(void)
 {
     struct tx_descriptor *d = thread_descriptor;
-    //gcptr x = stm_pop_root();
-    //assert(x == END_MARKER);
+    gcptr x = stm_pop_root();
+    assert(x == END_MARKER_ON);
     assert(stm_shadowstack == d->shadowstack);
     stm_shadowstack = NULL;
     free(d->shadowstack);
@@ -77,6 +77,7 @@
     long volatile v_atomic;
 
     stm_push_root(arg);
+    stm_push_root(END_MARKER_OFF);
 
     if (!(v_atomic = thread_descriptor->atomic))
         CommitTransaction();
@@ -98,14 +99,7 @@
     long counter, result;
     counter = v_counter;
     d->atomic = v_atomic;
-    stm_shadowstack = v_saved_value + 1;    /* skip the 'arg', pushed above */
-    //    if (!d->atomic) {
-    //        /* In non-atomic mode, we are now between two transactions.
-    //           It means that in the next transaction's collections we know
-    //           that we won't need to access the shadow stack beyond its
-    //           current position.  So we add an end marker. */
-    //        stm_push_root(END_MARKER);
-    //    }
+    stm_shadowstack = v_saved_value + 2;   /*skip the two values pushed above*/
 
     do {
         v_counter = counter + 1;
@@ -135,7 +129,7 @@
         /* invoke the callback in the new transaction */
         arg = v_saved_value[0];
         result = callback(arg, counter);
-        assert(stm_shadowstack == v_saved_value + 1);
+        assert(stm_shadowstack == v_saved_value + 2);
 
         v_atomic = d->atomic;
         if (!d->atomic)
@@ -154,7 +148,9 @@
         BeginInevitableTransaction();
     }
 
-    stm_pop_root();      /* pop the 'arg' */
+    gcptr x = stm_pop_root();   /* pop the END_MARKER */
+    assert(x == END_MARKER_OFF || x == END_MARKER_ON);
+    stm_pop_root();             /* pop the 'arg' */
     assert(stm_shadowstack == v_saved_value);
 }
 
diff --git a/c4/test/test_random.py b/c4/test/test_random.py
--- a/c4/test/test_random.py
+++ b/c4/test/test_random.py
@@ -305,12 +305,16 @@
         #
         self.roots = self.roots_outside_perform[:]
         self.startrev()
-        # XXX stm_perform_transaction() adds one root for the unused arg
+        # XXX stm_perform_transaction() adds one root for the unused arg,
+        # and one for an END_MARKER
+        end_marker = lib.stm_pop_root()
+        assert int(ffi.cast("revision_t", end_marker)) in [16, 24]
         arg = lib.stm_pop_root()
         assert arg == ffi.NULL
         self.pop_roots()
         self.push_roots()
         lib.stm_push_root(arg)
+        lib.stm_push_root(end_marker)
         self.check_valid(self.roots)
         #
         try:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to