[pypy-commit] stmgc c8-hashtable: Fix. Now test_hashtable seems to pass.
arigo
noreply at buildbot.pypy.org
Thu Mar 12 17:40:47 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: c8-hashtable
Changeset: r1731:0b32167a8194
Date: 2015-03-12 17:41 +0100
http://bitbucket.org/pypy/stmgc/changeset/0b32167a8194/
Log: Fix. Now test_hashtable seems to pass.
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -258,6 +258,14 @@
return stm_object_pages + segment_num * (NB_PAGES * 4096UL);
}
+static inline long get_num_segment_containing_address(char *addr)
+{
+ uintptr_t delta = addr - stm_object_pages;
+ uintptr_t result = delta / (NB_PAGES * 4096UL);
+ assert(result < NB_SEGMENTS);
+ return result;
+}
+
static inline
struct stm_segment_info_s *get_segment(long segment_num) {
return (struct stm_segment_info_s *)REAL_ADDRESS(
diff --git a/c8/stm/hashtable.c b/c8/stm/hashtable.c
--- a/c8/stm/hashtable.c
+++ b/c8/stm/hashtable.c
@@ -148,10 +148,10 @@
static void _stm_rehash_hashtable(stm_hashtable_t *hashtable,
uintptr_t biggercount,
- int remove_unread_from_seg)
+ char *segment_base)
{
- dprintf(("rehash %p to size %ld, remove_unread_from_seg=%d\n",
- hashtable, biggercount, remove_unread_from_seg));
+ dprintf(("rehash %p to size %ld, segment_base=%p\n",
+ hashtable, biggercount, segment_base));
size_t size = (offsetof(stm_hashtable_table_t, items)
+ biggercount * sizeof(stm_hashtable_entry_t *));
@@ -169,12 +169,11 @@
uintptr_t j, mask = table->mask;
uintptr_t rc = biggertable->resize_counter;
- char *segment_base = get_segment_base(remove_unread_from_seg);
for (j = 0; j <= mask; j++) {
stm_hashtable_entry_t *entry = table->items[j];
if (entry == NULL)
continue;
- if (remove_unread_from_seg != 0) {
+ if (segment_base != NULL) {
if (((struct stm_hashtable_entry_s *)
REAL_ADDRESS(segment_base, entry))->object == NULL &&
!_stm_was_read_by_anybody((object_t *)entry)) {
@@ -184,7 +183,7 @@
}
uintptr_t eindex;
- if (remove_unread_from_seg == 0)
+ if (segment_base == NULL)
eindex = entry->index; /* read from STM_SEGMENT */
else
eindex = ((struct stm_hashtable_entry_s *)
@@ -289,7 +288,6 @@
entry->userdata = stm_hashtable_entry_userdata;
entry->index = index;
entry->object = NULL;
- hashtable->additions = STM_SEGMENT->segment_num;
}
else {
/* for a non-nursery 'hashtableobj', we pretend that the
@@ -320,7 +318,7 @@
entry = (stm_hashtable_entry_t *)
stm_allocate_preexisting(sizeof(stm_hashtable_entry_t),
(char *)&initial.header);
- hashtable->additions += 0x100;
+ hashtable->additions++;
}
table->items[i] = entry;
write_fence(); /* make sure 'table->items' is written here */
@@ -335,7 +333,7 @@
biggercount *= 4;
else
biggercount *= 2;
- _stm_rehash_hashtable(hashtable, biggercount, /*remove_unread=*/0);
+ _stm_rehash_hashtable(hashtable, biggercount, /*segment_base=*/NULL);
goto restart;
}
}
@@ -460,16 +458,27 @@
return nresult;
}
-static void _stm_compact_hashtable(stm_hashtable_t *hashtable)
+static void _stm_compact_hashtable(struct object_s *hobj,
+ stm_hashtable_t *hashtable)
{
stm_hashtable_table_t *table = hashtable->table;
uintptr_t rc = table->resize_counter;
assert(!IS_EVEN(rc));
- if ((hashtable->additions >> 8) * 4 > table->mask) {
- int segment_num = (hashtable->additions & 0xFF);
- if (!segment_num) segment_num = 1;
- hashtable->additions = segment_num;
+ if (hashtable->additions * 4 > table->mask) {
+ hashtable->additions = 0;
+
+ /* If 'hobj' was created in some current transaction, i.e. if it is
+ now an overflow object, then we have the risk that some of its
+ entry objects were not created with stm_allocate_preexisting().
+ In that situation, a valid workaround is to read all entry
+ objects in the segment of the running transaction. Otherwise,
+ the base case is to read them all from segment zero.
+ */
+ long segnum = get_num_segment_containing_address((char *)hobj);
+ if (!IS_OVERFLOW_OBJ(get_priv_segment(segnum), hobj))
+ segnum = 0;
+
uintptr_t initial_rc = (table->mask + 1) * 4 + 1;
uintptr_t num_entries_times_6 = initial_rc - rc;
uintptr_t count = INITIAL_HASHTABLE_SIZE;
@@ -480,7 +489,7 @@
assert(count <= table->mask + 1);
dprintf(("compact with %ld items:\n", num_entries_times_6 / 6));
- _stm_rehash_hashtable(hashtable, count, /*remove_unread=*/segment_num);
+ _stm_rehash_hashtable(hashtable, count, get_segment_base(segnum));
}
table = hashtable->table;
@@ -503,10 +512,11 @@
}
}
-void stm_hashtable_tracefn(stm_hashtable_t *hashtable, void trace(object_t **))
+void stm_hashtable_tracefn(struct object_s *hobj, stm_hashtable_t *hashtable,
+ void trace(object_t **))
{
if (trace == TRACE_FOR_MAJOR_COLLECTION)
- _stm_compact_hashtable(hashtable);
+ _stm_compact_hashtable(hobj, hashtable);
stm_hashtable_table_t *table;
table = VOLATILE_HASHTABLE(hashtable)->table;
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -492,7 +492,8 @@
long stm_hashtable_list(object_t *, stm_hashtable_t *,
stm_hashtable_entry_t **results);
extern uint32_t stm_hashtable_entry_userdata;
-void stm_hashtable_tracefn(stm_hashtable_t *, void (object_t **));
+void stm_hashtable_tracefn(struct object_s *, stm_hashtable_t *,
+ void (object_t **));
struct stm_hashtable_entry_s {
struct object_s header;
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -210,7 +210,8 @@
long stm_hashtable_list(object_t *, stm_hashtable_t *,
stm_hashtable_entry_t **results);
uint32_t stm_hashtable_entry_userdata;
-void stm_hashtable_tracefn(stm_hashtable_t *, void (object_t **));
+void stm_hashtable_tracefn(struct object_s *, stm_hashtable_t *,
+ void trace(object_t **));
void _set_hashtable(object_t *obj, stm_hashtable_t *h);
stm_hashtable_t *_get_hashtable(object_t *obj);
@@ -442,7 +443,7 @@
if (myobj->type_id == 421419) {
/* hashtable */
stm_hashtable_t *h = *((stm_hashtable_t **)(myobj + 1));
- stm_hashtable_tracefn(h, visit);
+ stm_hashtable_tracefn(obj, h, visit);
return;
}
if (myobj->type_id == 421418) {
More information about the pypy-commit
mailing list