[pypy-commit] stmgc default: in-the-middle-of-progress
arigo
noreply at buildbot.pypy.org
Fri Jun 14 18:45:02 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r128:9cfc156e53f7
Date: 2013-06-14 18:44 +0200
http://bitbucket.org/pypy/stmgc/changeset/9cfc156e53f7/
Log: in-the-middle-of-progress
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -33,7 +33,7 @@
static int is_private(gcptr P)
{
return (P->h_revision == stm_private_rev_num) ||
- (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+ gcflag_private_from_protected(P);
}
int _stm_is_private(gcptr P)
{
@@ -80,7 +80,7 @@
revision_t v;
restart_all:
- if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
+ if (gcflag_private_from_protected(P))
{
assert(!(P->h_revision & 1)); /* pointer to the backup copy */
@@ -95,14 +95,14 @@
/* else, for the rest of this function, we can assume that P was not
a private copy */
- if (P->h_tid & GCFLAG_PUBLIC)
+ if (gcflag_public(P))
{
/* follow the chained list of h_revision's as long as they are
regular pointers. We will only find more public objects
along this chain.
*/
restart_all_public:
- assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(P));
v = ACCESS_ONCE(P->h_revision);
if (!(v & 1)) // "is a pointer", i.e.
{ // "has a more recent revision"
@@ -112,7 +112,7 @@
gcptr P_prev = P;
P = (gcptr)v;
- assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(P));
v = ACCESS_ONCE(P->h_revision);
@@ -145,7 +145,7 @@
because *we* have an entry in d->public_to_private. (It might
also be someone else.)
*/
- if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
+ if (gcflag_public_to_private(P))
{
wlog_t *item;
retry_public_to_private:;
@@ -154,7 +154,7 @@
/* We have a key in 'public_to_private'. The value is the
corresponding private object. */
P = item->val;
- assert(!(P->h_tid & GCFLAG_PUBLIC));
+ assert(!gcflag_public(P));
assert(is_private(P));
fprintf(stderr, "read_barrier: %p -> %p public_to_private\n", G, P);
return P;
@@ -229,7 +229,7 @@
fprintf(stderr, "read_barrier: %p -> stealing %p...\n ", G, P);
stm_steal_stub(P);
- assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(P));
goto restart_all_public;
}
}
@@ -245,8 +245,8 @@
if (pubobj == P || ((P->h_revision & 3) == 2 &&
pubobj->h_revision == P->h_revision))
{
- assert(!(org_pubobj->h_tid & GCFLAG_STUB));
- assert(!(privobj->h_tid & GCFLAG_PUBLIC));
+ assert(!gcflag_stub(org_pubobj));
+ assert(!gcflag_public(privobj));
assert(is_private(privobj));
if (P != org_pubobj)
fprintf(stderr, "| actually %p ", org_pubobj);
@@ -299,7 +299,7 @@
return P;
}
- if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
+ if (gcflag_private_from_protected(P))
{
/* private too, with a backup copy */
assert(!(P->h_revision & 1));
@@ -307,7 +307,7 @@
return P;
}
- if (P->h_tid & GCFLAG_PUBLIC)
+ if (gcflag_public(P))
{
fprintf(stderr, "public ");
@@ -323,7 +323,7 @@
}
P = (gcptr)v;
- assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(P));
fprintf(stderr, "-> %p public ", P);
}
@@ -354,12 +354,12 @@
{
P = (gcptr)(v - 2);
fprintf(stderr, "-foreign-> %p ", P);
- if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
+ if (gcflag_private_from_protected(P))
{
P = (gcptr)P->h_revision; /* the backup copy */
fprintf(stderr, "-backup-> %p ", P);
}
- if (!(P->h_tid & GCFLAG_PUBLIC))
+ if (!gcflag_public(P))
{
fprintf(stderr, "protected by someone else!\n");
return (gcptr)-1;
@@ -397,10 +397,10 @@
assert(P->h_revision != stm_private_rev_num);
assert(P->h_revision & 1);
- assert(!(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
- assert(!(P->h_tid & GCFLAG_BACKUP_COPY));
- assert(!(P->h_tid & GCFLAG_STUB));
- assert(!(P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
+ assert(!gcflag_public_to_private(P));
+ assert(!gcflag_backup_copy(P));
+ assert(!gcflag_stub(P));
+ assert(!gcflag_private_from_protected(P));
B = stmgc_duplicate(P);
B->h_tid |= GCFLAG_BACKUP_COPY;
@@ -410,12 +410,12 @@
gcptrlist_insert(&d->private_from_protected, P);
- return P;
+ return P; /* always returns its arg: the object is converted in-place */
}
static gcptr LocalizePublic(struct tx_descriptor *d, gcptr R)
{
- assert(R->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(R));
#ifdef _GC_DEBUG
wlog_t *entry;
@@ -427,9 +427,9 @@
R->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
gcptr L = stmgc_duplicate(R);
- assert(!(L->h_tid & GCFLAG_BACKUP_COPY));
- assert(!(L->h_tid & GCFLAG_STUB));
- assert(!(L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
+ assert(!gcflag_backup_copy(L));
+ assert(!gcflag_stub(L));
+ assert(!gcflag_private_from_protected(L));
L->h_tid &= ~(GCFLAG_OLD |
GCFLAG_VISITED |
GCFLAG_PUBLIC |
@@ -439,7 +439,6 @@
0);
L->h_revision = stm_private_rev_num;
g2l_insert(&d->public_to_private, R, L);
- gcptrlist_insert(&d->public_to_young, R);
fprintf(stderr, "write_barrier: adding %p -> %p to public_to_private\n",
R, L);
@@ -450,38 +449,64 @@
return L;
}
-static inline gcptr check_flag_write_barrier(gcptr W)
+static inline void record_write_barrier(gcptr P)
{
- if (W->h_tid & GCFLAG_WRITE_BARRIER)
+ if (gcflag_write_barrier(P))
{
- struct tx_descriptor *d = thread_descriptor;
- gcptrlist_insert(&d->private_old_pointing_to_young, W);
- W->h_tid &= ~GCFLAG_WRITE_BARRIER;
+ P->h_tid &= ~GCFLAG_WRITE_BARRIER;
+ gcptrlist_insert(&thread_descriptor->old_with_young_pointers_inside, P);
}
- return W;
}
gcptr stm_WriteBarrier(gcptr P)
{
- if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
- return check_flag_write_barrier(P);
+ if (is_private(P))
+ {
+ /* If we have GCFLAG_WRITE_BARRIER in P, then list it into
+ old_with_young_pointers_inside: it's a private object that may
+ be modified by the program after we return, and the mutation
+ may be to write young pointers (in fact it's a common case).
+ */
+ record_write_barrier(P);
+ return P;
+ }
gcptr R, W;
R = stm_read_barrier(P);
+
if (is_private(R))
- return check_flag_write_barrier(R);
+ {
+ record_write_barrier(P);
+ return P;
+ }
struct tx_descriptor *d = thread_descriptor;
assert(d->active >= 1);
+ /* We need the collection_lock for the sequel; this is required notably
+ because we're about to edit flags on a protected object.
+ */
spinlock_acquire(d->public_descriptor->collection_lock, 'L');
if (d->public_descriptor->stolen_objects.size != 0)
stm_normalize_stolen_objects(d);
- if (R->h_tid & GCFLAG_PUBLIC)
- W = LocalizePublic(d, R);
+ if (gcflag_public(R))
+ {
+ /* Make and return a new (young) private copy of the public R.
+ Add R into the list 'old_public_with_young_copy'.
+ */
+ assert(gcflag_old(R));
+ gcptrlist_insert(&d->old_public_with_young_copy, R);
+ W = LocalizePublic(d, R);
+ }
else
- W = LocalizeProtected(d, R);
+ {
+ /* Turn the protected copy in-place into a private copy. If it's
+ an old object that still has GCFLAG_WRITE_BARRIER, then we must
+ also record it in the list 'old_with_young_pointers_inside'. */
+ W = LocalizeProtected(d, R);
+ record_write_barrier(W);
+ }
spinlock_release(d->public_descriptor->collection_lock);
@@ -528,7 +553,7 @@
v = ACCESS_ONCE(R->h_revision);
if (!(v & 1)) // "is a pointer", i.e.
{ // "has a more recent revision"
- if (R->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
+ if (gcflag_private_from_protected(R))
{
/* such an object R might be listed in list_of_read_objects
before it was turned from protected to private */
@@ -786,7 +811,7 @@
gcptr R = item->addr;
revision_t v;
retry:
- assert(R->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(R));
v = ACCESS_ONCE(R->h_revision);
if (!(v & 1)) // "is a pointer", i.e.
{ // "has a more recent revision"
@@ -806,7 +831,7 @@
goto retry;
gcptr L = item->val;
- assert(L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED ?
+ assert(gcflag_private_from_protected(L) ?
L->h_revision == (revision_t)R :
L->h_revision == stm_private_rev_num);
assert(v != stm_private_rev_num);
@@ -830,7 +855,7 @@
gcptr L = item->val;
revision_t expected, v = L->h_revision;
- if (L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
+ if (gcflag_private_from_protected(L))
expected = (revision_t)R;
else
expected = stm_private_rev_num;
@@ -867,10 +892,10 @@
G2L_LOOP_FORWARD(d->public_to_private, item)
{
gcptr L = item->val;
- assert(!(L->h_tid & GCFLAG_VISITED));
- assert(!(L->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
- assert(!(L->h_tid & GCFLAG_PREBUILT_ORIGINAL));
- assert(!(L->h_tid & GCFLAG_NURSERY_MOVED));
+ assert(!gcflag_visited(L));
+ assert(!gcflag_public_to_private(L));
+ assert(!gcflag_prebuilt_original(L));
+ assert(!gcflag_nursery_moved(L));
assert(L->h_revision != localrev); /* modified by AcquireLocks() */
#ifdef DUMP_EXTRA
@@ -894,9 +919,9 @@
gcptr R = item->addr;
revision_t v = (revision_t)item->val;
- assert(R->h_tid & GCFLAG_PUBLIC);
- assert(R->h_tid & GCFLAG_PUBLIC_TO_PRIVATE);
- assert(!(R->h_tid & GCFLAG_NURSERY_MOVED));
+ assert(gcflag_public(R));
+ assert(gcflag_public_to_private(R));
+ assert(!gcflag_nursery_moved(R));
assert(R->h_revision != localrev);
#ifdef DUMP_EXTRA
@@ -907,7 +932,7 @@
ACCESS_ONCE(R->h_revision) = v;
#if 0
- if (R->h_tid & GCFLAG_PREBUILT_ORIGINAL)
+ if (gcflag_prebuilt_original(R))
{
/* cannot possibly get here more than once for a given value of R */
pthread_mutex_lock(&mutex_prebuilt_gcroots);
@@ -932,7 +957,7 @@
for (i = 0; i < size; i++)
{
gcptr P = items[i];
- assert(P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+ assert(gcflag_private_from_protected(P));
P->h_tid &= ~GCFLAG_PRIVATE_FROM_PROTECTED;
if (P->h_revision & 1) // "is not a pointer"
@@ -947,7 +972,7 @@
gcptr B = (gcptr)P->h_revision;
P->h_revision = new_revision;
- if (B->h_tid & GCFLAG_PUBLIC)
+ if (gcflag_public(B))
{
/* B was stolen */
while (1)
@@ -976,20 +1001,20 @@
for (i = 0; i < size; i++)
{
gcptr P = items[i];
- assert(P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+ assert(gcflag_private_from_protected(P));
assert(!(P->h_revision & 1)); // "is a pointer"
gcptr B = (gcptr)P->h_revision;
- if (B->h_tid & GCFLAG_PUBLIC)
+ if (gcflag_public(B))
{
- assert(!(B->h_tid & GCFLAG_BACKUP_COPY));
+ assert(!gcflag_backup_copy(B));
P->h_tid &= ~GCFLAG_PRIVATE_FROM_PROTECTED;
P->h_tid |= GCFLAG_PUBLIC;
/* P becomes a public outdated object */
}
else
{
- assert(B->h_tid & GCFLAG_BACKUP_COPY);
+ assert(gcflag_backup_copy(B));
memcpy(P, B, stmcb_size(P));
P->h_tid &= ~GCFLAG_BACKUP_COPY;
}
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -39,11 +39,12 @@
* GCFLAG_PREBUILT_ORIGINAL is only set on the original version of
* prebuilt objects.
*
- * GCFLAG_WRITE_BARRIER is set on *old* objects to track old-to- young
- * pointers. It may be left set on *public* objects but is ignored
- * there, because public objects are read-only. The flag is removed
- * once a write occurs and the object is recorded in the list
- * 'old_pointing_to_young'; it is set again at the next minor
+ * GCFLAG_WRITE_BARRIER is set on *old* objects to track old-to-young
+ * pointers. It is only useful on private objects, and on protected
+ * objects (which may be turned private again). It may be left set on
+ * public objects but is ignored there, because such objects are read-only.
+ * The flag is removed once a write occurs and the object is recorded in
+ * the list 'old_pointing_to_young'; it is set again at the next minor
* collection.
*
* GCFLAG_NURSERY_MOVED is used temporarily during minor collections.
@@ -82,6 +83,20 @@
"PRIVATE_FROM_PROTECTED", \
NULL }
+#define _DECLARE_FLAG(funcname, flagname) \
+ static inline _Bool funcname(gcptr P) { \
+ return (P->h_tid & flagname) != 0; }
+_DECLARE_FLAG(gcflag_old, GCFLAG_OLD)
+_DECLARE_FLAG(gcflag_visited, GCFLAG_VISITED)
+_DECLARE_FLAG(gcflag_public, GCFLAG_PUBLIC)
+_DECLARE_FLAG(gcflag_prebuilt_original, GCFLAG_PREBUILT_ORIGINAL)
+_DECLARE_FLAG(gcflag_public_to_private, GCFLAG_PUBLIC_TO_PRIVATE)
+_DECLARE_FLAG(gcflag_write_barrier, GCFLAG_WRITE_BARRIER)
+_DECLARE_FLAG(gcflag_nursery_moved, GCFLAG_NURSERY_MOVED)
+_DECLARE_FLAG(gcflag_backup_copy, GCFLAG_BACKUP_COPY)
+_DECLARE_FLAG(gcflag_stub, GCFLAG_STUB)
+_DECLARE_FLAG(gcflag_private_from_protected, GCFLAG_PRIVATE_FROM_PROTECTED)
+
/************************************************************/
#define ABRT_MANUAL 0
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -67,11 +67,11 @@
static inline gcptr create_old_object_copy(gcptr obj)
{
- assert(!(obj->h_tid & GCFLAG_NURSERY_MOVED));
- assert(!(obj->h_tid & GCFLAG_VISITED));
- assert(!(obj->h_tid & GCFLAG_WRITE_BARRIER));
- assert(!(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
- assert(!(obj->h_tid & GCFLAG_OLD));
+ assert(!gcflag_nursery_moved(obj));
+ assert(!gcflag_visited(obj));
+ assert(!gcflag_write_barrier(obj));
+ assert(!gcflag_prebuilt_original(obj));
+ assert(!gcflag_old(obj));
size_t size = stmcb_size(obj);
gcptr fresh_old_copy = stm_malloc(size);
@@ -134,7 +134,7 @@
for (i = 0; i < size; i++) {
gcptr P = items[i];
- assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(P));
revision_t v = ACCESS_ONCE(P->h_revision);
wlog_t *item;
@@ -145,11 +145,14 @@
We are in a case where we know the transaction will not
be able to commit successfully.
*/
+ fprintf(stderr, "public_to_young: %p was modified! abort!\n", P);
abort();
AbortTransactionAfterCollect(d, ABRT_COLLECT_MINOR);
//...
}
+ fprintf(stderr, "public_to_young: %p -> %p in public_to_private\n",
+ item->addr, item->val);
visit_if_young(&item->val);
continue;
@@ -159,6 +162,7 @@
It must come from an older transaction that aborted.
Nothing to do now.
*/
+ fprintf(stderr, "public_to_young: %p ignored\n", P);
continue;
}
@@ -170,6 +174,8 @@
in the past, but someone made even more changes.
Nothing to do now.
*/
+ fprintf(stderr, "public_to_young: %p -> %p not a stub, ignored\n",
+ P, S);
continue;
}
@@ -177,6 +183,8 @@
/* Bah, it's indeed a stub but for another thread. Nothing
to do now.
*/
+ fprintf(stderr, "public_to_young: %p -> %p stub wrong thread, "
+ "ignored\n", P, S);
continue;
}
@@ -184,6 +192,9 @@
feet because we hold our own collection_lock.
*/
gcptr L = (gcptr)(w - 2);
+ fprintf(stderr, "public_to_young: %p -> %p stub -> %p\n",
+ P, S, L);
+
visit_if_young(&L);
S->h_revision = ((revision_t)L) | 2;
}
@@ -203,8 +214,8 @@
while (gcptrlist_size(&d->old_objects_to_trace) > 0) {
gcptr obj = gcptrlist_pop(&d->old_objects_to_trace);
- assert(obj->h_tid & GCFLAG_OLD);
- assert(!(obj->h_tid & GCFLAG_WRITE_BARRIER));
+ assert(gcflag_old(obj));
+ assert(!gcflag_write_barrier(obj));
obj->h_tid |= GCFLAG_WRITE_BARRIER;
stmcb_trace(obj, &visit_if_young);
diff --git a/c4/nursery.h b/c4/nursery.h
--- a/c4/nursery.h
+++ b/c4/nursery.h
@@ -11,8 +11,8 @@
char *nursery_end; \
char *nursery_base; \
struct GcPtrList old_objects_to_trace; \
- struct GcPtrList public_to_young; \
- struct GcPtrList private_old_pointing_to_young;
+ struct GcPtrList old_public_with_young_copy; \
+ struct GcPtrList old_with_young_pointers_inside;
struct tx_descriptor; /* from et.h */
diff --git a/c4/steal.c b/c4/steal.c
--- a/c4/steal.c
+++ b/c4/steal.c
@@ -55,7 +55,7 @@
static void replace_ptr_to_protected_with_stub(gcptr *pobj)
{
gcptr stub, obj = *pobj;
- if (obj == NULL || (obj->h_tid & GCFLAG_PUBLIC) != 0)
+ if (obj == NULL || gcflag_public(obj))
return;
/* we use 'all_stubs', a dictionary, in order to try to avoid
@@ -98,7 +98,7 @@
/* L might be a private_from_protected, or just a protected copy.
To know which case it is, read GCFLAG_PRIVATE_FROM_PROTECTED.
*/
- if (L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
+ if (gcflag_private_from_protected(L)) {
gcptr B = (gcptr)L->h_revision; /* the backup copy */
/* B is now a backup copy, i.e. a protected object, and we own
@@ -107,9 +107,9 @@
*/
B->h_tid &= ~GCFLAG_BACKUP_COPY;
- if (B->h_tid & GCFLAG_PUBLIC_TO_PRIVATE) {
+ if (gcflag_public_to_private(B)) {
/* already stolen */
- assert(B->h_tid & GCFLAG_PUBLIC);
+ assert(gcflag_public(B));
fprintf(stderr, "already stolen: %p -> %p <-> %p\n", P, L, B);
L = B;
goto already_stolen;
@@ -125,7 +125,7 @@
}
}
else {
- if (L->h_tid & GCFLAG_PUBLIC) {
+ if (gcflag_public(L)) {
/* already stolen */
fprintf(stderr, "already stolen: %p -> %p\n", P, L);
goto already_stolen;
@@ -139,7 +139,7 @@
thread's collection_lock, so we can read/write the flags. Change
it from protected to public.
*/
- assert(!(L->h_tid & GCFLAG_PUBLIC));
+ assert(!gcflag_public(L));
L->h_tid |= GCFLAG_PUBLIC;
/* Note that all protected or backup copies have a h_revision that
@@ -192,8 +192,8 @@
gcptr B = items[i];
gcptr L = items[i + 1];
- assert(L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
- assert(!(B->h_tid & GCFLAG_BACKUP_COPY)); /* already removed */
+ assert(gcflag_private_from_protected(L));
+ assert(!gcflag_backup_copy(B)); /* already removed */
g2l_insert(&d->public_to_private, B, L);
@@ -218,7 +218,7 @@
gcptr B = items[i];
gcptr L = items[i + 1];
- assert(L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+ assert(gcflag_private_from_protected(L));
if (B == obj)
return L;
}
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -391,18 +391,19 @@
# ____________________________________________________________
def oalloc(size):
- "Allocate an 'old' public object, outside any nursery"
+ "Allocate an 'old' protected object, outside any nursery"
p = ffi.cast("gcptr", lib.stm_malloc(size))
- p.h_tid = GCFLAG_OLD | GCFLAG_PUBLIC
- p.h_revision = 1
+ p.h_tid = GCFLAG_OLD | GCFLAG_WRITE_BARRIER
+ p.h_revision = -sys.maxint
lib.settid(p, 42 + size)
return p
def oalloc_refs(nrefs):
- "Allocate an 'old' public object, outside any nursery, with nrefs pointers"
+ """Allocate an 'old' protected object, outside any nursery,
+ with nrefs pointers"""
p = ffi.cast("gcptr", lib.stm_malloc(HDR + WORD * nrefs))
- p.h_tid = GCFLAG_OLD | GCFLAG_PUBLIC
- p.h_revision = 1
+ p.h_tid = GCFLAG_OLD | GCFLAG_WRITE_BARRIER
+ p.h_revision = -sys.maxint
lib.settid(p, 421 + nrefs)
for i in range(nrefs):
rawsetptr(p, i, ffi.NULL)
diff --git a/c4/test/test_nursery.py b/c4/test/test_nursery.py
--- a/c4/test/test_nursery.py
+++ b/c4/test/test_nursery.py
@@ -126,7 +126,7 @@
check_not_free(p2b)
def test_minor_collection_at_thread_end():
- p1 = oalloc_refs(1)
+ p1 = palloc_refs(1)
p2 = nalloc(HDR)
setptr(p1, 0, p2)
lib.stm_finalize()
@@ -156,3 +156,31 @@
check_prebuilt(p0)
p2 = lib.getptr(p0, 0)
check_not_free(p2)
+
+def test_old_protected_stay_alive():
+ p0 = oalloc(HDR + WORD)
+ assert classify(p0) == "protected"
+ lib.rawsetlong(p0, 0, 81211)
+ lib.stm_push_root(p0)
+ minor_collect()
+ p0b = lib.stm_pop_root()
+ assert p0b == p0
+ assert classify(p0) == "protected"
+ assert lib.rawgetlong(p0, 0) == 81211
+
+def test_old_private_from_protected_to_young_private():
+ p0 = oalloc_refs(1)
+ assert classify(p0) == "protected"
+ p1 = nalloc(HDR)
+ lib.setptr(p0, 0, p1)
+ assert classify(p0) == "private" # private_from_protected
+ lib.stm_push_root(p0)
+ minor_collect()
+ p0b = lib.stm_pop_root()
+ assert p0b == p0
+ check_nursery_free(p1)
+ assert classify(p0) == "private" # private_from_protected
+ p2 = lib.getptr(p0, 0)
+ assert not lib.in_nursery(p2)
+ check_not_free(p2)
+ assert classify(p2) == "private"
More information about the pypy-commit
mailing list