[pypy-commit] stmgc default: Fix the two previous tests.
arigo
noreply at buildbot.pypy.org
Sun May 26 18:56:52 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r22:1dd1331ec33e
Date: 2013-05-26 18:56 +0200
http://bitbucket.org/pypy/stmgc/changeset/1dd1331ec33e/
Log: Fix the two previous tests.
diff --git a/c3/lists.c b/c3/lists.c
--- a/c3/lists.c
+++ b/c3/lists.c
@@ -22,6 +22,19 @@
memset(g2l, 0, sizeof(struct G2L));
}
+struct G2L *g2l_malloc(void)
+{
+ struct G2L *g2l = malloc(sizeof(struct G2L));
+ memset(g2l, 0, sizeof(struct G2L));
+ return g2l;
+}
+
+void g2l_free(struct G2L *g2l)
+{
+ free(g2l->raw_start);
+ free(g2l);
+}
+
wlog_t *_g2l_find(char *entry, gcptr addr)
{
revision_t key = (revision_t)addr;
@@ -172,6 +185,16 @@
gcptrlist->size = i + 3;
}
+void gcptrlist_insert_at_index(struct GcPtrList *gcptrlist, long index,
+ gcptr newitem)
+{
+ long lastitem = gcptrlist->size;
+ assert(index <= lastitem);
+ gcptrlist_insert(gcptrlist, NULL);
+ gcptrlist->items[lastitem] = gcptrlist->items[index];
+ gcptrlist->items[index] = newitem;
+}
+
void gcptrlist_merge(struct GcPtrList *gcptrlist,
struct GcPtrList *gcptrlist_source)
{
diff --git a/c3/lists.h b/c3/lists.h
--- a/c3/lists.h
+++ b/c3/lists.h
@@ -35,6 +35,8 @@
void g2l_clear(struct G2L *g2l);
void g2l_delete(struct G2L *g2l);
+struct G2L *g2l_malloc(void);
+void g2l_free(struct G2L *g2l);
static inline int g2l_any_entry(struct G2L *g2l) {
return g2l->raw_current != g2l->raw_start;
@@ -133,14 +135,20 @@
void gcptrlist_insert3(struct GcPtrList *gcptrlist, gcptr newitem1,
gcptr newitem2, gcptr newitem3);
-static inline void gcptrlist_insert(struct GcPtrList *gcptrlist, gcptr newitem) {
+/* items[size++] = items[index]; items[index] = newitem; */
+void gcptrlist_insert_at_index(struct GcPtrList *gcptrlist, long index,
+ gcptr newitem);
+
+static inline void gcptrlist_insert(struct GcPtrList *gcptrlist, gcptr newitem)
+{
if (UNLIKELY(gcptrlist->size == gcptrlist->alloc))
_gcptrlist_grow(gcptrlist);
gcptrlist->items[gcptrlist->size++] = newitem;
}
-static inline void gcptrlist_reduce_size(struct GcPtrList *gcptrlist, long newsize) {
- gcptrlist->size = newsize;
+static inline void gcptrlist_reduce_size(struct GcPtrList *gcptrlist, long nsz)
+{
+ gcptrlist->size = nsz;
}
static inline long gcptrlist_size(struct GcPtrList *gcptrlist)
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -661,19 +661,54 @@
spinlock_release(d->collection_lock);
}
+static __thread struct G2L *yo_stubs; /* { protected: public_stub } */
+
static void create_yo_stubs(gcptr *pobj)
{
- gcptr obj = *pobj;
+ gcptr stub, obj = *pobj;
if (obj == NULL || (obj->h_tid & GCFLAG_OLD) != 0)
return;
- /* xxx try to avoid duplicate stubs for the same object */
- gcptr stub = stmgcpage_malloc(sizeof(*stub));
+ /* we use 'yo_stubs', a dictionary, in order to try to avoid
+ duplicate stubs for the same object */
+ if (yo_stubs == NULL) {
+ yo_stubs = g2l_malloc();
+ }
+ else {
+ wlog_t *item;
+ G2L_FIND(*yo_stubs, obj, item, goto not_found);
+ /* found already */
+ stub = item->val;
+ assert(stub->h_revision == (((revision_t)obj) | 2));
+ *pobj = stub;
+ return;
+ }
+
+ not_found:
+ stub = stmgcpage_malloc(sizeof(*stub));
stub->h_tid = GCFLAG_OLD | GCFLAG_STUB; /* with type_id == 0 */
stub->h_revision = ((revision_t)obj) | 2;
+ g2l_insert(yo_stubs, obj, stub);
*pobj = stub;
}
+static long done_creating_yo_stubs(struct GcPtrList *add_to_list, long index)
+{
+ wlog_t *item;
+ struct G2L *stubs = yo_stubs;
+ if (stubs == NULL)
+ return index;
+
+ G2L_LOOP_FORWARD(*stubs, item) {
+ gcptrlist_insert_at_index(add_to_list, index, item->val);
+ index++;
+ } G2L_LOOP_END;
+
+ g2l_free(stubs);
+ yo_stubs = NULL;
+ return index;
+}
+
static void fix_new_public_to_protected_references(struct tx_descriptor *d)
{
long i, size = d->private_old_pointing_to_young.size;
@@ -683,6 +718,8 @@
stmcb_trace(items[i], &create_yo_stubs);
}
gcptrlist_clear(&d->private_old_pointing_to_young);
+ d->num_public_to_protected = done_creating_yo_stubs(
+ &d->public_to_young, d->num_public_to_protected);
}
static void free_unvisited_young_objects_outside_nursery(
@@ -900,12 +937,20 @@
/* R is now the protected object to move outside, with revision v. */
N = create_old_object_copy(R _REASON("**stolen copy"));
N->h_revision = v;
- gcptrlist_insert2(&source_d->stolen_objects, R, N);
+ gcptrlist_insert3(&source_d->stolen_objects, R, N, NULL);
/* there might be references in N going to protected objects. We
must fix them with stubs. */
stmcb_trace(N, &create_yo_stubs);
+ /* Cannot insert them here into the 'public_to_young' list, because
+ it might be accessed concurrently by the thread 'source_d'.
+ Instead we put them into stolen_objects. They are inserted
+ at position 'size - 1', which means just before the final NULL
+ that was already pushed by the above gcptrlist_insert3(). */
+ done_creating_yo_stubs(&source_d->stolen_objects,
+ source_d->stolen_objects.size - 1);
+
return N;
}
@@ -980,7 +1025,7 @@
gcptr *items = d->stolen_objects.items;
assert(d == thread_descriptor);
- for (i = 0; i < size; i += 2) {
+ for (i = 0; i < size; ) {
gcptr R = items[i];
gcptr N = items[i + 1];
@@ -1007,6 +1052,17 @@
gcptrlist_insert(&d->public_to_young, N);
}
recdump1("STOLEN", R);
+
+ /* then all items from i+2 up to the first NULL are new stubs
+ that must be added to d->public_to_young, in the first part
+ (i.e. before d->num_public_to_protected) */
+ i += 2;
+ long ptp = d->num_public_to_protected;
+ while ((N = items[i++]) != NULL) {
+ gcptrlist_insert_at_index(&d->public_to_young, ptp, N);
+ ptp++;
+ }
+ d->num_public_to_protected = ptp;
}
gcptrlist_clear(&d->stolen_objects);
}
More information about the pypy-commit
mailing list