[pypy-commit] stmgc c7-refactor: Actually implement surviving young_outside_nursery
arigo
noreply at buildbot.pypy.org
Tue Feb 25 09:50:25 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r854:4302246a0ad0
Date: 2014-02-25 09:50 +0100
http://bitbucket.org/pypy/stmgc/changeset/4302246a0ad0/
Log: Actually implement surviving young_outside_nursery
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -12,7 +12,7 @@
void _stm_write_slowpath(object_t *obj)
{
assert(_running_transaction());
- assert(!_is_in_nursery(obj));
+ assert(!_is_young(obj));
/* is this an object from the same transaction, outside the nursery? */
if ((obj->stm_flags & -GCFLAG_OVERFLOW_NUMBER_bit0) ==
@@ -225,7 +225,7 @@
static void synchronize_overflow_object_now(object_t *obj)
{
- assert(!_is_in_nursery(obj));
+ assert(!_is_young(obj));
assert((obj->stm_flags & GCFLAG_SMALL_UNIFORM) == 0);
char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -42,6 +42,12 @@
return (uintptr_t)obj < NURSERY_END;
}
+static inline bool _is_young(object_t *obj)
+{
+ return (_is_in_nursery(obj) ||
+ tree_contains(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj));
+}
+
bool _stm_in_nursery(object_t *obj)
{
return _is_in_nursery(obj);
@@ -54,6 +60,19 @@
#define FLAG_SYNC_LARGE_NOW 0x01
+static void minor_young_outside_nursery(object_t *obj)
+{
+ tree_delete_item(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj);
+
+ uintptr_t nobj_sync_now = (uintptr_t)obj;
+ if (STM_PSEGMENT->minor_collect_will_commit_now)
+ nobj_sync_now |= FLAG_SYNC_LARGE_NOW;
+ else
+ LIST_APPEND(STM_PSEGMENT->large_overflow_objects, obj);
+
+ LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now);
+}
+
static void minor_trace_if_young(object_t **pobj)
{
/* takes a normal pointer to a thread-local pointer to an object */
@@ -61,8 +80,13 @@
if (obj == NULL)
return;
assert((uintptr_t)obj < NB_PAGES * 4096UL);
- if (!_is_in_nursery(obj))
- return;
+ if (!_is_in_nursery(obj)) {
+ if (UNLIKELY(tree_contains(STM_PSEGMENT->young_outside_nursery,
+ (uintptr_t)obj))) {
+ minor_young_outside_nursery(obj);
+ }
+ return; /* else old object, nothing to do */
+ }
/* If the object was already seen here, its first word was set
to GCWORD_MOVED. In that case, the forwarding location, i.e.
@@ -133,7 +157,7 @@
static inline void _collect_now(object_t *obj)
{
- assert(!_is_in_nursery(obj));
+ assert(!_is_young(obj));
/* We must not have GCFLAG_WRITE_BARRIER so far. Add it now. */
assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER));
diff --git a/c7/test/test_nursery.py b/c7/test/test_nursery.py
--- a/c7/test/test_nursery.py
+++ b/c7/test/test_nursery.py
@@ -81,7 +81,7 @@
assert old
assert young
- def test_larger_than_limit_for_nursery(self):
+ def test_larger_than_limit_for_nursery_die(self):
obj_size = lib._STM_FAST_ALLOC + 16
self.start_transaction()
@@ -93,6 +93,28 @@
seen.add(new)
assert len(seen) < 5 # addresses are reused
+ def test_larger_than_limit_for_nursery_dont_die(self):
+ obj_nrefs = (lib._STM_FAST_ALLOC + 16) // 8
+
+ self.start_transaction()
+ lp1 = ffi.cast("object_t *", 0)
+ seen = set()
+ for i in range(100):
+ self.push_root(lp1)
+ stm_minor_collect()
+ lp1 = self.pop_root()
+ new = stm_allocate_refs(obj_nrefs)
+ assert not is_in_nursery(new)
+ seen.add(new)
+ stm_set_ref(new, i, lp1)
+ lp1 = new
+ assert len(seen) == 100 # addresses are not reused
+
+ for i in reversed(range(100)):
+ assert lp1
+ lp1 = stm_get_ref(lp1, i)
+ assert not lp1
+
def test_reset_partial_alloc_pages(self):
py.test.skip("a would-be-nice feature, but not actually needed: "
"the next major GC will take care of it")
More information about the pypy-commit
mailing list