Author: Remi Meier <[email protected]>
Branch:
Changeset: r256:67200f7bca96
Date: 2013-06-24 14:39 +0200
http://bitbucket.org/pypy/stmgc/changeset/67200f7bca96/
Log: add support for predefined hash in prebuilt objects
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -489,9 +489,13 @@
/* note that stmgc_duplicate() usually returns a young object, but may
return an old one if the nursery is full at this moment. */
gcptr L = stmgc_duplicate(R);
- if (!(L->h_original)) {
- /* if we don't have an original object yet,
- it must be the old public R */
+ if (!(L->h_original) || L->h_tid & GCFLAG_PREBUILT_ORIGINAL) {
+ /* if we don't have an original object yet, it must be the
+ old public R
+ Also, prebuilt objects may have a predefined hash stored
+ in the h_original. -> point to the original copy on copies
+ of the prebuilt.
+ */
assert(R->h_tid & GCFLAG_OLD); // if not, force stm_id??
L->h_original = (revision_t)R;
}
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -110,12 +110,6 @@
the shadow-original.
*/
-revision_t stm_hash(gcptr p)
-{
- return stm_id(p);
-}
-
-
static revision_t mangle_hash(revision_t n)
{
/* To hash pointers in dictionaries. Assumes that i shows some
@@ -127,13 +121,40 @@
return n ^ (n >> 4);
}
+
+revision_t stm_hash(gcptr p)
+{
+ /* Prebuilt objects may have a specific hash stored in an extra
+ field. For now, we will simply always follow h_original and
+ see, if it is a prebuilt object (XXX: maybe propagate a flag
+ to all copies of a prebuilt to avoid this cache miss).
+ */
+ if (p->h_original) {
+ if (p->h_tid & GCFLAG_PREBUILT_ORIGINAL) {
+ return p->h_original;
+ }
+ gcptr orig = (gcptr)p->h_original;
+ if ((orig->h_tid & GCFLAG_PREBUILT_ORIGINAL) && orig->h_original) {
+ return orig->h_original;
+ }
+ }
+ return stm_id(p);
+}
+
+
revision_t stm_id(gcptr p)
{
struct tx_descriptor *d = thread_descriptor;
revision_t result;
-
if (p->h_original) { /* fast path */
+ if (p->h_tid & GCFLAG_PREBUILT_ORIGINAL) {
+ /* h_original may contain a specific hash value,
+ but in case of the prebuilt original version,
+ its memory location is the id */
+ return mangle_hash((revision_t)p);
+ }
+
fprintf(stderr, "stm_id(%p) has orig fst: %p\n",
p, (gcptr)p->h_original);
return mangle_hash(p->h_original);
@@ -152,6 +173,7 @@
fprintf(stderr, "stm_id(%p) is old, orig=0 fst: %p\n", p, p);
return mangle_hash((revision_t)p);
}
+
spinlock_acquire(d->public_descriptor->collection_lock, 'I');
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -91,6 +91,7 @@
void rawsetlong(gcptr, long, long);
gcptr pseudoprebuilt(size_t size, int tid);
+ gcptr pseudoprebuilt_with_hash(size_t size, int tid, revision_t hash);
revision_t get_private_rev_num(void);
revision_t get_start_time(void);
void *my_stub_thread(void);
@@ -217,6 +218,13 @@
return x;
}
+ gcptr pseudoprebuilt_with_hash(size_t size, int tid, revision_t hash)
+ {
+ gcptr x = pseudoprebuilt(size, tid);
+ x->h_original = hash;
+ return x;
+ }
+
revision_t get_start_time(void)
{
return thread_descriptor->start_time;
@@ -473,15 +481,22 @@
assert rawgetptr(p, i) == ffi.NULL # must already be zero-filled
return p
-def palloc(size):
+def palloc(size, prehash=None):
"Get a ``prebuilt'' object."
- p = lib.pseudoprebuilt(size, 42 + size)
+ if prehash is None:
+ p = lib.pseudoprebuilt(size, 42 + size)
+ else:
+ p = lib.pseudoprebuilt_with_hash(size, 42 + size, prehash)
assert p.h_revision == 1
return p
-def palloc_refs(nrefs):
+def palloc_refs(nrefs, prehash=None):
"Get a ``prebuilt'' object with nrefs pointers."
- p = lib.pseudoprebuilt(HDR + WORD * nrefs, 421 + nrefs)
+ if prehash is None:
+ p = lib.pseudoprebuilt(HDR + WORD * nrefs, 421 + nrefs)
+ else:
+ p = lib.pseudoprebuilt_with_hash(HDR + WORD * nrefs,
+ 421 + nrefs, prehash)
return p
gettid = lib.gettid
diff --git a/c4/test/test_et.py b/c4/test/test_et.py
--- a/c4/test/test_et.py
+++ b/c4/test/test_et.py
@@ -569,4 +569,44 @@
id_with_stealing(0, 1)
id_with_stealing(0, 0)
+
+def test_prehash_simple():
+ p = palloc(HDR, 99)
+ assert lib.stm_hash(p) == 99
+ assert lib.stm_id(p) != lib.stm_hash(p)
+ pr = lib.stm_read_barrier(p)
+ assert lib.stm_hash(pr) == 99
+ assert lib.stm_id(p) == lib.stm_id(pr)
+ pw = lib.stm_write_barrier(p)
+ assert lib.stm_hash(pw) == 99
+ assert lib.stm_id(p) == lib.stm_id(pw)
+ lib.stm_push_root(pw)
+ minor_collect()
+ pw = lib.stm_pop_root()
+ assert lib.stm_hash(pw) == 99
+
+
+def test_prehash_with_stealing():
+ p = palloc(HDR, 99)
+ def f1(r):
+ lib.stm_write_barrier(p) # private copy
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
+ # p old public -> stub -> p1 young prot
+ r.set(2)
+ r.wait(3) # wait until the other thread really started
+ def f2(r):
+ r.wait(2)
+ r.set(3)
+
+ p2 = lib.stm_read_barrier(p) # steals
+ assert lib.stm_hash(p) == 99
+ assert lib.stm_hash(p2) == 99
+ assert lib.stm_id(p) == lib.stm_id(p2)
+ assert lib.stm_hash(p) != lib.stm_id(p)
+ run_parallel(f1, f2)
+
+
+
+
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit