[pypy-commit] stmgc default: Finish prebuilt.c, according to its test (which I forgot to check-in earlier)

arigo noreply at buildbot.pypy.org
Sun Mar 2 20:03:13 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r927:d8c4f5b49016
Date: 2014-03-02 20:03 +0100
http://bitbucket.org/pypy/stmgc/changeset/d8c4f5b49016/

Log:	Finish prebuilt.c, according to its test (which I forgot to check-in
	earlier)

diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -536,11 +536,10 @@
     major_clear_write_locks();
 
     /* marking */
-    mark_objects_to_trace = list_create();
+    LIST_CREATE(mark_objects_to_trace);
     mark_visit_from_modified_objects();
     mark_visit_from_roots();
-    list_free(mark_objects_to_trace);
-    mark_objects_to_trace = NULL;
+    LIST_FREE(mark_objects_to_trace);
 
     /* cleanup */
     clean_up_segment_lists();
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -15,6 +15,7 @@
     free(lst);
 }
 
+#define LIST_CREATE(lst)  ((lst) = list_create())
 #define LIST_FREE(lst)  (list_free(lst), (lst) = NULL)
 
 
diff --git a/c7/stm/prebuilt.c b/c7/stm/prebuilt.c
--- a/c7/stm/prebuilt.c
+++ b/c7/stm/prebuilt.c
@@ -5,23 +5,26 @@
 
 #define GCWORD_PREBUILT_MOVED  ((object_t *) 42)
 
+static struct list_s *prebuilt_objects_to_trace;
 
-object_t *stm_setup_prebuilt(object_t *staticobj_invalid)
+
+static void prebuilt_trace(object_t **pstaticobj_invalid)
 {
-    /* All variable names in "_invalid" here mean that although the
-       type is really "object_t *", it should not actually be accessed
-       via %gs.
+    uintptr_t objaddr = (uintptr_t)*pstaticobj_invalid;
+    struct object_s *obj = (struct object_s *)objaddr;
 
-       If the object was already moved, its first word was set to
+    if (obj == NULL)
+        return;
+
+    /* If the object was already moved, its first word was set to
        GCWORD_PREBUILT_MOVED.  In that case, the forwarding location,
        i.e. where the object moved to, is stored in the second word.
     */
-    uintptr_t objaddr = (uintptr_t)staticobj_invalid;
-    struct object_s *obj = (struct object_s *)objaddr;
     object_t **pforwarded_array = (object_t **)objaddr;
 
     if (pforwarded_array[0] == GCWORD_PREBUILT_MOVED) {
-        return pforwarded_array[1];    /* already moved */
+        *pstaticobj_invalid = pforwarded_array[1];    /* already moved */
+        return;
     }
 
     /* We need to make a copy of this object. */
@@ -32,7 +35,33 @@
     char *realnobj = REAL_ADDRESS(stm_object_pages, nobj);
     memcpy(realnobj, (char *)objaddr, size);
 
-    // XXX REFERENCES HERE
+    /* Mark the original object */
+    pforwarded_array[0] = GCWORD_PREBUILT_MOVED;
+    pforwarded_array[1] = nobj;
 
-    return nobj;
+    /* Done */
+    *pstaticobj_invalid = nobj;
+    LIST_APPEND(prebuilt_objects_to_trace, realnobj);
 }
+
+object_t *stm_setup_prebuilt(object_t *staticobj_invalid)
+{
+    /* All variable names in "_invalid" here mean that although the
+       type is really "object_t *", it should not actually be accessed
+       via %gs.
+    */
+    LIST_CREATE(prebuilt_objects_to_trace);
+
+    object_t *obj = staticobj_invalid;
+    prebuilt_trace(&obj);
+
+    while (!list_is_empty(prebuilt_objects_to_trace)) {
+        struct object_s *realobj1 =
+            (struct object_s *)list_pop_item(prebuilt_objects_to_trace);
+        stmcb_trace(realobj1, &prebuilt_trace);
+    }
+
+    LIST_FREE(prebuilt_objects_to_trace);
+
+    return obj;
+}
diff --git a/c7/test/test_prebuilt.py b/c7/test/test_prebuilt.py
new file mode 100644
--- /dev/null
+++ b/c7/test/test_prebuilt.py
@@ -0,0 +1,63 @@
+from support import *
+import py
+import weakref
+
+
+prebuilt_dict = weakref.WeakKeyDictionary()
+
+def _prebuilt(size, tid):
+    assert size >= 16
+    assert (size & 7) == 0
+    myobj1 = ffi.new("char[]", size)
+    myobj = ffi.cast("object_t *", myobj1)
+    prebuilt_dict[myobj] = myobj1
+    ffi.cast("uint32_t *", myobj)[1] = tid
+    return myobj
+
+def prebuilt(size):
+    return _prebuilt(size, 42 + size)
+
+def prebuilt_refs(n):
+    return _prebuilt(HDR + n * WORD, 421420 + n)
+
+
+class TestPrebuilt(BaseTest):
+
+    def test_simple_prebuilt(self):
+        static1 = prebuilt(16)
+        ffi.cast("char *", static1)[8:11] = 'ABC'
+        print static1
+        lp = lib.stm_setup_prebuilt(static1)
+        #
+        self.start_transaction()
+        assert stm_get_char(lp, 8) == 'A'
+        assert stm_get_char(lp, 9) == 'B'
+        assert stm_get_char(lp, 10) == 'C'
+
+    def test_prebuilt_rec(self):
+        static1 = prebuilt_refs(2)
+        static2 = prebuilt(16)
+        ffi.cast("char *", static2)[8:11] = 'ABC'
+        ffi.cast("object_t **", static1)[1] = static2
+        lp1 = lib.stm_setup_prebuilt(static1)
+        #
+        self.start_transaction()
+        assert not stm_get_ref(lp1, 1)
+        lp2 = stm_get_ref(lp1, 0)
+        print lp2
+        assert stm_get_char(lp2, 8) == 'A'
+        assert stm_get_char(lp2, 9) == 'B'
+        assert stm_get_char(lp2, 10) == 'C'
+
+    def test_prebuilt_rec_cycle(self):
+        static1 = prebuilt_refs(1)
+        static2 = prebuilt_refs(1)
+        ffi.cast("object_t **", static1)[1] = static2
+        ffi.cast("object_t **", static2)[1] = static1
+        lp1 = lib.stm_setup_prebuilt(static1)
+        #
+        self.start_transaction()
+        lp2 = stm_get_ref(lp1, 0)
+        print lp2
+        assert lp2 != lp1
+        assert stm_get_ref(lp2, 0) == lp1


More information about the pypy-commit mailing list