Author: Remi Meier <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit