Author: Armin Rigo <[email protected]>
Branch: weakref
Changeset: r396:e0e0b65b0f26
Date: 2013-07-15 16:28 +0200
http://bitbucket.org/pypy/stmgc/changeset/e0e0b65b0f26/
Log: Starting
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -54,6 +54,7 @@
gcptrlist_delete(&d->old_objects_to_trace);
gcptrlist_delete(&d->public_with_young_copy);
+ gcptrlist_delete(&d->young_weakrefs);
}
void stmgc_minor_collect_soon(void)
@@ -100,6 +101,15 @@
return P;
}
+gcptr stm_weakref_allocate(size_t size, unsigned long tid, gcptr obj)
+{
+ gcptr weakref = stm_allocate(size, tid);
+ assert(stmgc_size(weakref) == size);
+ WEAKREF_PTR(weakref, size) = obj;
+ gcptrlist_insert(&thread_descriptor->young_weakrefs, weakref);
+ return weakref;
+}
+
gcptr stmgc_duplicate(gcptr P)
{
size_t size = stmgc_size(P);
@@ -429,6 +439,19 @@
fxcache_clear(&d->recent_reads_cache);
}
+static void move_young_weakrefs(struct tx_descriptor *d)
+{
+ while (gcptrlist_size(&d->young_weakrefs) > 0) {
+ gcptr weakref = gcptrlist_pop(&d->young_weakrefs);
+ if (!(weakref->h_tid & GCFLAG_NURSERY_MOVED))
+ continue; /* the weakref itself dies */
+
+ weakref = (gcptr)weakref->h_revision;
+ size_t size = stmgc_size(weakref);
+ WEAKREF_PTR(weakref, size) = NULL; /* XXX */
+ }
+}
+
static void setup_minor_collect(struct tx_descriptor *d)
{
spinlock_acquire(d->public_descriptor->collection_lock, 'M'); /*minor*/
@@ -440,6 +463,7 @@
{
//assert(gcptrlist_size(&d->old_objects_to_trace) == 0);
assert(gcptrlist_size(&d->public_with_young_copy) == 0);
+ assert(gcptrlist_size(&d->young_weakrefs) == 0);
assert(gcptrlist_size(&d->public_descriptor->stolen_objects) == 0);
spinlock_release(d->public_descriptor->collection_lock);
@@ -475,6 +499,8 @@
surviving young-but-outside-the-nursery objects have been flagged
with GCFLAG_OLD
*/
+ move_young_weakrefs(d);
+
teardown_minor_collect(d);
assert(!stm_has_got_any_lock(d));
@@ -541,6 +567,7 @@
!g2l_any_entry(&d->young_objects_outside_nursery)*/ ) {
/* there is no young object */
assert(gcptrlist_size(&d->public_with_young_copy) == 0);
+ assert(gcptrlist_size(&d->young_weakrefs) == 0);
assert(gcptrlist_size(&d->list_of_read_objects) >=
d->num_read_objects_known_old);
assert(gcptrlist_size(&d->private_from_protected) >=
diff --git a/c4/nursery.h b/c4/nursery.h
--- a/c4/nursery.h
+++ b/c4/nursery.h
@@ -50,7 +50,10 @@
still in the same transaction, to know that the initial \
part of the lists cannot contain young objects any more. */ \
long num_private_from_protected_known_old; \
- long num_read_objects_known_old;
+ long num_read_objects_known_old; \
+ \
+ /* Weakref support */ \
+ struct GcPtrList young_weakrefs;
struct tx_descriptor; /* from et.h */
@@ -65,4 +68,7 @@
void stmgc_trace(gcptr, void visit(gcptr *));
void stmgc_minor_collect_soon(void);
+#define WEAKREF_PTR(wr, sz) (*(gcptr *)(((char *)(wr)) + (sz) - WORD))
+
+
#endif
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -39,10 +39,8 @@
_Bool stm_pointer_equal(gcptr, gcptr);
/* to push/pop objects into the local shadowstack */
-#if 0 // (optimized version below)
-void stm_push_root(gcptr);
-gcptr stm_pop_root(void);
-#endif
+static inline void stm_push_root(gcptr);
+static inline gcptr stm_pop_root(void);
/* initialize/deinitialize the stm framework in the current thread */
void stm_initialize(void);
@@ -55,16 +53,14 @@
void stm_leave_callback_call(int);
/* read/write barriers (the most general versions only for now) */
-#if 0 // (optimized version below)
-gcptr stm_read_barrier(gcptr);
-gcptr stm_write_barrier(gcptr);
-#endif
+static inline gcptr stm_read_barrier(gcptr);
+static inline gcptr stm_write_barrier(gcptr);
/* start a new transaction, calls callback(), and when it returns
finish that transaction. callback() is called with the 'arg'
provided, and with a retry_counter number. Must save roots around
- this call. The callback() is called repeatedly as long as it
- returns a value > 0. */
+ this call. If callback() returns a value > 0, it is called
+ again. */
void stm_perform_transaction(gcptr arg, int (*callback)(gcptr, int));
/* finish the current transaction, start a new one, or turn the current
@@ -114,6 +110,12 @@
void stm_minor_collect(void);
void stm_major_collect(void);
+/* weakref support: allocate a weakref object, and set it to point
+ weakly to 'obj'. The weak pointer offset is hard-coded to be at
+ 'size - WORD'. Important: stmcb_trace() must NOT trace it. */
+gcptr stm_weakref_allocate(size_t size, unsigned long tid, gcptr obj);
+
+
/**************** END OF PUBLIC INTERFACE *****************/
/************************************************************/
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -46,7 +46,7 @@
#define PREBUILT_FLAGS ...
#define PREBUILT_REVISION ...
- gcptr stm_allocate(size_t size, unsigned int tid);
+ gcptr stm_allocate(size_t size, unsigned long tid);
revision_t stm_hash(gcptr);
revision_t stm_id(gcptr);
_Bool stm_pointer_equal(gcptr, gcptr);
@@ -69,6 +69,7 @@
void stm_abort_info_pop(long count);
char *stm_inspect_abort_info(void);
void stm_abort_and_retry(void);
+ gcptr stm_weakref_allocate(size_t size, unsigned long tid, gcptr obj);
/* extra non-public code */
void printfcolor(char *msg);
@@ -164,14 +165,18 @@
gcptr rawgetptr(gcptr obj, long index)
{
- assert(gettid(obj) > 42142 + index);
+ revision_t t = gettid(obj);
+ if (t == 42142) t++;
+ assert(t > 42142 + index);
return ((gcptr *)(obj + 1))[index];
}
void rawsetptr(gcptr obj, long index, gcptr newvalue)
{
fprintf(stderr, "%p->[%ld] = %p\n", obj, index, newvalue);
- assert(gettid(obj) > 42142 + index);
+ revision_t t = gettid(obj);
+ if (t == 42142) t++;
+ assert(t > 42142 + index);
((gcptr *)(obj + 1))[index] = newvalue;
}
@@ -282,6 +287,8 @@
else {
int nrefs = gettid(obj) - 42142;
assert(nrefs < 100);
+ if (nrefs == 0) /* weakrefs */
+ nrefs = 1;
return sizeof(*obj) + nrefs * sizeof(gcptr);
}
}
@@ -484,7 +491,7 @@
def oalloc_refs(nrefs):
"""Allocate an 'old' protected object, outside any nursery,
with nrefs pointers"""
- size = HDR + WORD * nrefs
+ size = HDR + WORD * (nrefs or 1)
p = lib.stmgcpage_malloc(size)
lib.memset(p, 0, size)
p.h_tid = GCFLAG_OLD | GCFLAG_WRITE_BARRIER
@@ -506,9 +513,9 @@
def nalloc_refs(nrefs):
"Allocate a fresh object from the nursery, with nrefs pointers"
- p = lib.stm_allocate(HDR + WORD * nrefs, 42142 + nrefs)
+ p = lib.stm_allocate(HDR + WORD * (nrefs or 1), 42142 + nrefs)
assert p.h_revision == lib.get_private_rev_num()
- for i in range(nrefs):
+ for i in range(nrefs or 1):
assert rawgetptr(p, i) == ffi.NULL # must already be zero-filled
return p
@@ -524,9 +531,9 @@
def palloc_refs(nrefs, prehash=None):
"Get a ``prebuilt'' object with nrefs pointers."
if prehash is None:
- p = lib.pseudoprebuilt(HDR + WORD * nrefs, 42142 + nrefs)
+ p = lib.pseudoprebuilt(HDR + WORD * (nrefs or 1), 42142 + nrefs)
else:
- p = lib.pseudoprebuilt_with_hash(HDR + WORD * nrefs,
+ p = lib.pseudoprebuilt_with_hash(HDR + WORD * (nrefs or 1),
42142 + nrefs, prehash)
return p
@@ -684,5 +691,8 @@
should_break_transaction = lib.stm_should_break_transaction
-
+WEAKREF_SIZE = HDR + WORD
+WEAKREF_TID = 42142
+
+
nrb_protected = ffi.cast("gcptr", -1)
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
@@ -319,3 +319,14 @@
def test_collect_soon():
lib.stmgc_minor_collect_soon()
nalloc(HDR)
+
+def test_weakref_invalidate():
+ p2 = nalloc(HDR)
+ p1 = lib.stm_weakref_allocate(WEAKREF_SIZE, WEAKREF_TID, p2)
+ assert p1.h_tid == WEAKREF_TID # no GC flags
+ 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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit