Author: Remi Meier <meier...@student.ethz.ch>
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
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to