Author: Armin Rigo <ar...@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) { _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit