Author: Armin Rigo <[email protected]>
Branch: c7-refactor
Changeset: r853:9fb1364ed14f
Date: 2014-02-25 09:38 +0100
http://bitbucket.org/pypy/stmgc/changeset/9fb1364ed14f/

Log:    Use the trees to implement young_outside_nursery, step 1.

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -179,6 +179,7 @@
     }
 
     assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
+    assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery));
     assert(STM_PSEGMENT->objects_pointing_to_nursery == NULL);
     assert(STM_PSEGMENT->large_overflow_objects == NULL);
 
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -81,6 +81,11 @@
        current transaction spanned a minor collection. */
     struct list_s *large_overflow_objects;
 
+    /* List of all young objects outside the nursery ("young" in the
+       sense that they should be in the nursery, but were too big for
+       that). */
+    struct tree_s *young_outside_nursery;
+
     /* Start time: to know approximately for how long a transaction has
        been running, in contention management */
     uint64_t start_time;
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -105,8 +105,8 @@
 static void tree_clear(struct tree_s *tree);
 //static inline void tree_delete_not_used_any_more(struct tree_s *tree)...
 
-static inline bool tree_any_entry(struct tree_s *tree) {
-    return tree->raw_current != tree->raw_start;
+static inline bool tree_is_cleared(struct tree_s *tree) {
+    return tree->raw_current == tree->raw_start;
 }
 
 #define _TREE_LOOP(tree, item, INITIAL, _PLUS_)                         \
@@ -177,7 +177,8 @@
 static wlog_t *_tree_find(char *entry, uintptr_t addr);
 static void _tree_compress(struct tree_s *tree) __attribute__((unused));
 static void tree_insert(struct tree_s *tree, uintptr_t addr, uintptr_t val);
-static bool tree_delete_item(struct tree_s *tree, uintptr_t addr);
+static bool tree_delete_item(struct tree_s *tree, uintptr_t addr)
+     __attribute__((unused));
 
 static inline bool tree_contains(struct tree_s *tree, uintptr_t addr)
 {
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -182,6 +182,19 @@
     memset(realnursery, 0, size);
 
     STM_SEGMENT->nursery_current = (stm_char *)_stm_nursery_start;
+
+    /* free any object left from 'young_outside_nursery' */
+    if (!tree_is_cleared(STM_PSEGMENT->young_outside_nursery)) {
+        mutex_pages_lock();
+
+        wlog_t *item;
+        TREE_LOOP_FORWARD(*STM_PSEGMENT->young_outside_nursery, item) {
+            _stm_large_free(stm_object_pages + item->addr);
+        } TREE_LOOP_END;
+
+        tree_clear(STM_PSEGMENT->young_outside_nursery);
+        mutex_pages_unlock();
+    }
 }
 
 static void minor_collection(bool commit)
@@ -268,7 +281,14 @@
 
 object_t *_stm_allocate_external(ssize_t size_rounded_up)
 {
-    abort();//...
+    /* XXX force a minor/major collection if needed */
+
+    char *result = allocate_outside_nursery_large(size_rounded_up);
+    memset(result, 0, size_rounded_up);
+
+    object_t *o = (object_t *)(result - stm_object_pages);
+    tree_insert(STM_PSEGMENT->young_outside_nursery, (intptr_t)o, 0);
+    return o;
 }
 
 #ifdef STM_TESTS
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -56,6 +56,7 @@
         pr->objects_pointing_to_nursery = NULL;
         pr->large_overflow_objects = NULL;
         pr->modified_old_objects = list_create();
+        pr->young_outside_nursery = tree_create();
         pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * (i + 1);
         highest_overflow_number = pr->overflow_number;
     }
@@ -88,6 +89,7 @@
         assert(pr->objects_pointing_to_nursery == NULL);
         assert(pr->large_overflow_objects == NULL);
         list_free(pr->modified_old_objects);
+        tree_free(pr->young_outside_nursery);
     }
 
     munmap(stm_object_pages, TOTAL_MEMORY);
diff --git a/c7/test/test_list.py b/c7/test/test_list.py
--- a/c7/test/test_list.py
+++ b/c7/test/test_list.py
@@ -1,3 +1,4 @@
+import random
 import cffi
 from common import parent_dir
 
@@ -9,9 +10,11 @@
 struct tree_s *tree_create(void);
 void tree_free(struct tree_s *tree);
 void tree_clear(struct tree_s *tree);
+bool tree_is_cleared(struct tree_s *tree);
 bool tree_contains(struct tree_s *tree, uintptr_t addr);
 void tree_insert(struct tree_s *tree, uintptr_t addr, uintptr_t val);
 bool tree_delete_item(struct tree_s *tree, uintptr_t addr);
+int test_tree_walk(struct tree_s *tree, uintptr_t addrs[]);
 """)
 
 lib = ffi.verify('''
@@ -27,6 +30,23 @@
 
 #define _STM_CORE_H_
 #include "stm/list.c"
+
+int test_tree_walk(struct tree_s *tree, uintptr_t addrs[])
+{
+    int result = 0;
+    wlog_t *item;
+    TREE_LOOP_FORWARD(*tree, item) {
+        addrs[result++] = item->addr;
+    } TREE_LOOP_END;
+    int i = result;
+    TREE_LOOP_BACKWARD(*tree, item) {
+        assert(i > 0);
+        i--;
+        assert(addrs[i] == item->addr);
+    } TREE_LOOP_END;
+    assert(i == 0);
+    return result;
+}
 ''', define_macros=[('STM_TESTS', '1')],
      undef_macros=['NDEBUG'],
      include_dirs=[parent_dir],
@@ -35,6 +55,8 @@
 
 # ____________________________________________________________
 
+# XXX need tests for list_xxx too
+
 def test_tree_empty():
     t = lib.tree_create()
     for i in range(100):
@@ -47,3 +69,57 @@
     for i in range(100):
         assert lib.tree_contains(t, i) == (i == 23)
     lib.tree_free(t)
+
+def test_tree_is_cleared():
+    t = lib.tree_create()
+    assert lib.tree_is_cleared(t)
+    lib.tree_insert(t, 23, 456)
+    assert not lib.tree_is_cleared(t)
+    lib.tree_free(t)
+
+def test_tree_delete_item():
+    t = lib.tree_create()
+    lib.tree_insert(t, 23, 456)
+    lib.tree_insert(t, 42, 34289)
+    assert not lib.tree_is_cleared(t)
+    assert lib.tree_contains(t, 23)
+    res = lib.tree_delete_item(t, 23)
+    assert res
+    assert not lib.tree_contains(t, 23)
+    res = lib.tree_delete_item(t, 23)
+    assert not res
+    res = lib.tree_delete_item(t, 21)
+    assert not res
+    assert not lib.tree_is_cleared(t)
+    assert lib.tree_contains(t, 42)
+    res = lib.tree_delete_item(t, 42)
+    assert res
+    assert not lib.tree_is_cleared(t)   # not cleared, but still empty
+    for i in range(100):
+        assert not lib.tree_contains(t, i)
+    lib.tree_free(t)
+
+def test_tree_walk():
+    t = lib.tree_create()
+    lib.tree_insert(t, 23, 456)
+    lib.tree_insert(t, 42, 34289)
+    a = ffi.new("uintptr_t[10]")
+    res = lib.test_tree_walk(t, a)
+    assert res == 2
+    assert a[0] == 23
+    assert a[1] == 42
+    lib.tree_free(t)
+
+def test_tree_walk_big():
+    t = lib.tree_create()
+    values = [random.randrange(0, 1000000) for i in range(300)]
+    for x in values:
+        lib.tree_insert(t, x, x)
+    a = ffi.new("uintptr_t[1000]")
+    res = lib.test_tree_walk(t, a)
+    assert res == 300
+    found = set()
+    for i in range(res):
+        found.add(a[i])
+    assert found == set(values)
+    lib.tree_free(t)
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
@@ -3,23 +3,6 @@
 
 class TestBasic(BaseTest):
 
-    def test_nursery_large(self):
-        py.test.skip("XXX later")
-        self.start_transaction()
-        lp1 = stm_allocate(SOME_LARGE_SIZE)
-        lp2 = stm_allocate(SOME_LARGE_SIZE)
-
-        u1 = int(ffi.cast("uintptr_t", lp1))
-        u2 = int(ffi.cast("uintptr_t", lp2))
-        assert (u1 & 255) == 0
-        assert (u2 & 255) == 0
-        assert stm_creation_marker(lp1) == 0xff
-        assert stm_creation_marker(lp2) == 0xff
-
-        self.commit_transaction()
-        assert stm_creation_marker(lp1) == 0
-        assert stm_creation_marker(lp2) == 0
-
     def test_nursery_full(self):
         lib._stm_set_nursery_free_count(2048)
         self.start_transaction()
@@ -99,7 +82,6 @@
         assert young
 
     def test_larger_than_limit_for_nursery(self):
-        py.test.skip("XXX later")
         obj_size = lib._STM_FAST_ALLOC + 16
 
         self.start_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to