Author: Armin Rigo <[email protected]>
Branch: finalizer
Changeset: r1471:f191db4c021a
Date: 2014-10-16 06:57 +0200
http://bitbucket.org/pypy/stmgc/changeset/f191db4c021a/

Log:    Progress

diff --git a/c7/stm/finalizer.c b/c7/stm/finalizer.c
--- a/c7/stm/finalizer.c
+++ b/c7/stm/finalizer.c
@@ -8,6 +8,7 @@
 static void init_finalizers(struct finalizers_s *f)
 {
     f->objects_with_finalizers = list_create();
+    f->count_non_young = 0;
     f->run_finalizers = NULL;
     f->running_next = NULL;
 }
@@ -83,6 +84,8 @@
 
 object_t *stm_allocate_with_finalizer(ssize_t size_rounded_up)
 {
+    object_t *obj = _stm_allocate_external(size_rounded_up);
+
     if (STM_PSEGMENT->finalizers == NULL) {
         struct finalizers_s *f = malloc(sizeof(struct finalizers_s));
         if (f == NULL)
@@ -90,8 +93,6 @@
         init_finalizers(f);
         STM_PSEGMENT->finalizers = f;
     }
-
-    object_t *obj = _allocate_old(size_rounded_up);
     LIST_APPEND(STM_PSEGMENT->finalizers->objects_with_finalizers, obj);
     return obj;
 }
@@ -201,16 +202,17 @@
         LIST_APPEND(_finalizer_tmpstack, obj);
 }
 
-static inline struct list_s *finalizer_trace(object_t *obj, struct list_s *lst)
+static inline struct list_s *finalizer_trace(char *base, object_t *obj,
+                                             struct list_s *lst)
 {
-    struct object_s *realobj =
-        (struct object_s *)REAL_ADDRESS(stm_object_pages, obj);
+    struct object_s *realobj = (struct object_s *)REAL_ADDRESS(base, obj);
     _finalizer_tmpstack = lst;
     stmcb_trace(realobj, &_append_to_finalizer_tmpstack);
     return _finalizer_tmpstack;
 }
 
-static void _recursively_bump_finalization_state(object_t *obj, int to_state)
+static void _recursively_bump_finalization_state(char *base, object_t *obj,
+                                                 int to_state)
 {
     struct list_s *tmpstack = _finalizer_emptystack;
     assert(list_is_empty(tmpstack));
@@ -221,7 +223,7 @@
             write_locks[mark_loc(obj)]++;
 
             /* trace */
-            tmpstack = finalizer_trace(obj, tmpstack);
+            tmpstack = finalizer_trace(base, obj, tmpstack);
         }
 
         if (list_is_empty(tmpstack))
@@ -232,7 +234,7 @@
     _finalizer_emptystack = tmpstack;
 }
 
-static struct list_s *mark_finalize_step1(struct finalizers_s *f)
+static struct list_s *mark_finalize_step1(char *base, struct finalizers_s *f)
 {
     if (f == NULL)
         return NULL;
@@ -259,20 +261,21 @@
             int state = _finalization_state(y);
             if (state <= 0) {
                 _bump_finalization_state_from_0_to_1(y);
-                pending = finalizer_trace(y, pending);
+                pending = finalizer_trace(base, y, pending);
             }
             else if (state == 2) {
-                _recursively_bump_finalization_state(y, 3);
+                _recursively_bump_finalization_state(base, y, 3);
             }
         }
         _finalizer_pending = pending;
         assert(_finalization_state(x) == 1);
-        _recursively_bump_finalization_state(x, 2);
+        _recursively_bump_finalization_state(base, x, 2);
     }
     return marked;
 }
 
-static void mark_finalize_step2(struct finalizers_s *f, struct list_s *marked)
+static void mark_finalize_step2(char *base, struct finalizers_s *f,
+                                struct list_s *marked)
 {
     if (f == NULL)
         return;
@@ -289,7 +292,7 @@
             if (run_finalizers == NULL)
                 run_finalizers = list_create();
             LIST_APPEND(run_finalizers, x);
-            _recursively_bump_finalization_state(x, 3);
+            _recursively_bump_finalization_state(base, x, 3);
         }
         else {
             struct list_s *lst = f->objects_with_finalizers;
@@ -325,17 +328,19 @@
     long j;
     for (j = 1; j <= NB_SEGMENTS; j++) {
         struct stm_priv_segment_info_s *pseg = get_priv_segment(j);
-        marked_seg[j] = mark_finalize_step1(pseg->finalizers);
+        marked_seg[j] = mark_finalize_step1(pseg->pub.segment_base,
+                                            pseg->finalizers);
     }
-    marked_seg[0] = mark_finalize_step1(&g_finalizers);
+    marked_seg[0] = mark_finalize_step1(stm_object_pages, &g_finalizers);
 
     LIST_FREE(_finalizer_pending);
 
     for (j = 1; j <= NB_SEGMENTS; j++) {
         struct stm_priv_segment_info_s *pseg = get_priv_segment(j);
-        mark_finalize_step2(pseg->finalizers, marked_seg[j]);
+        mark_finalize_step2(pseg->pub.segment_base, pseg->finalizers,
+                            marked_seg[j]);
     }
-    mark_finalize_step2(&g_finalizers, marked_seg[0]);
+    mark_finalize_step2(stm_object_pages, &g_finalizers, marked_seg[0]);
 
     LIST_FREE(_finalizer_emptystack);
 }
diff --git a/c7/stm/finalizer.h b/c7/stm/finalizer.h
--- a/c7/stm/finalizer.h
+++ b/c7/stm/finalizer.h
@@ -1,6 +1,7 @@
 
 struct finalizers_s {
     struct list_s *objects_with_finalizers;
+    uintptr_t count_non_young;
     struct list_s *run_finalizers;
     uintptr_t *running_next;
 };
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -111,20 +111,14 @@
     return addr;
 }
 
-static object_t *_allocate_old(ssize_t size_rounded_up)
+object_t *_stm_allocate_old(ssize_t size_rounded_up)
 {
+    /* only for tests xxx but stm_setup_prebuilt() uses this now too */
     char *p = allocate_outside_nursery_large(size_rounded_up);
     memset(p, 0, size_rounded_up);
 
     object_t *o = (object_t *)(p - stm_object_pages);
     o->stm_flags = GCFLAG_WRITE_BARRIER;
-    return o;
-}
-
-object_t *_stm_allocate_old(ssize_t size_rounded_up)
-{
-    /* only for tests xxx but stm_setup_prebuilt() uses this now too */
-    object_t *o = _allocate_old(size_rounded_up);
 
     if (testing_prebuilt_objs == NULL)
         testing_prebuilt_objs = list_create();
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -435,6 +435,22 @@
     }
 }
 
+static void collect_objs_still_young_but_with_finalizers(void)
+{
+    struct list_s *lst = STM_PSEGMENT->finalizers->objects_with_finalizers;
+    uintptr_t i, total = list_count(lst);
+
+    for (i = STM_PSEGMENT->finalizers->count_non_young; i < total; i++) {
+
+        object_t *o = (object_t *)list_item(lst, i);
+        minor_trace_if_young(&o);
+
+        /* was not actually movable */
+        assert(o == (object_t *)list_item(lst, i));
+    }
+    STM_PSEGMENT->finalizers->count_non_young = total;
+}
+
 static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg)
 {
 #pragma push_macro("STM_PSEGMENT")
@@ -554,6 +570,9 @@
 
     collect_roots_in_nursery();
 
+    if (STM_PSEGMENT->finalizers != NULL)
+        collect_objs_still_young_but_with_finalizers();
+
     collect_oldrefs_to_nursery();
     assert(list_is_empty(STM_PSEGMENT->old_objects_with_cards));
 
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -163,6 +163,8 @@
 
 void (*stmcb_light_finalizer)(object_t *);
 void stm_enable_light_finalizer(object_t *);
+
+void (*stmcb_finalizer)(object_t *);
 """)
 
 
@@ -459,6 +461,18 @@
     stm_read(obj)
     return lib._get_ptr(obj, idx)
 
+def stm_allocate_with_finalizer(size):
+    o = lib.stm_allocate_with_finalizer(size)
+    tid = 42 + size
+    lib._set_type_id(o, tid)
+    return o
+
+def stm_allocate_with_finalizer_refs(n):
+    o = lib.stm_allocate_with_finalizer(HDR + n * WORD)
+    tid = 421420 + n
+    lib._set_type_id(o, tid)
+    return o
+
 def stm_set_char(obj, c, offset=HDR, use_cards=False):
     assert HDR <= offset < stm_get_obj_size(obj)
     if use_cards:
diff --git a/c7/test/test_finalizer.py b/c7/test/test_finalizer.py
--- a/c7/test/test_finalizer.py
+++ b/c7/test/test_finalizer.py
@@ -127,3 +127,23 @@
         lp1 = stm_allocate_with_finalizer(48)
         stm_minor_collect()
         self.expect_finalized([])
+
+    def test_finalizer_in_major_collection(self):
+        self.start_transaction()
+        lp1 = stm_allocate_with_finalizer(48)
+        lp2 = stm_allocate_with_finalizer(48)
+        lp3 = stm_allocate_with_finalizer(48)
+        print lp1, lp2, lp3
+        stm_major_collect()
+        self.expect_finalized([lp1, lp2, lp3])
+
+    def test_finalizer_ordering(self):
+        self.start_transaction()
+        lp1 = stm_allocate_with_finalizer_refs(1)
+        lp2 = stm_allocate_with_finalizer_refs(1)
+        lp3 = stm_allocate_with_finalizer_refs(1)
+        print lp1, lp2, lp3
+        stm_set_ref(lp3, 0, lp1)
+        stm_set_ref(lp1, 0, lp2)
+        stm_major_collect()
+        self.expect_finalized([lp3])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to