Author: Remi Meier <meier...@student.ethz.ch> Branch: implement-id Changeset: r216:04f0776e142a Date: 2013-06-20 16:51 +0200 http://bitbucket.org/pypy/stmgc/changeset/04f0776e142a/
Log: work in progress diff --git a/c4/et.h b/c4/et.h --- a/c4/et.h +++ b/c4/et.h @@ -57,6 +57,9 @@ * but converted from a protected. These are precisely the objects * that have a backup copy (in h_revision), which gives a copy of the * original protected object. + * + * GCFLAG_HAS_ID is set on young objects that have an old reserved + * memory to be copied to in minor collections (obj->h_original) */ static const revision_t GCFLAG_OLD = STM_FIRST_GCFLAG << 0; static const revision_t GCFLAG_VISITED = STM_FIRST_GCFLAG << 1; @@ -68,6 +71,7 @@ static const revision_t GCFLAG_BACKUP_COPY /*debug*/ = STM_FIRST_GCFLAG << 7; static const revision_t GCFLAG_STUB /*debug*/ = STM_FIRST_GCFLAG << 8; static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG << 9; +static const revision_t GCFLAG_HAS_ID = STM_FIRST_GCFLAG << 10; /* this value must be reflected in PREBUILT_FLAGS in stmgc.h */ #define GCFLAG_PREBUILT (GCFLAG_VISITED | \ diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -59,6 +59,7 @@ assert(tid == (tid & STM_USER_TID_MASK)); P->h_tid = tid; P->h_revision = stm_private_rev_num; + P->h_original = NULL; return P; } @@ -71,6 +72,13 @@ memcpy(L, P, size); L->h_tid &= ~GCFLAG_OLD; + L->h_tid &= ~GCFLAG_HAS_ID; + + if (P->h_original) + L->h_original = P->h_original; + else + L->h_original = P; + return L; } @@ -80,11 +88,64 @@ gcptr L = (gcptr)stmgcpage_malloc(size); memcpy(L, P, size); L->h_tid |= GCFLAG_OLD; + L->h_tid &= ~GCFLAG_HAS_ID; + + if (P->h_original) + L->h_original = P->h_original; + else + L->h_original = P; + return L; } /************************************************************/ + +revision_t stm_hash(gcptr p) +{ + return stm_id(p); +} + +revision_t stm_id(gcptr p) +{ + if (p->h_original) { + return p->h_original; + } + + //p->h_original == NULL + if (!(p->h_tid & GCFLAG_OLD)) {//(is_in_nursery(p)) { + // preallocate old "original" outside + // like stealing + gcptr O = stmgc_duplicate_old(L); + L->h_revision = (revision_t)O; + L->h_original = O; + L->h_tid |= GCFLAG_HAS_ID; + + + // could be stolen + if (p->h_tid & GCFLAG_NURSERY_MOVED) { + + } + } + else if (p->h_tid & GCFLAG_NURSERY_MOVED) { + if (p->h_tid & GCFLAG_PUBLIC) { + // moved by stealing + + } + + } + else { + assert(0); + } +} + +revision_t stm_pointer_equal(gcptr p1, gcptr p2) +{ + return stm_id(p1) == stm_id(p2); +} + +/************************************************************/ + static inline gcptr create_old_object_copy(gcptr obj) { assert(!(obj->h_tid & GCFLAG_PUBLIC)); @@ -100,6 +161,13 @@ return fresh_old_copy; } +static inline void copy_to_old_id_copy(gcptr obj, gcptr id) +{ + size_t size = stmcb_size(obj); + memcpy(id, obj, size); + id->h_tid &= ~GCFLAG_HAS_ID; +} + static void visit_if_young(gcptr *root) { gcptr obj = *root; @@ -111,17 +179,25 @@ } else { /* it's a nursery object. Was it already moved? */ - if (UNLIKELY(obj->h_tid & GCFLAG_NURSERY_MOVED)) { /* yes. Such an object can be a public object in the nursery too (such objects are always NURSERY_MOVED). For all cases, - we can just fix the ref. */ + we can just fix the ref. + Can be stolen objects or those we already moved. + */ *root = (gcptr)obj->h_revision; return; } - /* make a copy of it outside */ - fresh_old_copy = create_old_object_copy(obj); + if (obj->h_tid & GCFLAG_HAS_ID) { + /* already has a place to go to */ + fresh_old_copy = copy_to_old_id_copy(obj, obj->h_original); + } + else { + /* make a copy of it outside */ + fresh_old_copy = create_old_object_copy(obj); + } + obj->h_tid |= GCFLAG_NURSERY_MOVED; obj->h_revision = (revision_t)fresh_old_copy; diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -149,10 +149,20 @@ fprintf(stderr, "stolen: %p -> %p\n", P, L); - /* Copy the object out of the other thread's nursery, if needed */ - if (!(L->h_tid & GCFLAG_OLD)) { - gcptr O = stmgc_duplicate_old(L); - L->h_revision = (revision_t)O; + if (!(L->h_tid & GCFLAG_OLD)) { + gcptr O; + if (L->h_tid & GCFLAG_HAS_ID) { + L->h_tid &= ~GCFLAG_HAS_ID; + L->h_revision = (revision_t)L->h_original; + copy_to_old_id_copy(L, L->h_original); + O = L->h_original; + } else { + /* Copy the object out of the other thread's nursery, + if needed */ + O = stmgc_duplicate_old(L); + L->h_revision = (revision_t)O; + L->h_original = O; + } L->h_tid |= GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED; /* subtle: we need to remove L from the fxcache of the target thread, otherwise its read barrier might not trigger on it. diff --git a/c4/stmgc.h b/c4/stmgc.h --- a/c4/stmgc.h +++ b/c4/stmgc.h @@ -10,6 +10,7 @@ typedef struct stm_object_s { revision_t h_tid; revision_t h_revision; + gcptr h_original; } *gcptr; @@ -28,6 +29,14 @@ /* allocate an object out of the local nursery */ gcptr stm_allocate(size_t size, unsigned long tid); +/* returns a never changing hash for the object */ +revision_t stm_hash(gcptr); +/* returns an for the object which is unique during its lifetime */ +revision_t stm_id(gcptr); +/* returns nonzero if the two object-copy pointers belong to the +same original object */ +revision_t stm_pointer_equal(gcptr, gcptr); + /* to push/pop objects into the local shadowstack */ /* (could be turned into macros or something later) */ void stm_push_root(gcptr); _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit