Author: Remi Meier <[email protected]>
Branch:
Changeset: r549:b89b61f0df98
Date: 2013-11-19 17:15 +0100
http://bitbucket.org/pypy/stmgc/changeset/b89b61f0df98/
Log: document the real reason why we can't use just any h_original and
prevent things like stub->stub->stub on public addresses.
diff --git a/c4/doc-objects.txt b/c4/doc-objects.txt
--- a/c4/doc-objects.txt
+++ b/c4/doc-objects.txt
@@ -62,6 +62,7 @@
- prebuilt object, never modified 1
- other public object, never modified GT
- outdated ptr to a more recent public copy
+- stolen protected, made public some PRN
Public stubs (have also a ref to one thread):
- from stealing ptr (maybe to priv/prot) | 2
@@ -353,3 +354,6 @@
it is a predefined HASH value for this object. This is used by
`stm_hash` which otherwise returns a hashed version of the ID of
the object.
+
+DONT ASSUME THE H_ORIGINAL TO BE INITIALIZED. IT MAY HAVE E.G.
+H_REVISION SET TO AN OLD, FREED OBJECT.
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -183,7 +183,8 @@
if (v & 2)
goto follow_stub;
- /* we update P_prev->h_revision as a shortcut */
+ /* we update P_prev->h_revision as a shortcut
+ P_prev->P->v => P_prev->v */
/* XXX check if this really gives a worse performance than only
doing this write occasionally based on a counter in d */
P_prev->h_revision = v;
@@ -576,6 +577,7 @@
B = stmgc_duplicate_old(P);
B->h_tid |= GCFLAG_BACKUP_COPY;
B->h_tid &= ~GCFLAG_HAS_ID;
+
if (!(P->h_original) && (P->h_tid & GCFLAG_OLD)) {
/* if P is old, it must be the original
if P is young, it will create a shadow original later
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -89,21 +89,30 @@
}
assert(obj->h_tid & GCFLAG_OLD);
+ if (stm_is_registered(obj)) {
+ /* prevents stub->stub->stub->... */
+ /* only increment refcount: */
+ stm_register_integer_address((intptr_t)obj);
+ return (intptr_t)obj;
+ }
+
spinlock_acquire(d->public_descriptor->collection_lock, 'P');
/* it must have a h_original */
gcptr orig;
- if (obj->h_original == 0 || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL) {
+ if ((!obj->h_original) || (obj->h_tid & GCFLAG_PREBUILT_ORIGINAL)) {
orig = obj;
} else {
orig = (gcptr)obj->h_original;
}
- if ((orig->h_tid & (GCFLAG_PUBLIC | GCFLAG_PREBUILT_ORIGINAL))
- == (GCFLAG_PUBLIC | GCFLAG_PREBUILT_ORIGINAL)) {
- /* public is not enough as public stubs may get replaced
- by the protected object they point to, if they are in the
- same thread (I think...) */
+ if ((orig->h_tid & GCFLAG_PUBLIC)
+ && (obj->h_tid & GCFLAG_PREBUILT_ORIGINAL)) {
+ /* we can't just use *any* public original because their
+ h_revision is not kept up-to-date during major collections.
+ Meaning it can point to some long gone object.
+ Prebuilt originals, however, always get visited in major
+ collections. */
result = (intptr_t)orig;
}
else {
@@ -233,10 +242,11 @@
/* must create shadow original object XXX: or use
backup, if exists */
gcptr O = (gcptr)stmgcpage_malloc(stmgc_size(p));
- memcpy(O, p, stmgc_size(p)); /* at least major collections
- depend on some content of id_copy.
- remove after fixing that XXX */
+ memcpy(O, p, sizeof(struct stm_object_s));
+
O->h_tid |= GCFLAG_OLD;
+ assert(O->h_original == 0);
+ assert(O->h_revision = -1); /* debugging */
p->h_original = (revision_t)O;
p->h_tid |= GCFLAG_HAS_ID;
@@ -245,6 +255,7 @@
gcptr B = (gcptr)p->h_revision;
/* not stolen already: */
assert(!(B->h_tid & GCFLAG_PUBLIC));
+ assert(!B->h_original);
B->h_original = (revision_t)O;
}
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -37,6 +37,13 @@
}
}
+static void check_consistent(gcptr obj) {
+ if ((obj->h_revision & 3) == 2)
+ assert(stm_pointer_equal(obj, (gcptr)(obj->h_revision-2)));
+ else if ((obj->h_revision & 1) == 0)
+ assert(stm_pointer_equal(obj, (gcptr)(obj->h_revision)));
+}
+
/***** Support code *****/
@@ -217,6 +224,22 @@
/***** registering of small stubs as integer addresses *****/
+_Bool stm_is_registered(gcptr obj)
+{
+ wlog_t *found;
+ _Bool res = 0;
+
+ stmgcpage_acquire_global_lock();
+ /* find and increment refcount; or insert */
+ G2L_FIND(registered_objs, obj, found, goto finish);
+ found->val = (gcptr)(((revision_t)found->val) + 1);
+ goto finish;
+ res = 1;
+ finish:
+ stmgcpage_release_global_lock();
+ return res;
+}
+
void stm_register_integer_address(intptr_t adr)
{ /* needs to be inevitable! */
wlog_t *found;
@@ -253,6 +276,7 @@
/* become inevitable because we would have to re-register them
on abort, but make sure only to re-register if not registered
in the same aborted transaction (XXX) */
+ /* (obj will not move) */
stm_become_inevitable("stm_unregister_integer_address()");
stmgcpage_acquire_global_lock();
@@ -279,6 +303,10 @@
static gcptr copy_over_original(gcptr obj, gcptr id_copy)
{
+ /* no obj->h_revision = obj->h_original = id_copy */
+ assert(!((obj->h_revision <= ((revision_t)id_copy + 2)) &&
+ (obj->h_revision >= ((revision_t)id_copy))));
+
assert(obj != id_copy);
assert(id_copy == (gcptr)obj->h_original);
assert(!(id_copy->h_revision & 1)); /* not head-revision itself */
@@ -540,11 +568,6 @@
== (GCFLAG_MARKED|GCFLAG_VISITED|GCFLAG_PUBLIC));
continue;
}
- /* else if (R->h_original == 0) { */
- /* /\* the obj is an original and will therefore survive: *\/ */
- /* gcptr V = visit_public(R, NULL); */
- /* assert(V == R); */
- /* } */
else {
assert(R->h_tid & GCFLAG_SMALLSTUB); /* only case for now */
/* make sure R stays valid: */
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -186,6 +186,9 @@
/* priv_from_prot's backup->h_originals already point
to id_obj */
+ assert(IMPLIES(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED,
+ ((gcptr)obj->h_revision)->h_original
+ == obj->h_original));
}
else {
/* make a copy of it outside */
diff --git a/c4/steal.c b/c4/steal.c
--- a/c4/steal.c
+++ b/c4/steal.c
@@ -83,6 +83,7 @@
obj->h_original = (revision_t)stub;
stub->h_original = 0; /* stub_malloc does not set to 0... */
if (obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
+ assert(!(((gcptr)obj->h_revision)->h_original));
((gcptr)obj->h_revision)->h_original = (revision_t)stub;
}
}
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -41,7 +41,7 @@
called on the result (push roots!) */
intptr_t stm_allocate_public_integer_address(gcptr);
void stm_unregister_integer_address(intptr_t); /* push roots too! */
-
+_Bool stm_is_registered(gcptr);
/* returns a never changing hash for the object */
revision_t stm_hash(gcptr);
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit