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