[pypy-commit] stmgc default: do simple minor collections

Raemi noreply at buildbot.pypy.org
Wed Sep 3 13:33:56 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: 
Changeset: r1339:99ad13731c25
Date: 2014-09-03 13:33 +0200
http://bitbucket.org/pypy/stmgc/changeset/99ad13731c25/

Log:	do simple minor collections

diff --git a/c8/stm/gcpage.h b/c8/stm/gcpage.h
--- a/c8/stm/gcpage.h
+++ b/c8/stm/gcpage.h
@@ -5,3 +5,4 @@
 
 static void setup_gcpage(void);
 static void teardown_gcpage(void);
+static char *allocate_outside_nursery_large(uint64_t size);
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -30,6 +30,11 @@
     return (uintptr_t)obj < NURSERY_END;
 }
 
+static inline bool _is_young(object_t *obj)
+{
+    return _is_in_nursery(obj); /* XXX: young_outside_nursery */
+}
+
 long stm_can_move(object_t *obj)
 {
     /* 'long' return value to avoid using 'bool' in the public interface */
@@ -38,6 +43,83 @@
 
 
 /************************************************************/
+#define GCWORD_MOVED  ((object_t *) -1)
+
+static void minor_trace_if_young(object_t **pobj)
+{
+    /* takes a normal pointer to a thread-local pointer to an object */
+    object_t *obj = *pobj;
+    object_t *nobj;
+    char *realobj;
+    size_t size;
+
+    if (obj == NULL)
+        return;
+    assert((uintptr_t)obj < NB_PAGES * 4096UL);
+
+    if (_is_in_nursery(obj)) {
+        /* If the object was already seen here, its first word was set
+           to GCWORD_MOVED.  In that case, the forwarding location, i.e.
+           where the object moved to, is stored in the second word in 'obj'. */
+        object_t *TLPREFIX *pforwarded_array = (object_t *TLPREFIX *)obj;
+
+        realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+        size = stmcb_size_rounded_up((struct object_s *)realobj);
+
+        /* XXX: small objs */
+        char *allocated = allocate_outside_nursery_large(size);
+        nobj = (object_t *)(allocated - stm_object_pages);
+
+        char *realnobj = REAL_ADDRESS(STM_SEGMENT->segment_base, nobj);
+        memcpy(realnobj, realobj, size);
+
+        pforwarded_array[0] = GCWORD_MOVED;
+        pforwarded_array[1] = nobj;
+        *pobj = nobj;
+    }
+    else {
+        /* XXX: young_outside_nursery */
+        return;
+    }
+
+    /* Must trace the object later */
+    LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, (uintptr_t)nobj);
+}
+
+
+static inline void _collect_now(object_t *obj)
+{
+    assert(!_is_young(obj));
+
+    dprintf(("_collect_now: %p\n", obj));
+
+    assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER));
+
+    char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+    stmcb_trace((struct object_s *)realobj, &minor_trace_if_young);
+
+    obj->stm_flags |= GCFLAG_WRITE_BARRIER;
+}
+
+
+static void collect_oldrefs_to_nursery(void)
+{
+    dprintf(("collect_oldrefs_to_nursery\n"));
+    struct list_s *lst = STM_PSEGMENT->objects_pointing_to_nursery;
+
+    while (!list_is_empty(lst)) {
+        object_t *obj = (object_t *)list_pop_item(lst);;
+
+        _collect_now(obj);
+
+        /* XXX: only if commit now and only for big objs */
+        _push_obj_to_other_segments(obj);
+
+        /* the list could have moved while appending */
+        lst = STM_PSEGMENT->objects_pointing_to_nursery;
+    }
+}
+
 
 static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg)
 {
@@ -77,6 +159,8 @@
 {
     dprintf(("minor_collection commit=%d\n", (int)commit));
 
+    collect_oldrefs_to_nursery();
+
     assert(list_is_empty(STM_PSEGMENT->objects_pointing_to_nursery));
 
     throw_away_nursery(get_priv_segment(STM_SEGMENT->segment_num));
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -109,6 +109,7 @@
 };
 
 extern ssize_t stmcb_size_rounded_up(struct object_s *);
+void stmcb_trace(struct object_s *obj, void visit(object_t **));
 
 __attribute__((always_inline))
 static inline void stm_read(object_t *obj)
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -182,6 +182,22 @@
     }
 }
 
+
+void stmcb_trace(struct object_s *obj, void visit(object_t **))
+{
+    int i;
+    struct myobj_s *myobj = (struct myobj_s*)obj;
+    if (myobj->type_id < 421420) {
+        /* basic case: no references */
+        return;
+    }
+    for (i=0; i < myobj->type_id - 421420; i++) {
+        object_t **ref = ((object_t **)(myobj + 1)) + i;
+        visit(ref);
+    }
+}
+
+
 ''', sources=source_files,
      define_macros=[('STM_TESTS', '1'),
                     ('STM_NO_AUTOMATIC_SETJMP', '1'),
diff --git a/c8/test/test_basic.py b/c8/test/test_basic.py
--- a/c8/test/test_basic.py
+++ b/c8/test/test_basic.py
@@ -62,6 +62,7 @@
 
     def test_write_on_old(self):
         lp1 = stm_allocate_old(16)
+
         self.start_transaction()
         assert stm_get_char(lp1) == '\0'
         stm_write(lp1)
@@ -80,6 +81,8 @@
     def test_read_write_1(self):
         lp1 = stm_allocate_old(16)
         stm_get_real_address(lp1)[HDR] = 'a' #setchar
+        lib._push_obj_to_other_segments(lp1)
+        #
         self.start_transaction()
         self.commit_transaction()
         #
@@ -88,7 +91,7 @@
         assert modified_old_objects() == []
         stm_write(lp1)
         assert modified_old_objects() == [lp1]
-        assert objects_pointing_to_nursery() == None
+        assert objects_pointing_to_nursery() == [lp1]
         assert stm_get_char(lp1) == 'a'
         stm_set_char(lp1, 'b')
         #


More information about the pypy-commit mailing list