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

Reply via email to