Author: Remi Meier <[email protected]>
Branch: c8-card-marking
Changeset: r1674:11b04ac95b6c
Date: 2015-02-27 11:22 +0100
http://bitbucket.org/pypy/stmgc/changeset/11b04ac95b6c/
Log: in-progress state that needs overflow objs to continue
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -610,9 +610,11 @@
that the write_slowpath will not be called again until the
next minor collection. */
if (obj->stm_flags & GCFLAG_CARDS_SET) {
- /* if we clear this flag, we also need to clear the cards */
+ /* if we clear this flag, we also need to clear the cards.
+ bk_slices are not needed as this is a new object */
+ /* XXX: add_missing_bk_slices_and_"clear"_cards */
_reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
- obj, CARD_CLEAR, false);
+ obj, CARD_CLEAR, false, false);
}
obj->stm_flags &= ~(GCFLAG_WRITE_BARRIER | GCFLAG_CARDS_SET);
LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
@@ -731,8 +733,12 @@
if (obj->stm_flags & GCFLAG_CARDS_SET) {
/* if we clear this flag, we have to tell sync_old_objs that
everything needs to be synced */
+ /* if we clear this flag, we have to tell later write barriers
+ that we already did all backup slices: */
+ /* XXX: do_other_bk_slices_and_"clear"_cards */
_reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
- obj, CARD_MARKED_OLD, true); /* mark all */
+ obj, STM_SEGMENT->transaction_read_version,
+ true, false); /* mark all */
}
/* remove the WRITE_BARRIER flag and add WB_EXECUTED */
@@ -840,7 +846,8 @@
#endif
memset(readmarkers, 0, NB_READMARKER_PAGES * 4096UL);
}
- STM_SEGMENT->transaction_read_version = 1;
+ STM_SEGMENT->transaction_read_version = 2;
+ assert(STM_SEGMENT->transaction_read_version > _STM_CARD_MARKED);
}
static void reset_cards_from_modified_objects(void)
@@ -1308,8 +1315,27 @@
}
-static void _page_wise_synchronize_object_now(object_t *obj, ssize_t obj_size)
+
+static void synchronize_object_enqueue(object_t *obj)
{
+ assert(!_is_young(obj));
+ assert(STM_PSEGMENT->privatization_lock);
+ assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
+ assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED));
+
+ ssize_t obj_size = stmcb_size_rounded_up(
+ (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
+ OPT_ASSERT(obj_size >= 16);
+
+ if (LIKELY(is_small_uniform(obj))) {
+ assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
+ OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE);
+ _synchronize_fragment((stm_char *)obj, obj_size);
+ return;
+ }
+
+ /* else, a more complicated case for large objects, to copy
+ around data only within the needed pages */
uintptr_t start = (uintptr_t)obj;
uintptr_t end = start + obj_size;
@@ -1330,135 +1356,6 @@
} while (start != end);
}
-static void _card_wise_synchronize_object_now(object_t *obj, ssize_t obj_size)
-{
- assert(obj_size >= 32);
- assert(obj_should_use_cards(STM_SEGMENT->segment_base, obj));
- assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
-
- uintptr_t offset_itemsize[2];
- struct object_s *realobj = (struct object_s
*)REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
- stmcb_get_card_base_itemsize(realobj, offset_itemsize);
- size_t real_idx_count = (obj_size - offset_itemsize[0]) /
offset_itemsize[1];
-
- struct stm_read_marker_s *cards =
get_read_marker(STM_SEGMENT->segment_base, (uintptr_t)obj);
- uintptr_t card_index = 1;
- uintptr_t last_card_index = get_index_to_card_index(real_idx_count - 1);
/* max valid index */
- assert(cards->rm == STM_SEGMENT->transaction_read_version); /* stm_read()
*/
-
- /* simple heuristic to check if probably the whole object is
- marked anyway so we should do page-wise synchronize */
- if (cards[1].rm == CARD_MARKED_OLD
- && cards[last_card_index].rm == CARD_MARKED_OLD
- && cards[(last_card_index >> 1) + 1].rm == CARD_MARKED_OLD) {
-
- dprintf(("card_wise_sync assumes %p,size:%lu is fully marked\n", obj,
obj_size));
- _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
- obj, CARD_CLEAR, false);
- _page_wise_synchronize_object_now(obj, obj_size);
- return;
- }
-
- dprintf(("card_wise_sync syncs %p,size:%lu card-wise\n", obj, obj_size));
-
- /* Combine multiple marked cards and do a memcpy for them. We don't
- try yet to use page_copy() or otherwise take into account privatization
- of pages (except _has_private_page_in_range) */
- bool all_cards_were_cleared = true;
-
- uintptr_t start_card_index = -1;
- while (card_index <= last_card_index) {
- uint8_t card_value = cards[card_index].rm;
-
- if (card_value == CARD_MARKED_OLD) {
- cards[card_index].rm = CARD_CLEAR;
-
- if (start_card_index == -1) { /* first marked card */
- start_card_index = card_index;
- /* start = (uintptr_t)obj + stmcb_index_to_byte_offset( */
- /* realobj, get_card_index_to_index(card_index)); */
- if (all_cards_were_cleared) {
- all_cards_were_cleared = false;
- }
- }
- }
- else {
- OPT_ASSERT(card_value == CARD_CLEAR);
- }
-
- if (start_card_index != -1 /* something to copy */
- && (card_value != CARD_MARKED_OLD /* found non-marked card
*/
- || card_index == last_card_index)) { /* this is the last card
*/
- /* do the copying: */
- uintptr_t start, copy_size;
- uintptr_t next_card_offset;
- uintptr_t start_card_offset;
- uintptr_t next_card_index = card_index;
-
- if (card_value == CARD_MARKED_OLD) {
- /* card_index is the last card of the object, but we need
- to go one further to get the right offset */
- next_card_index++;
- }
-
- start_card_offset = offset_itemsize[0] +
- get_card_index_to_index(start_card_index) * offset_itemsize[1];
-
- next_card_offset = offset_itemsize[0] +
- get_card_index_to_index(next_card_index) * offset_itemsize[1];
-
- if (next_card_offset > obj_size)
- next_card_offset = obj_size;
-
- start = (uintptr_t)obj + start_card_offset;
- copy_size = next_card_offset - start_card_offset;
- OPT_ASSERT(copy_size > 0);
-
- /* push to seg0 and enqueue for synchronization */
- _synchronize_fragment((stm_char *)start, copy_size);
-
- start_card_index = -1;
- }
-
- card_index++;
- }
-
- if (all_cards_were_cleared) {
- /* well, seems like we never called stm_write_card() on it, so actually
- we need to fall back to synchronize the whole object */
- _page_wise_synchronize_object_now(obj, obj_size);
- return;
- }
-
-}
-
-
-static void synchronize_object_enqueue(object_t *obj, bool ignore_cards)
-{
- assert(!_is_young(obj));
- assert(STM_PSEGMENT->privatization_lock);
- assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
- assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED));
-
- ssize_t obj_size = stmcb_size_rounded_up(
- (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
- OPT_ASSERT(obj_size >= 16);
-
- if (LIKELY(is_small_uniform(obj))) {
- assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
- OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE);
- _synchronize_fragment((stm_char *)obj, obj_size);
- return;
- } else if (ignore_cards ||
!obj_should_use_cards(STM_SEGMENT->segment_base, obj)) {
- /* else, a more complicated case for large objects, to copy
- around data only within the needed pages */
- _page_wise_synchronize_object_now(obj, obj_size);
- } else {
- /* ... or even only cards that need to be updated */
- _card_wise_synchronize_object_now(obj, obj_size);
- }
-}
-
static void synchronize_objects_flush(void)
{
long j = STM_PSEGMENT->sq_len;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -50,7 +50,7 @@
enum /* card values in read markers */ {
CARD_CLEAR = 0, /* card not used at all */
CARD_MARKED = _STM_CARD_MARKED, /* card marked for tracing in the next gc
*/
- CARD_MARKED_OLD = _STM_CARD_MARKED+1,
+ /* CARD_MARKED_OLD = STM_PSEGMENT->transaction_read_version, */
/* card was marked before, but cleared in a GC */
};
@@ -246,7 +246,7 @@
static stm_thread_local_t *abort_with_mutex_no_longjmp(void);
static void abort_data_structures_from_segment_num(int segment_num);
-static void synchronize_object_enqueue(object_t *obj, bool ignore_cards);
+static void synchronize_object_enqueue(object_t *obj);
static void synchronize_objects_flush(void);
static void _signal_handler(int sig, siginfo_t *siginfo, void *context);
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -518,8 +518,9 @@
/* mark marked cards as old if it survives */
uint8_t mark_value = mark_visited_test(item) ?
- CARD_MARKED_OLD : CARD_CLEAR;
- _reset_object_cards(pseg, item, mark_value, false);
+ pseg->pub.transaction_read_version : CARD_CLEAR;
+ _reset_object_cards(pseg, item, mark_value, false,
+ mark_value == CARD_CLEAR);
}));
list_clear(lst);
@@ -531,7 +532,7 @@
object_t *obj = (object_t *)list_item(lst, n);
if (!mark_visited_test(obj)) {
if (obj_should_use_cards(pseg->pub.segment_base, obj))
- _reset_object_cards(pseg, obj, CARD_CLEAR, false);
+ _reset_object_cards(pseg, obj, CARD_CLEAR, false, true);
list_set_item(lst, n, list_pop_item(lst));
}
}
diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -118,6 +118,11 @@
return cards[get_index_to_card_index(idx)].rm;
}
+uint8_t _stm_get_transaction_read_version()
+{
+ return STM_SEGMENT->transaction_read_version;
+}
+
static struct stm_commit_log_entry_s *_last_cl_entry;
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -159,7 +159,8 @@
uintptr_t last_card_index = get_index_to_card_index(size - 1); /* max
valid index */
while (card_index <= last_card_index) {
- assert(cards[card_index].rm == CARD_CLEAR);
+ assert(cards[card_index].rm == CARD_CLEAR
+ || cards[card_index].rm < pseg->pub.transaction_read_version);
card_index++;
}
@@ -191,7 +192,7 @@
static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
object_t *obj, uint8_t mark_value,
- bool mark_all)
+ bool mark_all, bool really_clear)
{
#pragma push_macro("STM_PSEGMENT")
#pragma push_macro("STM_SEGMENT")
@@ -205,8 +206,12 @@
stmcb_get_card_base_itemsize(realobj, offset_itemsize);
size = (size - offset_itemsize[0]) / offset_itemsize[1];
+ /* really_clear only used for freed new objs in minor collections, as
+ they need to clear cards even if they are set to
transaction_read_version */
+ assert(IMPLY(really_clear, mark_value == CARD_CLEAR && !mark_all));
assert(IMPLY(mark_value == CARD_CLEAR, !mark_all)); /* not necessary */
- assert(IMPLY(mark_all, mark_value == CARD_MARKED_OLD)); /* set *all* to
OLD */
+ assert(IMPLY(mark_all,
+ mark_value == pseg->pub.transaction_read_version)); /* set
*all* to OLD */
struct stm_read_marker_s *cards = get_read_marker(pseg->pub.segment_base,
(uintptr_t)obj);
uintptr_t card_index = 1;
@@ -216,7 +221,8 @@
obj, size, mark_value, mark_all));
dprintf(("obj has %lu cards\n", last_card_index));*/
while (card_index <= last_card_index) {
- if (mark_all || cards[card_index].rm != CARD_CLEAR) {
+ if (mark_all || cards[card_index].rm == CARD_MARKED
+ || (really_clear && cards[card_index].rm != CARD_CLEAR)) {
/* dprintf(("mark card %lu,wl:%lu of %p with %d\n", */
/* card_index, card_lock_idx, obj, mark_value)); */
cards[card_index].rm = mark_value;
@@ -238,7 +244,6 @@
assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
dprintf(("_trace_card_object(%p)\n", obj));
- uint8_t mark_value = CARD_MARKED_OLD;
struct object_s *realobj = (struct object_s
*)REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
size_t size = stmcb_size_rounded_up(realobj);
@@ -254,7 +259,7 @@
while (card_index <= last_card_index) {
if (cards[card_index].rm == CARD_MARKED) {
/* clear or set to old: */
- cards[card_index].rm = mark_value;
+ cards[card_index].rm = STM_SEGMENT->transaction_read_version;
uintptr_t start = get_card_index_to_index(card_index);
uintptr_t stop = get_card_index_to_index(card_index + 1);
@@ -340,7 +345,7 @@
struct stm_priv_segment_info_s *pseg =
get_priv_segment(STM_SEGMENT->segment_num);
if (pseg->minor_collect_will_commit_now) {
acquire_privatization_lock(pseg->pub.segment_num);
- synchronize_object_enqueue(obj, true); /* ignore cards! */
+ synchronize_object_enqueue(obj);
release_privatization_lock(pseg->pub.segment_num);
} else {
LIST_APPEND(pseg->new_objects, obj);
diff --git a/c8/stm/nursery.h b/c8/stm/nursery.h
--- a/c8/stm/nursery.h
+++ b/c8/stm/nursery.h
@@ -5,7 +5,7 @@
static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg,
object_t *obj);
static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
object_t *obj, uint8_t mark_value,
- bool mark_all);
+ bool mark_all, bool really_clear);
static void minor_collection(bool commit);
static void check_nursery_at_transaction_start(void);
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -77,7 +77,7 @@
#define _STM_NSE_SIGNAL_ABORT 1
#define _STM_NSE_SIGNAL_MAX 2
-#define _STM_CARD_MARKED 1
+#define _STM_CARD_MARKED 1 /* should always be 1... */
#define _STM_GCFLAG_CARDS_SET 0x8
#define _STM_CARD_SIZE 32 /* must be >= 32 */
#define _STM_MIN_CARD_COUNT 17
@@ -94,6 +94,7 @@
char *_stm_real_address(object_t *o);
#ifdef STM_TESTS
#include <stdbool.h>
+uint8_t _stm_get_transaction_read_version();
uint8_t _stm_get_card_value(object_t *obj, long idx);
bool _stm_was_read(object_t *obj);
bool _stm_was_written(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
@@ -48,6 +48,7 @@
/*void stm_write_card(); use _checked_stm_write_card() instead */
uint8_t _stm_get_card_value(object_t *obj, long idx);
+uint8_t _stm_get_transaction_read_version();
void stm_setup(void);
void stm_teardown(void);
@@ -401,7 +402,7 @@
CARD_SIZE = lib._STM_CARD_SIZE # 16b at least
CARD_CLEAR = 0
CARD_MARKED = lib._STM_CARD_MARKED
-CARD_MARKED_OLD = CARD_MARKED + 1
+CARD_MARKED_OLD = lib._stm_get_transaction_read_version
class Conflict(Exception):
diff --git a/c8/test/test_card_marking.py b/c8/test/test_card_marking.py
--- a/c8/test/test_card_marking.py
+++ b/c8/test/test_card_marking.py
@@ -235,7 +235,7 @@
assert o in old_objects_with_cards_set()
stm_minor_collect()
- assert get_card_value(o, 1000) == CARD_MARKED_OLD
+ assert get_card_value(o, 1000) == CARD_MARKED_OLD()
self.commit_transaction()
self.start_transaction()
@@ -288,3 +288,43 @@
assert o not in old_objects_with_cards_set()
self.commit_transaction()
+
+ def test_clear_cards4(self):
+ self.start_transaction()
+ o = stm_allocate(1000+20*CARD_SIZE)
+ p = stm_allocate(1000+20*CARD_SIZE)
+ assert get_card_value(o, 1000) == CARD_CLEAR
+ assert get_card_value(p, 1000) == CARD_CLEAR
+
+ self.push_root(o)
+ self.push_root(p)
+ stm_minor_collect()
+ p = self.pop_root()
+ o = self.pop_root()
+
+ assert get_card_value(o, 1000) == CARD_CLEAR
+ assert get_card_value(p, 1000) == CARD_CLEAR
+ stm_set_char(o, 'b', 1000, True)
+ stm_set_char(p, 'b', 1000, True)
+ assert get_card_value(o, 1000) == CARD_MARKED
+ assert get_card_value(p, 1000) == CARD_MARKED
+
+ self.push_root(o)
+ stm_minor_collect()
+ o = self.pop_root()
+
+ assert get_card_value(o, 1000) == CARD_MARKED_OLD()
+ assert get_card_value(p, 1000) == CARD_CLEAR
+
+ self.push_root(o)
+ self.commit_transaction()
+
+ self.start_transaction()
+ o = self.pop_root()
+
+ assert get_card_value(o, 1000) != CARD_CLEAR
+ assert get_card_value(o, 1000) < CARD_MARKED_OLD()
+ stm_set_char(o, 'b', 1000, True)
+ assert get_card_value(o, 1000) == CARD_MARKED
+
+ self.commit_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit