Author: Remi Meier <[email protected]>
Branch: 
Changeset: r1375:9817d13b7e38
Date: 2014-09-09 11:16 +0200
http://bitbucket.org/pypy/stmgc/changeset/9817d13b7e38/

Log:    add prebuilt-support

diff --git a/c8/stm/prebuilt.c b/c8/stm/prebuilt.c
new file mode 100644
--- /dev/null
+++ b/c8/stm/prebuilt.c
@@ -0,0 +1,73 @@
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+
+static struct list_s *prebuilt_objects_to_trace;
+static struct tree_s *tree_prebuilt_objs;  /* XXX from gcpage.c */
+
+
+static void prebuilt_trace(object_t **pstaticobj_invalid)
+{
+    uintptr_t objaddr = (uintptr_t)*pstaticobj_invalid;
+    struct object_s *obj = (struct object_s *)objaddr;
+
+    if (obj == NULL)
+        return;
+
+    /* If the object was already moved, it is stored in 'tree_prebuilt_objs'.
+       For now we use this dictionary, with keys being equal to the numeric
+       address of the prebuilt object.
+     */
+    wlog_t *item;
+    TREE_FIND(tree_prebuilt_objs, (uintptr_t)obj, item, goto not_found);
+
+    *pstaticobj_invalid = (object_t *)item->val;    /* already moved */
+    return;
+
+ not_found:;
+    /* We need to make a copy of this object.  The extra "long" is for
+       the prebuilt hash. */
+    size_t size = stmcb_size_rounded_up(obj);
+    object_t *nobj = _stm_allocate_old(size + sizeof(long));
+
+    /* Copy the object */
+    char *realnobj = REAL_ADDRESS(stm_object_pages, nobj);
+    memcpy(realnobj, (char *)objaddr, size);
+
+    /* Fix the flags in the copied object, asserting that it was zero so far */
+    assert(nobj->stm_flags == 0);
+    nobj->stm_flags = GCFLAG_WRITE_BARRIER;
+
+    /* Add the object to the tree */
+    tree_insert(tree_prebuilt_objs, (uintptr_t)obj, (uintptr_t)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.
+    */
+    if (tree_prebuilt_objs == NULL)
+        tree_prebuilt_objs = tree_create();
+
+    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/c8/stmgc.c b/c8/stmgc.c
--- a/c8/stmgc.c
+++ b/c8/stmgc.c
@@ -23,4 +23,5 @@
 #include "stm/fprintcolor.c"
 #include "stm/rewind_setjmp.c"
 #include "stm/hash_id.c"
+#include "stm/prebuilt.c"
 #include "stm/misc.c"
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -187,6 +187,12 @@
 
 void stm_collect(long level);
 
+long stm_identityhash(object_t *obj);
+long stm_id(object_t *obj);
+void stm_set_prebuilt_identityhash(object_t *obj, long hash);
+
+object_t *stm_setup_prebuilt(object_t *);
+
 
 #ifdef STM_NO_AUTOMATIC_SETJMP
 int stm_is_inevitable(void);
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -42,6 +42,9 @@
 void stm_validate(void *free_if_abort);
 bool _check_stm_validate();
 
+object_t *stm_setup_prebuilt(object_t *);
+
+
 bool _checked_stm_write(object_t *obj);
 bool _stm_was_read(object_t *obj);
 bool _stm_was_written(object_t *obj);
diff --git a/c8/test/test_prebuilt.py b/c8/test/test_prebuilt.py
new file mode 100644
--- /dev/null
+++ b/c8/test/test_prebuilt.py
@@ -0,0 +1,99 @@
+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
+        assert lib._stm_get_flags(lp1) == lib._STM_GCFLAG_WRITE_BARRIER
+        assert lib._stm_get_flags(lp2) == lib._STM_GCFLAG_WRITE_BARRIER
+
+    def test_multiple_calls_to_stm_setup_prebuilt_1(self, reverse=False):
+        static1 = prebuilt_refs(1)
+        static2 = prebuilt_refs(1)
+        ffi.cast("object_t **", static1)[1] = static2
+        if not reverse:
+            lp1 = lib.stm_setup_prebuilt(static1)
+            lp2 = lib.stm_setup_prebuilt(static2)
+        else:
+            lp2 = lib.stm_setup_prebuilt(static2)
+            lp1 = lib.stm_setup_prebuilt(static1)
+        #
+        self.start_transaction()
+        assert stm_get_ref(lp1, 0) == lp2
+        assert stm_get_ref(lp2, 0) == ffi.NULL
+        assert lib._stm_get_flags(lp1) == lib._STM_GCFLAG_WRITE_BARRIER
+        assert lib._stm_get_flags(lp2) == lib._STM_GCFLAG_WRITE_BARRIER
+
+    def test_multiple_calls_to_stm_setup_prebuilt_2(self):
+        self.test_multiple_calls_to_stm_setup_prebuilt_1(reverse=True)
+
+    def test_prebuilt_align_4_byte(self):
+        static0 = prebuilt(16)
+        p0 = ffi.cast("char *", static0)
+        for i in reversed(range(12)):
+            p0[i + 4] = p0[i]
+        static1 = ffi.cast("object_t *", p0 + 4)
+        ffi.cast("char *", static1)[8:11] = 'ABC'
+        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'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to