[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