Author: Remi Meier
Branch: c7-weakref
Changeset: r979:3040d781125a
Date: 2014-03-12 16:18 +0100
http://bitbucket.org/pypy/stmgc/changeset/3040d781125a/
Log: start adding weakref support
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -180,6 +180,7 @@
}
assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
+ assert(list_is_empty(STM_PSEGMENT->young_weakrefs));
assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery));
assert(tree_is_cleared(STM_PSEGMENT->nursery_objects_shadows));
assert(tree_is_cleared(STM_PSEGMENT->callbacks_on_abort));
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -54,6 +54,11 @@
after the object. */
GCFLAG_HAS_SHADOW = 0x04,
+ /* This flag is set on weakref objects. Weakref objects have a
+ reference to the referenced object at the byte-offset
+ stmcb_size_rounded_up(obj) - sizeof(void*) */
+ GCFLAG_WEAKREF = 0x08,
+
/* All remaining bits of the 32-bit 'stm_flags' field are taken by
the "overflow number". This is a number that identifies the
"overflow objects" from the current transaction among all old
@@ -61,7 +66,7 @@
current transaction that have been flushed out of the nursery,
which occurs if the same transaction allocates too many objects.
*/
- GCFLAG_OVERFLOW_NUMBER_bit0 = 0x08 /* must be last */
+ GCFLAG_OVERFLOW_NUMBER_bit0 = 0x10 /* must be last */
};
@@ -105,6 +110,14 @@
next minor collection. */
struct tree_s *nursery_objects_shadows;
+ /* List of all young weakrefs to check in minor collections. These
+ are the only weakrefs that may point to young objects. */
+ struct list_s *young_weakrefs;
+
+ /* List of all old weakrefs to check in major collections. These
+ weakrefs never point to young objects */
+ struct list_s *old_weakrefs;
+
/* Tree of 'key->callback' associations from stm_call_on_abort() */
struct tree_s *callbacks_on_abort;
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -299,6 +299,9 @@
collect_oldrefs_to_nursery();
+ /* now all surviving nursery objects have been moved out */
+ stm_move_young_weakrefs();
+
throw_away_nursery(get_priv_segment(STM_SEGMENT->segment_num));
assert(MINOR_NOTHING_TO_DO(STM_PSEGMENT));
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -57,6 +57,8 @@
pr->objects_pointing_to_nursery = NULL;
pr->large_overflow_objects = NULL;
pr->modified_old_objects = list_create();
+ pr->young_weakrefs = list_create();
+ pr->old_weakrefs = list_create();
pr->young_outside_nursery = tree_create();
pr->nursery_objects_shadows = tree_create();
pr->callbacks_on_abort = tree_create();
@@ -95,6 +97,8 @@
assert(pr->objects_pointing_to_nursery == NULL);
assert(pr->large_overflow_objects == NULL);
list_free(pr->modified_old_objects);
+ list_free(pr->young_weakrefs);
+ list_free(pr->old_weakrefs);
tree_free(pr->young_outside_nursery);
tree_free(pr->nursery_objects_shadows);
tree_free(pr->callbacks_on_abort);
diff --git a/c7/stm/weakref.c b/c7/stm/weakref.c
new file mode 100644
--- /dev/null
+++ b/c7/stm/weakref.c
@@ -0,0 +1,226 @@
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+
+object_t *stm_allocate_weakref(ssize_t size_rounded_up)
+{
+ OPT_ASSERT(size_rounded_up > sizeof(struct object_s));
+ object_t *obj = stm_allocate(size_rounded_up);
+ obj->stm_flags |= GCFLAG_WEAKREF;
+ LIST_APPEND(STM_PSEGMENT->young_weakrefs, obj);
+ return obj;
+}
+
+
+/***** Minor collection *****/
+
+void stm_move_young_weakrefs()
+{
+ /* The code relies on the fact that no weakref can be an old object
+ weakly pointing to a young object. Indeed, weakrefs are immutable
+ so they cannot point to an object that was created after it.
+ */
+ LIST_FOREACH_R(
+ STM_PSEGMENT->young_weakrefs,
+ object_t * /*item*/,
+ ({
+ if (_is_in_nursery(item)) {
+ object_t *TLPREFIX *pforwarded_array = (object_t *TLPREFIX
*)item;
+
+ /* the following checks are done like in nursery.c: */
+ if (!(item->stm_flags & GCFLAG_HAS_SHADOW)
+ || (pforwarded_array[0] != GCWORD_MOVED)) {
+ /* weakref dies */
+ continue;
+ }
+
+ item = pforwarded_array[1]; /* moved location */
+ }
+ else {
+ /* young outside nursery object */
+ if (tree_contains(STM_PSEGMENT->young_outside_nursery,
+ (uintptr_t)item)) {
+ /* still in the tree -> wasn't seen by the minor
collection,
+ so it doesn't survive */
+ continue;
+ }
+ }
+ assert(!_is_young(item));
+
+ char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, item);
+ ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj);
+ object_t *pointing_to = *WEAKREF_PTR(item, size);
+ assert(pointing_to != NULL);
+
+ if (_is_in_nursery(pointing_to)) {
+ object_t *TLPREFIX *pforwarded_array = (object_t *TLPREFIX
*)pointing_to;
+ /* the following checks are done like in nursery.c: */
+ if (!(pointing_to->stm_flags & GCFLAG_HAS_SHADOW)
+ || (pforwarded_array[0] != GCWORD_MOVED)) {
+ /* pointing_to dies */
+ *WEAKREF_PTR(item, size) = NULL;
+ continue; /* no need to remember in old_weakrefs */
+ }
+ else {
+ /* moved location */
+ *WEAKREF_PTR(item, size) = pforwarded_array[1];
+ }
+ }
+ else {
+ /* young outside nursery object or old object */
+ if (tree_contains(STM_PSEGMENT->young_outside_nursery,
+ (uintptr_t)pointing_to)) {
+ /* still in the tree -> wasn't seen by the minor
collection,
+ so it doesn't survive */
+ *WEAKREF_PTR(item, size) = NULL;
+ continue; /* no need to remember in old_weakrefs */
+ }
+ /* pointing_to was already old */
+ }
+ LIST_APPEND(STM_PSEGMENT->old_weakrefs, item);
+ }));
+ list_clear(STM_PSEGMENT->young_weakrefs);
+}
+
+
+/***** Major collection *****/
+
+/* static _Bool is_partially_visited(gcptr obj) */
+/* { */
+/* /\* Based on gcpage.c:visit_public(). Check the code here if we change
*/
+/* visit_public(). Returns True or False depending on whether we find
any */
+/* version of 'obj' to be MARKED or not. */
+/* *\/ */
+/* assert(IMPLIES(obj->h_tid & GCFLAG_VISITED, */
+/* obj->h_tid & GCFLAG_MARKED)); */
+/* if (obj->h_tid & GCFLAG_MARKED) */
+/* return 1; */
+
+/* /\* if (!(obj->h_tid & GCFLAG_PUBLIC)) *\/ */
+/* /\* return 0; *\/ */
+/* assert(!(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL)); */
+/* if (obj->h_original != 0) { */
+/* gcptr original = (gcptr)obj->h_original; */
+/* assert(IMPLIES(original->h_tid & GCFLAG_VISITED, */
+/* original->h_tid & GCFLAG_MARKED)); */
+/* if (original->h_tid & GCFLAG_MARKED) */
+/* return 1; */
+/* } */
+/* return 0; */
+/* } */
+
+/* static void update_old_weakrefs_list(struct tx_public_descriptor *gcp) */
+/* { */
+/* long i, size = gcp->old_weakrefs.size; */
+/* gcptr *items = gcp->old_weakrefs.items; */
+
+/* for (i = 0; i < size; i++) { */
+/* gcptr weakref = items[i]; */
+
+/* /\* if a weakref moved, update its position in the list *\/ */
+/* if (weakref->h_tid & GCFLAG_MOVED) { */
+/* items[i] = (gcptr)weakref->h_original; */
+/* } */
+/* } */
+/* } */
+
+/* static void visit_old_weakrefs(struct tx_public_descriptor *gcp) */
+/* { */
+/* /\* Note: it's possible that a weakref points to a public stub to a */
+/* protected object, and only the protected object was marked as */
+/* VISITED so far. In this case, this function needs to mark the */
+/* public stub as VISITED too. */
+/* *\/ */
+/* long i, size = gcp->old_weakrefs.size; */
+/* gcptr *items = gcp->old_weakrefs.items; */
+
+/* for (i = 0; i < size; i++) { */
+/* gcptr weakref = items[i]; */
+
+/* if (!(weakref->h_tid & GCFLAG_VISITED)) { */
+/* /\* the weakref itself dies *\/ */
+/* } */
+/* else { */
+/* /\* the weakref belongs to our thread, therefore we should */
+/* always see the most current revision here: *\/ */
+/* assert(weakref->h_revision & 1); */
+
+/* size_t size = stmgc_size(weakref); */
+/* gcptr pointing_to = *WEAKREF_PTR(weakref, size); */
+/* assert(pointing_to != NULL); */
+/* if (is_partially_visited(pointing_to)) { */
+/* pointing_to = stmgcpage_visit(pointing_to); */
+/* dprintf(("mweakref ptr moved %p->%p\n", */
+/* *WEAKREF_PTR(weakref, size), */
+/* pointing_to)); */
+
+/* assert(pointing_to->h_tid & GCFLAG_VISITED); */
+/* *WEAKREF_PTR(weakref, size) = pointing_to; */
+/* } */
+/* else { */
+/* /\* the weakref appears to be pointing to a dying object, */
+/* but we don't know for sure now. Clearing it is left */
+/* to clean_old_weakrefs(). *\/ */
+/* } */
+/* } */
+/* } */
+/* } */
+
+/* static void clean_old_weakrefs(struct tx_public_descriptor *gcp) */
+/* { */
+/* long i, size = gcp->old_weakrefs.size; */
+/* gcptr *items = gcp->old_weakrefs.items; */
+
+/* for (i = size - 1; i >= 0; i--) { */
+/* gcptr weakref = items[i]; */
+/* assert(weakref->h_revision & 1); */
+/* if (weakref->h_tid & GCFLAG_VISITED) { */
+/* size_t size = stmgc_size(weakref); */
+/* gcptr pointing_to = *WEAKREF_PTR(weakref, size); */
+/* if (pointing_to->h_tid & GCFLAG_VISITED) { */
+/* continue; /\* the target stays alive, the weakref remains
*\/ */
+/* } */
+/* dprintf(("mweakref lost ptr %p\n", *WEAKREF_PTR(weakref,
size))); */
+/* *WEAKREF_PTR(weakref, size) = NULL; /\* the target dies *\/ */
+/* } */
+/* /\* remove this weakref from the list *\/ */
+/* items[i] = items[--gcp->old_weakrefs.size]; */
+/* } */
+/* gcptrlist_compress(&gcp->old_weakrefs); */
+/* } */
+
+/* static void for_each_public_descriptor( */
+/* void visit(struct tx_public_descriptor
*)) { */
+/* struct tx_descriptor *d; */
+/* for (d = stm_tx_head; d; d = d->tx_next) */
+/* visit(d->public_descriptor); */
+
+/* struct tx_public_descriptor *gcp; */
+/* revision_t index = -1; */
+/* while ((gcp = stm_get_free_public_descriptor(&index)) != NULL) */
+/* visit(gcp); */
+/* } */
+
+/* void stm_update_old_weakrefs_lists(void) */
+/* { */
+/* /\* go over old weakrefs lists and update the list with possibly */
+/* new pointers because of copy_over_original *\/ */
+/* for_each_public_descriptor(update_old_weakrefs_list); */
+/* } */
+
+
+/* void stm_visit_old_weakrefs(void) */
+/* { */
+/* /\* Figure out which weakrefs survive, which possibly */
+/* adds more objects to 'objects_to_trace'. */
+/* *\/ */
+/* for_each_public_descriptor(visit_old_weakrefs); */
+/* } */
+
+/* void stm_clean_old_weakrefs(void) */
+/* { */
+/* /\* Clean up the non-surviving weakrefs */
+/* *\/ */
+/* for_each_public_descriptor(clean_old_weakrefs); */
+/* } */
diff --git a/c7/stm/weakref.h b/c7/stm/weakref.h
new file mode 100644
--- /dev/null
+++ b/c7/stm/weakref.h
@@ -0,0 +1,13 @@
+#ifndef _SRCSTM_WEAKREF_H
+#define _SRCSTM_WEAKREF_H
+
+
+#define WEAKREF_PTR(wr, sz) ((object_t * TLPREFIX *)(((stm_char *)(wr)) +
(sz) - sizeof(void*)))
+
+void stm_move_young_weakrefs(void);
+/* void stm_update_old_weakrefs_lists(void); */
+/* void stm_visit_old_weakrefs(void); */
+/* void stm_clean_old_weakrefs(void); */
+
+
+#endif
diff --git a/c7/stmgc.c b/c7/stmgc.c
--- a/c7/stmgc.c
+++ b/c7/stmgc.c
@@ -12,6 +12,7 @@
#include "stm/contention.h"
#include "stm/extra.h"
#include "stm/fprintcolor.h"
+#include "stm/weakref.h"
#include "stm/misc.c"
#include "stm/list.c"
@@ -28,3 +29,4 @@
#include "stm/contention.c"
#include "stm/extra.c"
#include "stm/fprintcolor.c"
+#include "stm/weakref.c"
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -194,6 +194,14 @@
return (object_t *)p;
}
+/* Allocate a weakref object. Weakref objects have a
+ reference to the referenced object at the byte-offset
+ stmcb_size_rounded_up(obj) - sizeof(void*)
+ This reference becomes NULL if the referenced object was freed.
+ You must assign the reference before the next collection may happen.
+ After that, they may be considered immutable. */
+object_t *stm_allocate_weakref(ssize_t size_rounded_up);
+
/* stm_setup() needs to be called once at the beginning of the program.
stm_teardown() can be called at the end, but that's not necessary
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -25,6 +25,7 @@
void stm_read(object_t *obj);
/*void stm_write(object_t *obj); use _checked_stm_write() instead */
object_t *stm_allocate(ssize_t size_rounded_up);
+object_t *stm_allocate_weakref(ssize_t size_rounded_up);
object_t *_stm_allocate_old(ssize_t size_rounded_up);
void stm_setup(void);
@@ -54,6 +55,10 @@
void _set_ptr(object_t *obj, int n, object_t *v);
object_t * _get_ptr(object_t *obj, int n);
+void _set_weakref(object_t *obj, object_t *v);
+object_t* _get_weakref(object_t *obj);
+
+
void _stm_start_safe_point(void);
bool _check_stop_safe_point(void);
@@ -163,6 +168,21 @@
}
+#define WEAKREF_PTR(wr, sz) ((object_t * TLPREFIX *)(((stm_char *)(wr)) +
(sz) - sizeof(void*)))
+void _set_weakref(object_t *obj, object_t *v)
+{
+ char *realobj = _stm_real_address(obj);
+ ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj);
+ *WEAKREF_PTR(obj, size) = v;
+}
+
+object_t * _get_weakref(object_t *obj)
+{
+ char *realobj = _stm_real_address(obj);
+ ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj);
+ return *WEAKREF_PTR(obj, size);
+}
+
void _set_ptr(object_t *obj, int n, object_t *v)
{
long nrefs = (long)((myobj_t*)obj)->type_id - 421420;
@@ -266,6 +286,16 @@
lib._set_type_id(o, tid)
return o
+def stm_allocate_weakref(point_to_obj):
+ o = lib.stm_allocate(HDR + WORD)
+ tid = 421420
+ lib._set_type_id(o, tid)
+ lib._set_weakref(o, point_to_obj)
+ return o
+
+def stm_get_weakref(o):
+ return lib._get_weakref(o)
+
def stm_allocate_refs(n):
o = lib.stm_allocate(HDR + n * WORD)
tid = 421420 + n
diff --git a/c7/test/test_weakref.py b/c7/test/test_weakref.py
new file mode 100644
--- /dev/null
+++ b/c7/test/test_weakref.py
@@ -0,0 +1,221 @@
+import py
+from support import *
+
+
+
+
+class TestMinorCollection(BaseTest):
+ def test_simple(self):
+ lib._stm_set_nursery_free_count(2048)
+ self.start_transaction()
+
+ self.push_root_no_gc()
+ lp1 = stm_allocate_weakref(ffi.NULL) # no collection here
+ self.pop_root()
+
+ assert stm_get_weakref(lp1) == ffi.NULL
+
+ self.push_root(lp1)
+ stm_minor_collect()
+ lp1 = self.pop_root()
+
+ assert stm_get_weakref(lp1) == ffi.NULL
+
+ # def test_weakref_invalidate(self):
+ # p2 = nalloc(HDR)
+ # p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+ # assert p1.h_tid == WEAKREF_TID | GCFLAG_IMMUTABLE | GCFLAG_WEAKREF
+ # assert p1.h_revision == lib.get_private_rev_num()
+ # assert lib.rawgetptr(p1, 0) == p2
+ # lib.stm_push_root(p1)
+ # minor_collect()
+ # p1 = lib.stm_pop_root()
+ # assert lib.rawgetptr(p1, 0) == ffi.NULL
+
+ # def test_weakref_itself_dies(self):
+ # p2 = nalloc(HDR)
+ # p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+ # minor_collect()
+
+ # def test_weakref_keep(self):
+ # p2 = nalloc(HDR)
+ # p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+ # assert p1.h_tid == WEAKREF_TID | GCFLAG_IMMUTABLE | GCFLAG_WEAKREF
+ # assert p1.h_revision == lib.get_private_rev_num()
+ # assert lib.rawgetptr(p1, 0) == p2
+ # lib.stm_push_root(p1)
+ # lib.stm_push_root(p2)
+ # minor_collect()
+ # p2 = lib.stm_pop_root()
+ # p1 = lib.stm_pop_root()
+ # assert lib.rawgetptr(p1, 0) == p2
+
+ # def test_weakref_old_keep(self):
+ # p2 = oalloc(HDR)
+ # p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+ # assert p1.h_tid == WEAKREF_TID | GCFLAG_IMMUTABLE | GCFLAG_WEAKREF
+ # assert p1.h_revision == lib.get_private_rev_num()
+ # assert lib.rawgetptr(p1, 0) == p2
+ # lib.stm_push_root(p1)
+ # lib.stm_push_root(p2)
+ # minor_collect()
+ # p2 = lib.stm_pop_root()
+ # p1 = lib.stm_pop_root()
+ # assert lib.rawgetptr(p1, 0) == p2
+
+
+ # def test_old_private_not_keep_alive_weakref(self):
+ # p = palloc(HDR + WORD)
+ # q = palloc_refs(1)
+
+ # def f1(c):
+ # if c == 1:
+ # # currently fails because:
+ # # p1 still in old_objects_to_trace
+ # # -> keeps alive weakp1w
+ # # -> stm_move_young_weakrefs() sees a weakref pointing
+ # # to an aborted object
+ # minor_collect()
+ # return
+
+ # # allocate the "container" as old, private q1
+ # q1 = lib.stm_write_barrier(q)
+ # assert classify(q1) == "private"
+ # lib.stm_push_root(q1)
+ # minor_collect()
+ # q1 = lib.stm_pop_root()
+ # assert classify(q1) == "private"
+ # assert q1.h_tid & GCFLAG_OLD
+ # assert q1.h_tid & GCFLAG_WRITE_BARRIER
+
+ # # allocate young private p1 to point to
+ # p1 = lib.stm_write_barrier(p)
+ # assert ffi.cast("gcptr", p1.h_original) == p
+ # assert classify(p1) == "private"
+ # assert not (p1.h_tid & GCFLAG_OLD)
+
+ # lib.stm_push_root(p1)
+ # lib.stm_push_root(q1)
+ # weakp1w = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p1)
+ # q1 = lib.stm_pop_root()
+ # p1 = lib.stm_pop_root()
+ # # q1 still old, p1 still young, weakp1w also young
+
+ # q1w = lib.stm_write_barrier(q1)
+ # # add q1 to old_objects_to_trace
+ # assert q1 == q1w # was and is private
+ # lib.rawsetptr(q1, 0, weakp1w)
+
+ # abort_and_retry()
+
+ # perform_transaction(f1)
+
+
+
+
+
+
+
+
+
+
+# class TestMajorCollection(BaseTest):
+
+# def test_weakref_old(self):
+# p2 = nalloc(HDR)
+# p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+# #
+# lib.stm_push_root(p1)
+# lib.stm_push_root(p2)
+# major_collect()
+# p2 = lib.stm_pop_root()
+# p1 = lib.stm_pop_root()
+# assert lib.rawgetptr(p1, 0) == p2
+# #
+# lib.stm_push_root(p1)
+# major_collect()
+# p1 = lib.stm_pop_root()
+# assert lib.rawgetptr(p1, 0) == ffi.NULL
+
+# def test_weakref_to_prebuilt(self):
+# p2 = palloc(HDR)
+# p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+# #
+# lib.stm_push_root(p1)
+# major_collect()
+# p1 = lib.stm_pop_root()
+# assert lib.rawgetptr(p1, 0) == p2
+
+# def test_weakref_update_version(self):
+# p2 = oalloc(HDR + WORD); make_public(p2)
+# p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+# #
+# lib.stm_push_root(p1)
+# lib.stm_push_root(p2)
+# major_collect()
+# p2 = lib.stm_pop_root()
+# p1 = lib.stm_pop_root()
+# assert lib.rawgetptr(p1, 0) == p2
+# #
+# lib.stm_commit_transaction()
+# lib.stm_begin_inevitable_transaction()
+# #
+# lib.setlong(p2, 0, 912809218) # write barrier
+# assert lib.rawgetlong(p2, 0) == 0
+# lib.stm_push_root(p1)
+# lib.stm_push_root(p2)
+# major_collect()
+# p2 = lib.stm_pop_root()
+# p1 = lib.stm_pop_root()
+# assert lib.rawgetptr(p1, 0) == p2
+# assert lib.rawgetlong(p2, 0) == 0
+# #
+# lib.stm_commit_transaction()
+# lib.stm_begin_inevitable_transaction()
+# #
+# assert lib.rawgetptr(p1, 0) == p2
+# assert lib.rawgetlong(p2, 0) == 0
+# lib.stm_push_root(p1)
+# lib.stm_push_root(p2)
+# major_collect()
+# p2b = lib.stm_pop_root()
+# p1 = lib.stm_pop_root()
+# assert lib.rawgetptr(p1, 0) == p2
+# assert p2b != p2
+# assert lib.getlong(p2b, 0) == 912809218
+# assert lib.getlong(p2, 0) == 912809218
+
+
+# def test_stealing(self):
+# p = palloc_refs(1)
+# u = palloc_refs(1)
+
+# def f1(r):
+# q = nalloc(HDR+WORD)
+# # lib.stm_push_root(q)
+# w = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, q)
+# # q = lib.stm_pop_root()
+# setptr(p, 0, w)
+# setptr(u, 0, q)
+# minor_collect()
+# lib.stm_commit_transaction()
+# lib.stm_begin_inevitable_transaction()
+# r.set(2)
+# r.wait(3)
+# print "happy"
+
+# def f2(r):
+# r.wait(2)
+# # steal p, should stub the weakref contained in it
+# pr = lib.stm_read_barrier(p)
+# w = rawgetptr(pr, 0)
+# assert classify(w) == "stub"
+
+# # read weakref, should stub out weakptr
+# wr = lib.stm_read_barrier(w)
+# assert wr.h_tid & GCFLAG_WEAKREF
+# assert classify(lib.rawgetptr(wr, 0)) == "stub"
+
+# r.set(3)
+
+# run_parallel(f1, f2)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit