Author: Armin Rigo <[email protected]>
Branch:
Changeset: r291:6a50b88e3e3a
Date: 2013-06-26 19:17 +0200
http://bitbucket.org/pypy/stmgc/changeset/6a50b88e3e3a/
Log: Clean up sweep_pages()
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -1494,7 +1494,6 @@
assert(descriptor_array_free_list >= 0);
assert(pd->stolen_objects.size == 0);
assert(pd->stolen_young_stubs.size == 0);
- pd->shutdown = 0;
/* there may be a thread holding the collection lock
because it steals a stub belonging to the thread
that previously owned this descriptor.
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -156,9 +156,10 @@
/* Allocates an object of the given 'size'. This will never run
a collection: you need to call stmgcpage_possibly_major_collect(0)
when you know you're at a safe point. */
+ struct tx_public_descriptor *gcp = LOCAL_GCPAGES();
+
if (size <= GC_SMALL_REQUEST_THRESHOLD) {
gcptr result;
- struct tx_public_descriptor *gcp = LOCAL_GCPAGES();
int size_class = (size + WORD - 1) / WORD;
assert(0 < size_class && size_class < GC_SMALL_REQUESTS);
@@ -175,6 +176,7 @@
else {
gcptr result = (gcptr)alloc_tracked_memory(size);
dprintf(("stmgcpage_malloc(BIG %zu): %p\n", size, result));
+ g2l_insert(&gcp->nonsmall_objects, result, result);
return result;
}
}
@@ -186,8 +188,9 @@
void stmgcpage_free(gcptr obj)
{
size_t size = stmgc_size(obj);
+ struct tx_public_descriptor *gcp = LOCAL_GCPAGES();
+
if (size <= GC_SMALL_REQUEST_THRESHOLD) {
- struct tx_public_descriptor *gcp = LOCAL_GCPAGES();
int size_class = (size + WORD - 1) / WORD;
assert(0 < size_class && size_class < GC_SMALL_REQUESTS);
@@ -199,7 +202,8 @@
//stm_dbgmem_not_used(obj, size_class * WORD, 0);
}
else {
- stm_free(obj, stmgc_size(obj));
+ g2l_delete_item(&gcp->nonsmall_objects, obj);
+ stm_free(obj, size);
}
}
@@ -475,17 +479,17 @@
/***** Major collections: sweeping *****/
-static void sweep_pages(struct tx_public_descriptor *gcp, int size_class,
- page_header_t *lpage)
+static void sweep_pages(struct tx_public_descriptor *gcp, int size_class)
{
int objs_per_page = nblocks_for_size[size_class];
revision_t obj_size = size_class * WORD;
- gcptr freelist = gcp->free_loc_for_size[size_class];
- page_header_t *lpagenext;
+ gcptr freelist = NULL;
+ page_header_t *lpage, *lpagenext;
+ page_header_t *surviving_pages = NULL;
int j;
gcptr p;
- for (; lpage; lpage = lpagenext) {
+ for (lpage = gcp->pages_for_size[size_class]; lpage; lpage = lpagenext) {
lpagenext = lpage->next_page;
/* sweep 'page': any object with GCFLAG_VISITED stays alive
and the flag is removed; other locations are marked as free. */
@@ -497,8 +501,8 @@
}
if (j < objs_per_page) {
/* the page contains at least one object that stays alive */
- lpage->next_page = gcp->pages_for_size[size_class];
- gcp->pages_for_size[size_class] = lpage;
+ lpage->next_page = surviving_pages;
+ surviving_pages = lpage;
p = (gcptr)(lpage + 1);
for (j = 0; j < objs_per_page; j++) {
if (p->h_tid & GCFLAG_VISITED) {
@@ -541,19 +545,15 @@
count_global_pages--;
}
}
+ gcp->pages_for_size[size_class] = surviving_pages;
gcp->free_loc_for_size[size_class] = freelist;
}
static void free_unused_local_pages(struct tx_public_descriptor *gcp)
{
int i;
- page_header_t *lpage;
-
for (i = 1; i < GC_SMALL_REQUESTS; i++) {
- lpage = gcp->pages_for_size[i];
- gcp->pages_for_size[i] = NULL;
- gcp->free_loc_for_size[i] = NULL;
- sweep_pages(gcp, i, lpage);
+ sweep_pages(gcp, i);
}
}
@@ -568,20 +568,14 @@
static void free_closed_thread_descriptors(void)
{
int i;
- page_header_t *gpage;
struct tx_public_descriptor *gcp;
revision_t index = -1;
while ((gcp = stm_get_free_public_descriptor(&index)) != NULL) {
- if (gcp->shutdown)
- continue;
- for (i = 1; i < GC_SMALL_REQUESTS; i++) {
- gpage = gcp->pages_for_size[i];
- sweep_pages(gcp, i, gpage);
- }
+ free_unused_local_pages(gcp);
+
assert(gcp->collection_lock == 0);
- gcp->shutdown = 1;
assert(gcp->stolen_objects.size == 0);
assert(gcp->stolen_young_stubs.size == 0);
gcptrlist_delete(&gcp->stolen_objects);
diff --git a/c4/gcpage.h b/c4/gcpage.h
--- a/c4/gcpage.h
+++ b/c4/gcpage.h
@@ -62,10 +62,10 @@
/* For statistics */ \
size_t count_pages; \
\
- /* Set to 1 when a major collection shuts down a \
- public_descriptor after the corresponding thread was \
- already finished */ \
- int shutdown;
+ /* A set of all non-small objects (outside the nursery). \
+ We could also have a single global set, but this avoids \
+ locking in stmgcpage_malloc/free. */ \
+ struct G2L nonsmall_objects;
#define LOCAL_GCPAGES() (thread_descriptor->public_descriptor)
diff --git a/c4/lists.c b/c4/lists.c
--- a/c4/lists.c
+++ b/c4/lists.c
@@ -116,6 +116,17 @@
*(char **)p = (char *)wlog;
}
+void g2l_delete_item(struct G2L *g2l, gcptr addr)
+{
+ wlog_t *entry;
+ G2L_FIND(*g2l, addr, entry, goto missing);
+ g2l_mark_as_deleted(entry);
+ return;
+
+ missing:
+ stm_fatalerror("g2l_delete_item: item %p not in dict", addr);
+}
+
/************************************************************/
void gcptrlist_delete(struct GcPtrList *gcptrlist)
diff --git a/c4/lists.h b/c4/lists.h
--- a/c4/lists.h
+++ b/c4/lists.h
@@ -102,6 +102,7 @@
wlog_t *_g2l_find(char *entry, gcptr addr);
void g2l_insert(struct G2L *g2l, gcptr addr, gcptr val);
+void g2l_delete_item(struct G2L *g2l, gcptr addr);
static inline int g2l_contains(struct G2L *g2l, gcptr addr)
{
diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py
--- a/c4/test/test_gcpage.py
+++ b/c4/test/test_gcpage.py
@@ -424,3 +424,17 @@
assert p1b == p1
lib.stm_commit_transaction()
lib.stm_begin_inevitable_transaction()
+
+def test_big_old_object_collect():
+ p1 = oalloc(HDR + 50 * WORD)
+ lib.stm_push_root(p1)
+ major_collect()
+ p1b = lib.stm_pop_root()
+ assert p1b == p1
+ check_not_free(p1)
+ #
+ major_collect()
+ check_free_old(p1)
+ #
+ major_collect()
+ check_free_old(p1)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit