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