Author: Remi Meier <remi.me...@inf.ethz.ch>
Branch: card-marking
Changeset: r1211:38e68ec4f6b5
Date: 2014-05-19 15:32 +0200
http://bitbucket.org/pypy/stmgc/changeset/38e68ec4f6b5/

Log:    initial sketch of API

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -40,8 +40,13 @@
 #endif
 }
 
-void _stm_write_slowpath(object_t *obj)
+void _stm_write_slowpath(object_t *obj, uintptr_t offset)
 {
+    assert(IMPLY(!(obj->stm_flags & GCFLAG_HAS_CARDS),
+                 offset == 0));
+    if (offset)
+        abort();
+
     assert(_seems_to_be_running_transaction());
     assert(!_is_young(obj));
     assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -35,6 +35,8 @@
 #define WRITELOCK_START       ((END_NURSERY_PAGE * 4096UL) >> 4)
 #define WRITELOCK_END         READMARKER_END
 
+#define CARD_SIZE   _STM_CARD_SIZE
+
 enum /* stm_flags */ {
     /* This flag is set on non-nursery objects.  It forces stm_write()
        to call _stm_write_slowpath().
@@ -54,6 +56,9 @@
        after the object. */
     GCFLAG_HAS_SHADOW = 0x04,
 
+    /* Set on objects after allocation that may use card marking */
+    GCFLAG_HAS_CARDS = _STM_GCFLAG_HAS_CARDS,
+
     /* All remaining bits of the 32-bit 'stm_flags' field are taken by
        the "overflow number".  This is a number that identifies the
        "overflow objects" from the current transaction among all old
@@ -61,7 +66,7 @@
        current transaction that have been flushed out of the nursery,
        which occurs if the same transaction allocates too many objects.
     */
-    GCFLAG_OVERFLOW_NUMBER_bit0 = 0x8   /* must be last */
+    GCFLAG_OVERFLOW_NUMBER_bit0 = 0x10   /* must be last */
 };
 
 
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -83,6 +83,7 @@
 {
     /* Check that some values are acceptable */
     assert(NB_SEGMENTS <= NB_SEGMENTS_MAX);
+    assert(CARD_SIZE > 0 && CARD_SIZE % 16 == 0);
     assert(4096 <= ((uintptr_t)STM_SEGMENT));
     assert((uintptr_t)STM_SEGMENT == (uintptr_t)STM_PSEGMENT);
     assert(((uintptr_t)STM_PSEGMENT) + sizeof(*STM_PSEGMENT) <= 8192);
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -106,7 +106,7 @@
 
 /* this should use llvm's coldcc calling convention,
    but it's not exposed to C code so far */
-void _stm_write_slowpath(object_t *);
+void _stm_write_slowpath(object_t *, uintptr_t);
 object_t *_stm_allocate_slowpath(ssize_t);
 object_t *_stm_allocate_external(ssize_t);
 void _stm_become_inevitable(const char*);
@@ -143,6 +143,8 @@
 #endif
 
 #define _STM_GCFLAG_WRITE_BARRIER      0x01
+#define _STM_GCFLAG_HAS_CARDS          0x08
+#define _STM_CARD_SIZE                 16 /* modulo 16 == 0! */
 #define _STM_NSE_SIGNAL_MAX     _STM_TIME_N
 #define _STM_FAST_ALLOC           (66*1024)
 
@@ -210,7 +212,24 @@
 static inline void stm_write(object_t *obj)
 {
     if (UNLIKELY((obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0))
-        _stm_write_slowpath(obj);
+        _stm_write_slowpath(obj, 0);
+}
+
+/* The following are barriers that work on the granularity of CARD_SIZE.
+   They can only be used on objects one called stm_use_cards() on. */
+__attribute__((always_inline))
+static inline void stm_read_card(object_t *obj, uintptr_t offset)
+{
+    OPT_ASSERT(obj->stm_flags & _STM_GCFLAG_HAS_CARDS);
+    ((stm_read_marker_t *)(((uintptr_t)obj + offset) >> 4))->rm =
+        STM_SEGMENT->transaction_read_version;
+}
+__attribute__((always_inline))
+static inline void stm_write_card(object_t *obj, uintptr_t offset)
+{
+    OPT_ASSERT(obj->stm_flags & _STM_GCFLAG_HAS_CARDS);
+    if (UNLIKELY((obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0))
+        _stm_write_slowpath(obj, offset);
 }
 
 /* Must be provided by the user of this library.
@@ -248,6 +267,16 @@
     return (object_t *)p;
 }
 
+/* directly after allocation one can enable card marking for any
+   kind of object with stm_use_cards(obj). This enables the use
+   of stm_write/read_card() barriers that do more fine-grained
+   conflict detection and garbage collection. */
+__attribute__((always_inline))
+static inline void stm_use_cards(object_t* o)
+{
+    o->stm_flags |= _STM_GCFLAG_HAS_CARDS;
+}
+
 /* Allocate a weakref object. Weakref objects have a
    reference to an object at the byte-offset
        stmcb_size_rounded_up(obj) - sizeof(void*)
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -12,6 +12,8 @@
 #define STM_NB_SEGMENTS ...
 #define _STM_FAST_ALLOC ...
 #define _STM_GCFLAG_WRITE_BARRIER ...
+#define _STM_GCFLAG_HAS_CARDS ...
+#define _STM_CARD_SIZE ...
 #define STM_STACK_MARKER_NEW ...
 #define STM_STACK_MARKER_OLD ...
 
@@ -41,6 +43,11 @@
 object_t *stm_allocate_weakref(ssize_t size_rounded_up);
 object_t *_stm_allocate_old(ssize_t size_rounded_up);
 
+void stm_use_cards(object_t* o);
+void stm_read_card(object_t *obj, uintptr_t offset);
+/*void stm_write_card(); use _checked_stm_write_card() instead */
+
+
 void stm_setup(void);
 void stm_teardown(void);
 void stm_register_thread_local(stm_thread_local_t *tl);
@@ -49,6 +56,7 @@
 object_t *stm_setup_prebuilt_weakref(object_t *);
 
 bool _checked_stm_write(object_t *obj);
+bool _checked_stm_write_card(object_t *obj, uintptr_t offset);
 bool _stm_was_read(object_t *obj);
 bool _stm_was_written(object_t *obj);
 char *_stm_real_address(object_t *obj);
@@ -181,6 +189,10 @@
     CHECKED(stm_write(object));
 }
 
+bool _checked_stm_write_card(object_t *object, uintptr_t offset) {
+    CHECKED(stm_write_card(object, offset));
+}
+
 bool _check_stop_safe_point(void) {
     CHECKED(_stm_stop_safe_point());
 }
@@ -323,6 +335,8 @@
 HDR = lib.SIZEOF_MYOBJ
 assert HDR == 8
 GCFLAG_WRITE_BARRIER = lib._STM_GCFLAG_WRITE_BARRIER
+GCFLAG_HAS_CARDS = lib._STM_GCFLAG_HAS_CARDS
+CARD_SIZE = lib._STM_CARD_SIZE # 16b at least
 NB_SEGMENTS = lib.STM_NB_SEGMENTS
 
 
@@ -335,20 +349,26 @@
 def is_in_nursery(o):
     return lib.stm_can_move(o)
 
-def stm_allocate_old(size):
+def stm_allocate_old(size, use_cards=False):
     o = lib._stm_allocate_old(size)
+    if use_cards:
+        lib.stm_use_cards(o)
     tid = 42 + size
     lib._set_type_id(o, tid)
     return o
 
-def stm_allocate_old_refs(n):
+def stm_allocate_old_refs(n, use_cards=False):
     o = lib._stm_allocate_old(HDR + n * WORD)
+    if use_cards:
+        lib.stm_use_cards(o)
     tid = 421420 + n
     lib._set_type_id(o, tid)
     return o
 
-def stm_allocate(size):
+def stm_allocate(size, use_cards=False):
     o = lib.stm_allocate(size)
+    if use_cards:
+        lib.stm_use_cards(o)
     tid = 42 + size
     lib._set_type_id(o, tid)
     return o
@@ -365,8 +385,10 @@
 def stm_get_weakref(o):
     return lib._get_weakref(o)
 
-def stm_allocate_refs(n):
+def stm_allocate_refs(n, use_cards=False):
     o = lib.stm_allocate(HDR + n * WORD)
+    if use_cards:
+        lib.stm_use_cards(o)
     tid = 421420 + n
     lib._set_type_id(o, tid)
     return o
@@ -395,10 +417,21 @@
 def stm_read(o):
     lib.stm_read(o)
 
+def stm_read_card(o, offset):
+    assert stm_get_flags(o) & GCFLAG_HAS_CARDS
+    assert offset < stm_get_obj_size(o)
+    lib.stm_read_card(o, offset)
+
 def stm_write(o):
     if lib._checked_stm_write(o):
         raise Conflict()
 
+def stm_write_card(o, offset):
+    assert stm_get_flags(o) & GCFLAG_HAS_CARDS
+    assert offset < stm_get_obj_size(o)
+    if lib._checked_stm_write_card(o, offset):
+        raise Conflict()
+
 def stm_was_read(o):
     return lib._stm_was_read(o)
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to