Author: Remi Meier <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit