Author: Remi Meier <[email protected]>
Branch:
Changeset: r248:78c58b8aabfa
Date: 2013-06-24 09:10 +0200
http://bitbucket.org/pypy/stmgc/changeset/78c58b8aabfa/
Log: add some comments; add hash_mangling
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -88,13 +88,45 @@
}
/************************************************************/
-
+/* Each object has a h_original pointer to an old copy of
+ the same object (e.g. an old revision), the "original".
+ The memory location of this old object is used as the ID
+ for this object. If h_original is NULL *and* it is an
+ old object copy, it itself is the original. This invariant
+ must be upheld by all code dealing with h_original.
+ The original copy must never be moved again. Also, it may
+ be just a stub-object.
+
+ If we want the ID of an object which is still young,
+ we must preallocate an old shadow-original that is used
+ as the target of the young object in a minor collection.
+ In this case, we set the HAS_ID flag on the young obj
+ to notify minor_collect.
+ This flag can be lost if the young obj is stolen. Then
+ the stealing thread uses the shadow-original itself and
+ minor_collect must not overwrite it again.
+ Also, if there is already a backup-copy around, we use
+ this instead of allocating another old object to use as
+ 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
+ alignment (to 4, 8, maybe 16 bytes), so we use the following
+ formula to avoid the trailing bits being always 0.
+ This formula is reversible: two different values of 'i' will
+ always give two different results.
+ */
+ return n ^ (n >> 4);
+}
+
revision_t stm_id(gcptr p)
{
struct tx_descriptor *d = thread_descriptor;
@@ -104,15 +136,23 @@
if (p->h_original) { /* fast path */
fprintf(stderr, "stm_id(%p) has orig fst: %p\n",
p, (gcptr)p->h_original);
- return p->h_original;
+ return mangle_hash(p->h_original);
}
else if (!(p->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
&& (p->h_tid & GCFLAG_OLD)) {
/* we can be sure that p->h_original doesn't
- get set during the if and the else-if */
+ get set during the if and the else-if
+
+ XXX: check for priv_from_protected may not be
+ necessary. only if this func may be called on
+ another thread's young objects that are made
+ old at the same time, and we see the OLD flag
+ before h_original has been set.
+ */
fprintf(stderr, "stm_id(%p) is old, orig=0 fst: %p\n", p, p);
- return (revision_t)p;
+ return mangle_hash((revision_t)p);
}
+
spinlock_acquire(d->public_descriptor->collection_lock, 'I');
/* old objects must have an h_original xOR be
@@ -137,7 +177,6 @@
if (p->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
gcptr B = (gcptr)p->h_revision;
/* don't set, otherwise nursery will copy over backup */
- //p->h_tid |= GCFLAG_HAS_ID; // see AbortPrivateFromProtected
p->h_original = (revision_t)B;
// B->h_tid |= GCFLAG_PUBLIC; done by CommitPrivateFromProtected
@@ -157,7 +196,7 @@
}
spinlock_release(d->public_descriptor->collection_lock);
- return result;
+ return mangle_hash(result);
}
revision_t stm_pointer_equal(gcptr p1, gcptr p2)
diff --git a/c4/steal.c b/c4/steal.c
--- a/c4/steal.c
+++ b/c4/steal.c
@@ -93,7 +93,6 @@
assert(!(L->h_tid & GCFLAG_HAS_ID));
/* original must be L */
B->h_original = (revision_t)L;
- assert(0);
}
else {
/* we can make the backup the "original"
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
@@ -216,12 +216,10 @@
def test_id_private_from_protected():
# read and write from protected
p = oalloc(HDR)
- pid = lib.stm_id(p)
porig = follow_original(p)
# impl detail {
# old objects have id==itself, if not set differently
assert porig == ffi.NULL
- assert ffi.cast("gcptr", pid) == p
# }
p1 = oalloc(HDR)
@@ -237,7 +235,6 @@
assert p2id == lib.stm_id(p2w)
# impl detail {
assert p2w.h_original == 0
- assert follow_revision(p2w).h_original == lib.stm_id(p2w)
# }
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit