Author: Remi Meier <[email protected]>
Branch: card-marking
Changeset: r1225:4ccf9352f725
Date: 2014-05-21 18:33 +0200
http://bitbucket.org/pypy/stmgc/changeset/4ccf9352f725/
Log: horrible conversion to 3-state cards (cards get reset too often and
it's generally messy)
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -43,7 +43,18 @@
static void _stm_mark_card(object_t *obj, uintptr_t card_index)
{
assert(card_index > 0);
- dprintf(("mark %p card %lu\n", obj, card_index));
+
+ assert(obj->stm_flags & GCFLAG_HAS_CARDS);
+ assert(!(obj->stm_flags & GCFLAG_SMALL_UNIFORM)); /* not supported/tested
*/
+#ifndef NDEBUG
+ struct object_s *realobj = (struct object_s *)
+ REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+ size_t size = stmcb_size_rounded_up(realobj);
+ assert(size >= 32);
+ /* we need at least one lock in addition to the STM-reserved object
write-lock */
+#endif
+
+ dprintf(("mark %p card %lu with %d\n", obj, card_index, CARD_MARKED));
if (!(obj->stm_flags & GCFLAG_CARDS_SET)) {
/* not yet in the list */
@@ -60,19 +71,18 @@
We already own the object here or it is an overflow obj. */
uintptr_t card_lock_idx = get_write_lock_idx((uintptr_t)obj) + card_index;
- assert(write_locks[card_lock_idx] == 0
- || write_locks[card_lock_idx] == STM_PSEGMENT->write_lock_num);
+ assert(write_locks[get_write_lock_idx((uintptr_t)obj)] == 0 /* overflow
obj */
+ || write_locks[get_write_lock_idx((uintptr_t)obj)] ==
STM_PSEGMENT->write_lock_num);
assert(get_write_lock_idx((uintptr_t)obj) != card_lock_idx);
- if (!write_locks[card_lock_idx])
- write_locks[card_lock_idx] = STM_PSEGMENT->write_lock_num;
+ if (write_locks[card_lock_idx] != CARD_MARKED)
+ write_locks[card_lock_idx] = CARD_MARKED;
}
static bool _stm_write_slowpath_overflow_objs(object_t *obj, uintptr_t
card_index)
{
/* is this an object from the same transaction, outside the nursery? */
- if ((obj->stm_flags & -GCFLAG_OVERFLOW_NUMBER_bit0)
- == STM_PSEGMENT->overflow_number) {
+ if (IS_OVERFLOW_OBJ(STM_PSEGMENT, obj)) {
assert(STM_PSEGMENT->objects_pointing_to_nursery != NULL);
dprintf_test(("write_slowpath %p -> ovf obj_to_nurs\n", obj));
@@ -542,6 +552,7 @@
STM_PSEGMENT->marker_inev[1] = 0;
/* reset these lists to NULL for the next transaction */
+
_verify_cards_cleared_in_all_lists(get_priv_segment(STM_SEGMENT->segment_num));
LIST_FREE(STM_PSEGMENT->objects_pointing_to_nursery);
LIST_FREE(STM_PSEGMENT->old_objects_with_cards);
LIST_FREE(STM_PSEGMENT->large_overflow_objects);
@@ -681,6 +692,10 @@
static void abort_data_structures_from_segment_num(int segment_num)
{
+#pragma push_macro("STM_PSEGMENT")
+#pragma push_macro("STM_SEGMENT")
+#undef STM_PSEGMENT
+#undef STM_SEGMENT
/* This function clears the content of the given segment undergoing
an abort. It is called from abort_with_mutex(), but also sometimes
from other threads that figure out that this segment should abort.
@@ -725,6 +740,8 @@
LIST_FREE(pseg->old_objects_with_cards);
LIST_FREE(pseg->large_overflow_objects);
list_clear(pseg->young_weakrefs);
+#pragma pop_macro("STM_SEGMENT")
+#pragma pop_macro("STM_PSEGMENT")
}
static void abort_with_mutex(void)
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -223,9 +223,19 @@
static uint8_t write_locks[WRITELOCK_END - WRITELOCK_START];
+enum /* card values for write_locks */ {
+ CARD_CLEAR = 0, /* card not used at all */
+ CARD_MARKED = 100, /* card marked for tracing in the next gc */
+ CARD_MARKED_OLD = 101, /* card was marked before, but cleared
+ in a GC */
+};
+
#define REAL_ADDRESS(segment_base, src) ((segment_base) + (uintptr_t)(src))
+#define IS_OVERFLOW_OBJ(pseg, obj) ((obj->stm_flags &
-GCFLAG_OVERFLOW_NUMBER_bit0) \
+ == pseg->overflow_number)
+
static inline uintptr_t get_card_index(uintptr_t byte_offset) {
assert(_STM_CARD_SIZE == 32);
return (byte_offset >> 5) + 1;
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -440,6 +440,11 @@
static void clean_up_segment_lists(void)
{
+#pragma push_macro("STM_PSEGMENT")
+#pragma push_macro("STM_SEGMENT")
+#undef STM_PSEGMENT
+#undef STM_SEGMENT
+
long i;
for (i = 1; i <= NB_SEGMENTS; i++) {
struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
@@ -455,15 +460,28 @@
*/
lst = pseg->objects_pointing_to_nursery;
if (lst != NULL) {
- LIST_FOREACH_R(lst, uintptr_t /*item*/,
+ LIST_FOREACH_R(lst, object_t* /*item*/,
({
struct object_s *realobj = (struct object_s *)
- REAL_ADDRESS(pseg->pub.segment_base, item);
+ REAL_ADDRESS(pseg->pub.segment_base, (uintptr_t)item);
assert(!(realobj->stm_flags & GCFLAG_WRITE_BARRIER));
OPT_ASSERT(!(realobj->stm_flags & GCFLAG_CARDS_SET));
realobj->stm_flags |= GCFLAG_WRITE_BARRIER;
+ /* XXX: this will be necessary when only synchronising
cards */
+
+ if (realobj->stm_flags & GCFLAG_HAS_CARDS) {
+ /* We called a normal WB on these objs. If we wrote
+ a value to some place in them, we need to
+ synchronise the whole object on commit */
+ if (IS_OVERFLOW_OBJ(pseg, realobj)) {
+ /* we do not need the old cards for overflow
objects */
+ _reset_object_cards(pseg, item, CARD_CLEAR, false);
+ } else {
+ _reset_object_cards(pseg, item, CARD_MARKED_OLD,
true); /* mark all */
+ }
+ }
}));
list_clear(lst);
@@ -473,19 +491,19 @@
struct object_s *realobj = (struct object_s *)
REAL_ADDRESS(pseg->pub.segment_base, item);
OPT_ASSERT(realobj->stm_flags & GCFLAG_CARDS_SET);
- _reset_object_cards(&pseg->pub, item);
+ OPT_ASSERT(realobj->stm_flags & GCFLAG_WRITE_BARRIER);
+
+ /* XXX: this will be necessary when only synchronising
cards */
+ uint8_t mark_value = IS_OVERFLOW_OBJ(pseg, realobj) ?
+ CARD_CLEAR : CARD_MARKED_OLD;
+ _reset_object_cards(pseg, item, mark_value, false);
}));
list_clear(lst);
+
} else {
- LIST_FOREACH_R(pseg->modified_old_objects, 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->pub, item);
- }
- });
+ /* if here MINOR_NOTHING_TO_DO() was true before, it's like
+ we "didn't do a collection" at all. So nothing to do on
+ modified_old_objs. */
}
/* Remove from 'large_overflow_objects' all objects that die */
@@ -500,6 +518,8 @@
}
}
}
+#pragma pop_macro("STM_SEGMENT")
+#pragma pop_macro("STM_PSEGMENT")
}
static inline bool largemalloc_keep_object_at(char *data)
@@ -513,6 +533,17 @@
_stm_largemalloc_sweep();
}
+static void assert_cleared_locks(size_t n)
+{
+#ifndef NDEBUG
+ size_t i;
+ uint8_t *s = write_locks;
+ for (i = 0; i < n; i++)
+ assert(s[i] == CARD_CLEAR || s[i] == CARD_MARKED
+ || s[i] == CARD_MARKED_OLD);
+#endif
+}
+
static void clean_write_locks(void)
{
/* the write_locks array, containing the visit marker during
@@ -522,7 +553,7 @@
object_t *loc2 = (object_t *)(uninitialized_page_stop - stm_object_pages);
uintptr_t lock2_idx = mark_loc(loc2 - 1) + 1;
- assert_memset_zero(write_locks, lock2_idx);
+ assert_cleared_locks(lock2_idx);
memset(write_locks + lock2_idx, 0, sizeof(write_locks) - lock2_idx);
}
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -183,30 +183,96 @@
minor_trace_if_young(&tl->thread_local_obj);
}
-static void _reset_object_cards(struct stm_segment_info_s *seg, object_t *obj)
+static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg,
object_t *obj)
+{
+#ifndef NDEBUG
+ struct object_s *realobj = (struct object_s
*)REAL_ADDRESS(pseg->pub.segment_base, obj);
+ size_t size = stmcb_size_rounded_up(realobj);
+
+ if (!(realobj->stm_flags & GCFLAG_HAS_CARDS))
+ return;
+
+ uintptr_t first_card_index = get_write_lock_idx((uintptr_t)obj);
+ uintptr_t card_index = 1;
+ uintptr_t last_card_index = get_card_index(size - 1);
+
+ OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS_MAX
+ || write_locks[first_card_index] == 255); /* see gcpage.c */
+ while (card_index <= last_card_index) {
+ uintptr_t card_lock_idx = first_card_index + card_index;
+ assert(write_locks[card_lock_idx] == CARD_CLEAR);
+ card_index++;
+ }
+
+ assert(!(realobj->stm_flags & GCFLAG_CARDS_SET));
+#endif
+}
+
+static void _verify_cards_cleared_in_all_lists(struct stm_priv_segment_info_s
*pseg)
+{
+#ifndef NDEBUG
+ LIST_FOREACH_R(
+ pseg->modified_old_objects, object_t * /*item*/,
+ _cards_cleared_in_object(pseg, item));
+
+ if (pseg->large_overflow_objects) {
+ LIST_FOREACH_R(
+ pseg->large_overflow_objects, object_t * /*item*/,
+ _cards_cleared_in_object(pseg, item));
+ }
+ if (pseg->objects_pointing_to_nursery) {
+ LIST_FOREACH_R(
+ pseg->objects_pointing_to_nursery, object_t * /*item*/,
+ _cards_cleared_in_object(pseg, item));
+ }
+ if (pseg->old_objects_with_cards) {
+ LIST_FOREACH_R(
+ pseg->old_objects_with_cards, object_t * /*item*/,
+ _cards_cleared_in_object(pseg, item));
+ }
+#endif
+}
+
+static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
+ object_t *obj, uint8_t mark_value,
+ bool mark_all)
{
#pragma push_macro("STM_PSEGMENT")
#pragma push_macro("STM_SEGMENT")
#undef STM_PSEGMENT
#undef STM_SEGMENT
- struct object_s *realobj = (struct object_s
*)REAL_ADDRESS(seg->segment_base, obj);
+ 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 >= 32);
+ assert(realobj->stm_flags & GCFLAG_HAS_CARDS);
+ 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(IS_OVERFLOW_OBJ(pseg, realobj),
+ mark_value == CARD_CLEAR)); /* overflows are always CLEARed */
+
uintptr_t first_card_index = get_write_lock_idx((uintptr_t)obj);
uintptr_t card_index = 1;
uintptr_t last_card_index = get_card_index(size - 1);
+ dprintf(("mark cards of %p, size %lu with %d\n", obj, size, mark_value));
+
+ OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS
+ || write_locks[first_card_index] == 255); /* see gcpage.c */
while (card_index <= last_card_index) {
- #ifndef NDEBUG
- if (write_locks[first_card_index + card_index])
- dprintf(("cleared card %lu on %p\n", card_index, obj));
- #endif
- write_locks[first_card_index + card_index] = 0;
+ uintptr_t card_lock_idx = first_card_index + card_index;
+
+ if (mark_all || write_locks[card_lock_idx] != CARD_CLEAR) {
+ /* dprintf(("mark card %lu,wl:%lu of %p with %d\n", */
+ /* card_index, card_lock_idx, obj, mark_value)); */
+ write_locks[card_lock_idx] = mark_value;
+ }
card_index++;
}
+ OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS
+ || write_locks[first_card_index] == 255); /* see gcpage.c */
realobj->stm_flags &= ~GCFLAG_CARDS_SET;
- dprintf(("reset cards on %p\n", obj));
#pragma pop_macro("STM_SEGMENT")
#pragma pop_macro("STM_PSEGMENT")
}
@@ -218,11 +284,10 @@
also gives the obj-base */
assert(_card_base_obj);
uintptr_t base_lock_idx = get_write_lock_idx((uintptr_t)_card_base_obj);
- uintptr_t card_lock_idx = base_lock_idx;
- card_lock_idx += get_card_index(
+ uintptr_t card_lock_idx = base_lock_idx + get_card_index(
(uintptr_t)((char*)pobj - STM_SEGMENT->segment_base) -
(uintptr_t)_card_base_obj);
- if (write_locks[card_lock_idx]) {
+ if (write_locks[card_lock_idx] == CARD_MARKED) {
dprintf(("minor_trace_if_young_cards: trace %p\n", *pobj));
minor_trace_if_young(pobj);
}
@@ -234,13 +299,17 @@
_card_base_obj = obj;
assert(!_is_in_nursery(obj));
assert(obj->stm_flags & GCFLAG_CARDS_SET);
+ assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
dprintf(("_trace_card_object(%p)\n", obj));
char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
stmcb_trace((struct object_s *)realobj, &minor_trace_if_young_cards);
- _reset_object_cards(get_segment(STM_SEGMENT->segment_num), obj);
+ bool obj_is_overflow = IS_OVERFLOW_OBJ(STM_PSEGMENT, obj);
+ uint8_t mark_value = obj_is_overflow ? CARD_CLEAR : CARD_MARKED_OLD;
+ _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+ obj, mark_value, false); /* mark marked */
}
@@ -259,8 +328,15 @@
stmcb_trace((struct object_s *)realobj, &minor_trace_if_young);
obj->stm_flags |= GCFLAG_WRITE_BARRIER;
- if (obj->stm_flags & GCFLAG_CARDS_SET) {
- _reset_object_cards(get_segment(STM_SEGMENT->segment_num), obj);
+ if (obj->stm_flags & GCFLAG_HAS_CARDS) {
+ if (IS_OVERFLOW_OBJ(STM_PSEGMENT, obj)) {
+ /* we do not need the old cards for overflow objects */
+ _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+ obj, CARD_CLEAR, false);
+ } else {
+ _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+ obj, CARD_MARKED_OLD, true); /* mark all */
+ }
}
} if (obj->stm_flags & GCFLAG_CARDS_SET) {
_trace_card_object(obj);
@@ -298,13 +374,18 @@
WRITE_BARRIER flag and traced into it to fix its
content); or add the object to 'large_overflow_objects'.
*/
+ struct stm_priv_segment_info_s *pseg =
get_priv_segment(STM_SEGMENT->segment_num);
if (STM_PSEGMENT->minor_collect_will_commit_now) {
acquire_privatization_lock();
synchronize_object_now(obj);
release_privatization_lock();
+ if (obj->stm_flags & GCFLAG_HAS_CARDS) {
+ _reset_object_cards(pseg, obj, CARD_CLEAR, false); /* was
young */
+ }
} else {
LIST_APPEND(STM_PSEGMENT->large_overflow_objects, obj);
}
+ _cards_cleared_in_object(pseg, obj);
}
/* the list could have moved while appending */
@@ -368,7 +449,15 @@
wlog_t *item;
TREE_LOOP_FORWARD(*pseg->young_outside_nursery, item) {
- assert(!_is_in_nursery((object_t *)item->addr));
+ object_t *obj = (object_t*)item->addr;
+ struct object_s *realobj = (struct object_s *)
+ REAL_ADDRESS(pseg->pub.segment_base, item->addr);
+
+ assert(!_is_in_nursery(obj));
+ if (realobj->stm_flags & GCFLAG_HAS_CARDS)
+ _reset_object_cards(pseg, obj, CARD_CLEAR, false);
+ _cards_cleared_in_object(pseg, obj);
+
_stm_large_free(stm_object_pages + item->addr);
} TREE_LOOP_END;
@@ -377,21 +466,37 @@
tree_clear(pseg->nursery_objects_shadows);
- if (pseg->old_objects_with_cards) {
- LIST_FOREACH_R(pseg->old_objects_with_cards, object_t * /*item*/,
- _reset_object_cards(&pseg->pub, item));
- } else {
- LIST_FOREACH_R(pseg->modified_old_objects, 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->pub, item);
- }
- });
+ /* nearly all objs in old_objects_with_cards are also in
modified_old_objects,
+ so we don't need to go through both lists: */
+ LIST_FOREACH_R(pseg->modified_old_objects, object_t * /*item*/,
+ {
+ struct object_s *realobj = (struct object_s *)
+ REAL_ADDRESS(pseg->pub.segment_base, item);
+
+ if (realobj->stm_flags & GCFLAG_HAS_CARDS) {
+ /* clear all possibly used cards in this transaction */
+ _reset_object_cards(pseg, item, CARD_CLEAR, false);
+ }
+ });
+ /* overflow objects with cards are not in modified_old_objects */
+ if (pseg->large_overflow_objects != NULL) {
+ /* some overflow objects may have cards, clear them too */
+ LIST_FOREACH_R(pseg->large_overflow_objects, object_t * /*item*/,
+ {
+ struct object_s *realobj = (struct object_s *)
+ REAL_ADDRESS(pseg->pub.segment_base, item);
+
+ if (realobj->stm_flags & GCFLAG_CARDS_SET) {
+ /* CARDS_SET is enough since other HAS_CARDS objs
+ are already cleared */
+ _reset_object_cards(pseg, item, CARD_CLEAR, false);
+ }
+ });
}
+ _verify_cards_cleared_in_all_lists(pseg);
+
return nursery_used;
#pragma pop_macro("STM_SEGMENT")
#pragma pop_macro("STM_PSEGMENT")
diff --git a/c7/stm/nursery.h b/c7/stm/nursery.h
--- a/c7/stm/nursery.h
+++ b/c7/stm/nursery.h
@@ -6,7 +6,9 @@
static uint32_t highest_overflow_number;
-static void _reset_object_cards(struct stm_segment_info_s *seg, 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);
static void minor_collection(bool commit);
static void check_nursery_at_transaction_start(void);
static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg);
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -271,7 +271,9 @@
/* 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. */
+ conflict detection and garbage collection.
+ These objects need to be at least 32bytes in size!
+*/
__attribute__((always_inline))
static inline void stm_use_cards(object_t* o)
{
diff --git a/c7/test/test_random.py b/c7/test/test_random.py
--- a/c7/test/test_random.py
+++ b/c7/test/test_random.py
@@ -227,14 +227,19 @@
self.root_numbering = 0
self.ref_type_map = {}
self.root_sizes = {}
+ self.with_cards = {}
- def get_new_root_name(self, is_ref_type, size):
+ def get_new_root_name(self, is_ref_type, size, with_cards):
self.root_numbering += 1
r = "lp_%s_%d" % ("ref" if is_ref_type else "char",
self.root_numbering)
self.ref_type_map[r] = is_ref_type
self.root_sizes[r] = size
+ self.with_cards[r] = with_cards
return r
+ def has_cards(self, r):
+ return self.with_cards[r]
+
def has_ref_type(self, r):
return self.ref_type_map[r]
@@ -363,10 +368,11 @@
#"SOME_MEDIUM_SIZE+16",
#"SOME_LARGE_SIZE+16",
])
- r = global_state.get_new_root_name(False, size)
+ with_cards = int(size) >= 32
+ r = global_state.get_new_root_name(False, size, with_cards)
thread_state.push_roots(ex)
- ex.do('%s = stm_allocate(%s)' % (r, size))
+ ex.do('%s = stm_allocate(%s, %s)' % (r, size, bool(with_cards)))
ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r]))))
thread_state.transaction_state.add_root(r, 0, True)
@@ -376,9 +382,10 @@
def op_allocate_ref(ex, global_state, thread_state):
num = str(global_state.rnd.randrange(1, 100))
- r = global_state.get_new_root_name(True, num)
+ with_cards = int(num) >= 4
+ r = global_state.get_new_root_name(True, num, with_cards)
thread_state.push_roots(ex)
- ex.do('%s = stm_allocate_refs(%s, True)' % (r, num))
+ ex.do('%s = stm_allocate_refs(%s, %s)' % (r, num, bool(with_cards)))
ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r]))))
thread_state.transaction_state.add_root(r, "ffi.NULL", True)
@@ -410,6 +417,7 @@
r = thread_state.get_random_root()
trs = thread_state.transaction_state
is_ref = global_state.has_ref_type(r)
+ has_cards = global_state.has_cards(r)
#
# check for possible write-write conflict:
was_written = False
@@ -438,13 +446,13 @@
thread_state.abort_transaction()
offset = global_state.get_root_size(r) + " - 1"
if is_ref:
- ex.do(raising_call(aborts, "stm_set_ref", r, offset, v, "True"))
+ ex.do(raising_call(aborts, "stm_set_ref", r, offset, v, has_cards))
if not aborts:
- ex.do(raising_call(False, "stm_set_ref", r, "0", v, "True"))
+ ex.do(raising_call(False, "stm_set_ref", r, "0", v, has_cards))
else:
- ex.do(raising_call(aborts, "stm_set_char", r, repr(chr(v)), offset))
+ ex.do(raising_call(aborts, "stm_set_char", r, repr(chr(v)), offset,
has_cards))
if not aborts:
- ex.do(raising_call(False, "stm_set_char", r, repr(chr(v)), "HDR"))
+ ex.do(raising_call(False, "stm_set_char", r, repr(chr(v)), "HDR",
has_cards))
def op_read(ex, global_state, thread_state):
r = thread_state.get_random_root()
@@ -556,12 +564,12 @@
curr_thread = global_state.thread_states[0]
for i in range(N_OBJECTS):
- r = global_state.get_new_root_name(False, "384")
- ex.do('%s = stm_allocate_old(384)' % r)
+ r = global_state.get_new_root_name(False, "384", True)
+ ex.do('%s = stm_allocate_old(384, True)' % r)
global_state.committed_transaction_state.add_root(r, 0, False)
global_state.prebuilt_roots.append(r)
- r = global_state.get_new_root_name(True, "50")
+ r = global_state.get_new_root_name(True, "50", True)
ex.do('%s = stm_allocate_old_refs(50, True)' % r)
global_state.committed_transaction_state.add_root(r, "ffi.NULL",
False)
global_state.prebuilt_roots.append(r)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit