Author: Remi Meier <[email protected]>
Branch: c8-card-marking
Changeset: r1682:133dcfae5ec0
Date: 2015-02-27 21:51 +0100
http://bitbucket.org/pypy/stmgc/changeset/133dcfae5ec0/
Log: more fixes
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -658,12 +658,7 @@
/* get whole card range */
struct object_s *realobj = (struct
object_s*)REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
size_t obj_size = stmcb_size_rounded_up(realobj);
-
- uintptr_t offset_itemsize[2];
- if (index != -1) {
- /* don't call if index==-1 as callback may not be supported at all */
- stmcb_get_card_base_itemsize(realobj, offset_itemsize);
- }
+ uintptr_t offset_itemsize[2] = {-1, -1};
/* decide where to start copying: */
size_t start_offset;
@@ -682,17 +677,20 @@
(stm_char*)obj + obj_size);
} else {
/* only fixed part */
+ stmcb_get_card_base_itemsize(realobj, offset_itemsize);
make_bk_slices_for_range(obj, (stm_char*)obj + start_offset,
(stm_char*)obj + offset_itemsize[0]);
}
return;
}
+ stmcb_get_card_base_itemsize(realobj, offset_itemsize);
+
size_t real_idx_count = (obj_size - offset_itemsize[0]) /
offset_itemsize[1];
assert(IMPLY(index != -1 && index != -2, index >= 0 && index <
real_idx_count));
struct stm_read_marker_s *cards =
get_read_marker(STM_SEGMENT->segment_base, (uintptr_t)obj);
uintptr_t last_card_index = get_index_to_card_index(real_idx_count - 1);
/* max valid index */
-
+ uintptr_t card_index;
/* decide if we want only a specific card: */
if (index != -1) {
@@ -702,13 +700,16 @@
(stm_char*)obj + offset_itemsize[0]);
}
- size_t after_card_offset = offset_itemsize[0] + (index + 1) *
offset_itemsize[1];
+ card_index = get_index_to_card_index(index);
+ size_t card_offset = offset_itemsize[0]
+ + get_card_index_to_index(card_index) * offset_itemsize[1];
+ size_t after_card_offset = offset_itemsize[0]
+ + get_card_index_to_index(card_index + 1) * offset_itemsize[1];
if (after_card_offset > obj_size)
after_card_offset = obj_size;
make_bk_slices_for_range(
- obj, (stm_char*)obj + offset_itemsize[0] + index *
offset_itemsize[1],
- (stm_char*)obj + after_card_offset);
+ obj, (stm_char*)obj + card_offset, (stm_char*)obj +
after_card_offset);
return;
}
@@ -716,7 +717,7 @@
/* look for CARD_CLEAR or some non-transaction_read_version cards
and make bk slices for them */
assert(do_missing_cards && index == -1 && start_offset == -1);
- uintptr_t card_index = 1;
+ card_index = 1;
uintptr_t start_card_index = -1;
while (card_index <= last_card_index) {
uint8_t card_value = cards[card_index].rm;
@@ -728,13 +729,13 @@
if (start_card_index == -1) { /* first unmarked card */
start_card_index = card_index;
}
- }
- else {
+ } else {
/* "CARD_MARKED_OLD" or CARD_MARKED */
OPT_ASSERT(card_value == STM_SEGMENT->transaction_read_version
|| card_value == CARD_MARKED);
- /* we don't need the cards anymore after executing this function */
- cards[card_index].rm = CARD_CLEAR;
+ /* we don't need CARD_MARKED anymore after executing this function,
+ but we may still need to avoid creating bk copies in the
future: */
+ cards[card_index].rm = STM_SEGMENT->transaction_read_version;
}
if (start_card_index != -1 /* something to copy */
@@ -780,7 +781,7 @@
}
obj->stm_flags &= ~GCFLAG_CARDS_SET;
- _cards_cleared_in_object(get_priv_segment(STM_SEGMENT->segment_num), obj);
+ _cards_cleared_in_object(get_priv_segment(STM_SEGMENT->segment_num), obj,
false);
}
__attribute__((always_inline))
@@ -835,6 +836,37 @@
/* add to read set: */
stm_read(obj);
+ if (!(obj->stm_flags & GCFLAG_WB_EXECUTED)) {
+ /* the first time we write this obj, make sure it is fully
+ accessible, as major gc may depend on being able to trace
+ the full obj in this segment (XXX) */
+ char *realobj;
+ size_t obj_size;
+ int my_segnum = STM_SEGMENT->segment_num;
+ uintptr_t end_page, first_page = ((uintptr_t)obj) / 4096UL;
+
+ realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+ obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
+ /* get the last page containing data from the object */
+ if (LIKELY(is_small_uniform(obj))) {
+ end_page = first_page;
+ } else {
+ end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
+ }
+
+ acquire_privatization_lock(STM_SEGMENT->segment_num);
+ uintptr_t page;
+ for (page = first_page; page <= end_page; page++) {
+ if (get_page_status_in(my_segnum, page) == PAGE_NO_ACCESS) {
+ release_privatization_lock(STM_SEGMENT->segment_num);
+ volatile char *dummy = REAL_ADDRESS(STM_SEGMENT->segment_base,
page * 4096UL);
+ *dummy; /* force segfault */
+ acquire_privatization_lock(STM_SEGMENT->segment_num);
+ }
+ }
+ release_privatization_lock(STM_SEGMENT->segment_num);
+ }
+
if (mark_card) {
if (!(obj->stm_flags & GCFLAG_WB_EXECUTED)) {
make_bk_slices(obj,
@@ -894,14 +926,6 @@
return mark_card;
}
-long _stm_write_slowpath_card_extra_base(void)
-{
- /* XXX can go away? */
- /* for the PyPy JIT: _stm_write_slowpath_card_extra_base[obj >> 4]
- is the byte that must be set to CARD_MARKED. The logic below
- does the same, but more explicitly. */
- return 0;
-}
void _stm_write_slowpath_card(object_t *obj, uintptr_t index)
{
@@ -1278,10 +1302,9 @@
/* clear CARD_MARKED on objs (don't care about CARD_MARKED_OLD) */
LIST_FOREACH_R(pseg->old_objects_with_cards_set, object_t * /*item*/,
{
- struct object_s *realobj = (struct object_s *)
- REAL_ADDRESS(pseg->pub.segment_base, item);
- if (realobj->stm_flags & GCFLAG_CARDS_SET)
- _reset_object_cards(pseg, item, CARD_CLEAR, false, false);
+ /* CARDS_SET may have already been lost because stm_validate()
+ may call reset_modified_from_backup_copies() */
+ _reset_object_cards(pseg, item, CARD_CLEAR, false, false);
});
acquire_modification_lock(segment_num);
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -142,10 +142,11 @@
/* Must trace the object later */
LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now);
- _cards_cleared_in_object(get_priv_segment(STM_SEGMENT->segment_num), nobj);
+ _cards_cleared_in_object(get_priv_segment(STM_SEGMENT->segment_num), nobj,
true);
}
-static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg,
object_t *obj)
+static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg,
object_t *obj,
+ bool strict) /* strict = MARKED_OLD not
allowed */
{
#ifndef NDEBUG
struct object_s *realobj = (struct object_s
*)REAL_ADDRESS(pseg->pub.segment_base, obj);
@@ -154,17 +155,25 @@
if (size < _STM_MIN_CARD_OBJ_SIZE)
return; /* too small for cards */
+ assert(!(realobj->stm_flags & GCFLAG_CARDS_SET));
+
+ if (!stmcb_obj_supports_cards(realobj))
+ return;
+
+ uintptr_t offset_itemsize[2] = {0, 0};
+ stmcb_get_card_base_itemsize(realobj, offset_itemsize);
struct stm_read_marker_s *cards = get_read_marker(pseg->pub.segment_base,
(uintptr_t)obj);
uintptr_t card_index = 1;
- uintptr_t last_card_index = get_index_to_card_index(size - 1); /* max
valid index */
+ size_t real_idx_count = (size - offset_itemsize[0]) / offset_itemsize[1];
+ uintptr_t last_card_index = get_index_to_card_index(real_idx_count - 1);
/* max valid index */
while (card_index <= last_card_index) {
assert(cards[card_index].rm == CARD_CLEAR
- || cards[card_index].rm < pseg->pub.transaction_read_version);
+ || (cards[card_index].rm != CARD_MARKED
+ && cards[card_index].rm <
pseg->pub.transaction_read_version)
+ || (!strict && cards[card_index].rm != CARD_MARKED));
card_index++;
}
-
- assert(!(realobj->stm_flags & GCFLAG_CARDS_SET));
#endif
}
@@ -176,17 +185,17 @@
struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
for (; undo < end; undo++) {
- _cards_cleared_in_object(pseg, undo->object);
+ _cards_cleared_in_object(pseg, undo->object, false);
}
LIST_FOREACH_R(
pseg->large_overflow_objects, object_t * /*item*/,
- _cards_cleared_in_object(pseg, item));
+ _cards_cleared_in_object(pseg, item, false));
LIST_FOREACH_R(
pseg->objects_pointing_to_nursery, object_t * /*item*/,
- _cards_cleared_in_object(pseg, item));
+ _cards_cleared_in_object(pseg, item, false));
LIST_FOREACH_R(
pseg->old_objects_with_cards_set, object_t * /*item*/,
- _cards_cleared_in_object(pseg, item));
+ _cards_cleared_in_object(pseg, item, false));
#endif
}
@@ -198,6 +207,8 @@
#pragma push_macro("STM_SEGMENT")
#undef STM_PSEGMENT
#undef STM_SEGMENT
+ dprintf(("_reset_object_cards(%p, mark=%d, mark_all=%d,
really_clear=%d)\n",
+ obj, mark_value, mark_all, really_clear));
struct object_s *realobj = (struct object_s
*)REAL_ADDRESS(pseg->pub.segment_base, obj);
size_t size = stmcb_size_rounded_up(realobj);
OPT_ASSERT(size >= _STM_MIN_CARD_OBJ_SIZE);
@@ -351,7 +362,7 @@
} else {
LIST_APPEND(STM_PSEGMENT->large_overflow_objects, obj);
}
- _cards_cleared_in_object(pseg, obj);
+ _cards_cleared_in_object(pseg, obj, false);
}
/* the list could have moved while appending */
diff --git a/c8/stm/nursery.h b/c8/stm/nursery.h
--- a/c8/stm/nursery.h
+++ b/c8/stm/nursery.h
@@ -4,7 +4,8 @@
static uint32_t highest_overflow_number;
-static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg,
object_t *obj);
+static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg,
object_t *obj,
+ bool strict);
static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
object_t *obj, uint8_t mark_value,
bool mark_all, bool really_clear);
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -85,6 +85,7 @@
void _stm_write_slowpath(object_t *);
void _stm_write_slowpath_card(object_t *, uintptr_t);
+char _stm_write_slowpath_card_extra(object_t *);
object_t *_stm_allocate_slowpath(ssize_t);
object_t *_stm_allocate_external(ssize_t);
void _stm_become_inevitable(const char*);
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
@@ -329,3 +329,15 @@
assert get_card_value(o, 1000) == CARD_MARKED
self.commit_transaction()
+
+ def test_card_marked_old(self):
+ o = stm_allocate_old(1000+20*CARD_SIZE)
+ self.start_transaction()
+ stm_set_char(o, 'x', HDR, True)
+ stm_set_char(o, 'u', HDR, False)
+ stm_minor_collect()
+ stm_set_char(o, 'y', HDR, True)
+ self.abort_transaction()
+
+ self.start_transaction()
+ assert stm_get_char(o, HDR) == '\0'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit