Author: Armin Rigo <ar...@tunes.org> Branch: c8-hashtable Changeset: r1713:397c4402e270 Date: 2015-03-10 20:01 +0100 http://bitbucket.org/pypy/stmgc/changeset/397c4402e270/
Log: Add the code from c7 diff --git a/c8/stm/core.h b/c8/stm/core.h --- a/c8/stm/core.h +++ b/c8/stm/core.h @@ -284,6 +284,17 @@ static void _signal_handler(int sig, siginfo_t *siginfo, void *context); static bool _stm_validate(); +static inline bool was_read_remote(char *base, object_t *obj) +{ + uint8_t other_transaction_read_version = + ((struct stm_segment_info_s *)REAL_ADDRESS(base, STM_PSEGMENT)) + ->transaction_read_version; + uint8_t rm = ((struct stm_read_marker_s *) + (base + (((uintptr_t)obj) >> 4)))->rm; + assert(rm <= other_transaction_read_version); + return rm == other_transaction_read_version; +} + static inline void _duck(void) { /* put a call to _duck() between two instructions that set 0 into a %gs-prefixed address and that may otherwise be replaced with diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c --- a/c8/stm/gcpage.c +++ b/c8/stm/gcpage.c @@ -127,6 +127,56 @@ return o; } +static void _fill_preexisting_slice(long segnum, char *dest, + const char *src, uintptr_t size) +{ + uintptr_t np = dest - get_segment_base(segnum); + if (get_page_status_in(segnum, np / 4096) != PAGE_NO_ACCESS) + memcpy(dest, src, size); +} + +object_t *stm_allocate_preexisting(ssize_t size_rounded_up, + const char *initial_data) +{ + stm_char *np = allocate_outside_nursery_large(size_rounded_up); + uintptr_t nobj = (uintptr_t)np; + dprintf(("allocate_preexisting: %p\n", (object_t *)nobj)); + + char *dest = stm_object_pages + nobj; + memcpy(dest, initial_data, size_rounded_up); + ((struct object_s *)dest)->stm_flags = GCFLAG_WRITE_BARRIER; + + acquire_all_privatization_locks(); + + long j; + for (j = 1; j <= NB_SEGMENTS; j++) { + const char *src = initial_data; + char *dest = get_segment_base(j) + nobj; + char *end = dest + size_rounded_up; + + while (((uintptr_t)dest) / 4096 != ((uintptr_t)end - 1) / 4096) { + uintptr_t count = 4096 - ((uintptr_t)dest) / 4096; + _fill_preexisting_slice(j, dest, src, count); + src += count; + dest += count; + } + _fill_preexisting_slice(j, dest, src, end - dest); + +#ifdef STM_TESTS + /* can't really enable this check outside tests, because there is + a change that the transaction_state changes in parallel */ + if (get_priv_segment(j)->transaction_state != TS_NONE) { + assert(!was_read_remote(get_segment_base(j), (object_t *)nobj)); + } +#endif + } + + release_all_privatization_locks(); + + write_fence(); /* make sure 'nobj' is fully initialized from + all threads here */ + return (object_t *)nobj; +} /************************************************************/ diff --git a/c7/stm/hashtable.c b/c8/stm/hashtable.c copy from c7/stm/hashtable.c copy to c8/stm/hashtable.c --- a/c7/stm/hashtable.c +++ b/c8/stm/hashtable.c @@ -110,7 +110,7 @@ /* can only be safely called during major GC, when all other threads are suspended */ long i; - for (i = 1; i <= NB_SEGMENTS; i++) { + for (i = 1; i < NB_SEGMENTS; i++) { if (get_priv_segment(i)->transaction_state == TS_NONE) continue; if (was_read_remote(get_segment_base(i), obj)) diff --git a/c8/stm/misc.c b/c8/stm/misc.c --- a/c8/stm/misc.c +++ b/c8/stm/misc.c @@ -31,10 +31,7 @@ bool _stm_was_read(object_t *obj) { - uint8_t rm = ((struct stm_read_marker_s *) - (STM_SEGMENT->segment_base + (((uintptr_t)obj) >> 4)))->rm; - assert(rm <= STM_SEGMENT->transaction_read_version); - return rm == STM_SEGMENT->transaction_read_version; + return was_read_remote(STM_SEGMENT->segment_base, obj); } bool _stm_was_written(object_t *obj) diff --git a/c8/stmgc.c b/c8/stmgc.c --- a/c8/stmgc.c +++ b/c8/stmgc.c @@ -39,3 +39,4 @@ #include "stm/prof.c" #include "stm/rewind_setjmp.c" #include "stm/finalizer.c" +#include "stm/hashtable.c" diff --git a/c8/stmgc.h b/c8/stmgc.h --- a/c8/stmgc.h +++ b/c8/stmgc.h @@ -467,6 +467,37 @@ /* dummies for now: */ static inline void stm_flush_timing(stm_thread_local_t *tl, int verbose) {} + +/* Hashtables. Keys are 64-bit unsigned integers, values are + 'object_t *'. Note that the type 'stm_hashtable_t' is not an + object type at all; you need to allocate and free it explicitly. + If you want to embed the hashtable inside an 'object_t' you + probably need a light finalizer to do the freeing. */ +typedef struct stm_hashtable_s stm_hashtable_t; +typedef TLPREFIX struct stm_hashtable_entry_s stm_hashtable_entry_t; + +stm_hashtable_t *stm_hashtable_create(void); +void stm_hashtable_free(stm_hashtable_t *); +stm_hashtable_entry_t *stm_hashtable_lookup(object_t *, stm_hashtable_t *, + uintptr_t key); +object_t *stm_hashtable_read(object_t *, stm_hashtable_t *, uintptr_t key); +void stm_hashtable_write(object_t *, stm_hashtable_t *, uintptr_t key, + object_t *nvalue, stm_thread_local_t *); +void stm_hashtable_write_entry(object_t *hobj, stm_hashtable_entry_t *entry, + object_t *nvalue); +long stm_hashtable_length_upper_bound(stm_hashtable_t *); +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 **)); + +struct stm_hashtable_entry_s { + struct object_s header; + uint32_t userdata; + uintptr_t index; + object_t *object; +}; + /* ==================== END ==================== */ static void (*stmcb_expand_marker)(char *segment_base, uintptr_t odd_number, diff --git a/c8/test/support.py b/c8/test/support.py --- a/c8/test/support.py +++ b/c8/test/support.py @@ -197,6 +197,25 @@ void stm_enable_light_finalizer(object_t *); void (*stmcb_finalizer)(object_t *); + +typedef struct stm_hashtable_s stm_hashtable_t; +typedef ... stm_hashtable_entry_t; +stm_hashtable_t *stm_hashtable_create(void); +void stm_hashtable_free(stm_hashtable_t *); +bool _check_hashtable_read(object_t *, stm_hashtable_t *, uintptr_t key); +object_t *hashtable_read_result; +bool _check_hashtable_write(object_t *, stm_hashtable_t *, uintptr_t key, + object_t *nvalue, stm_thread_local_t *tl); +long stm_hashtable_length_upper_bound(stm_hashtable_t *); +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 _set_hashtable(object_t *obj, stm_hashtable_t *h); +stm_hashtable_t *_get_hashtable(object_t *obj); +uintptr_t _get_entry_index(stm_hashtable_entry_t *entry); +object_t *_get_entry_object(stm_hashtable_entry_t *entry); """) @@ -299,6 +318,19 @@ CHECKED(stm_validate()); } +object_t *hashtable_read_result; + +bool _check_hashtable_read(object_t *hobj, stm_hashtable_t *h, uintptr_t key) +{ + CHECKED(hashtable_read_result = stm_hashtable_read(hobj, h, key)); +} + +bool _check_hashtable_write(object_t *hobj, stm_hashtable_t *h, uintptr_t key, + object_t *nvalue, stm_thread_local_t *tl) +{ + CHECKED(stm_hashtable_write(hobj, h, key, nvalue, tl)); +} + #undef CHECKED @@ -326,6 +358,32 @@ return *WEAKREF_PTR(obj, size); } +void _set_hashtable(object_t *obj, stm_hashtable_t *h) +{ + stm_char *field_addr = ((stm_char*)obj); + field_addr += SIZEOF_MYOBJ; /* header */ + *(stm_hashtable_t *TLPREFIX *)field_addr = h; +} + +stm_hashtable_t *_get_hashtable(object_t *obj) +{ + stm_char *field_addr = ((stm_char*)obj); + field_addr += SIZEOF_MYOBJ; /* header */ + return *(stm_hashtable_t *TLPREFIX *)field_addr; +} + +uintptr_t _get_entry_index(stm_hashtable_entry_t *entry) +{ + stm_read((object_t *)entry); + return entry->index; +} + +object_t *_get_entry_object(stm_hashtable_entry_t *entry) +{ + stm_read((object_t *)entry); + return entry->object; +} + void _set_ptr(object_t *obj, int n, object_t *v) { long nrefs = (long)((myobj_t*)obj)->type_id - 421420; @@ -351,11 +409,17 @@ } - ssize_t stmcb_size_rounded_up(struct object_s *obj) { struct myobj_s *myobj = (struct myobj_s*)obj; + assert(myobj->type_id != 0); if (myobj->type_id < 421420) { + if (myobj->type_id == 421419) { /* hashtable */ + return sizeof(struct myobj_s) + 1 * sizeof(void*); + } + if (myobj->type_id == 421418) { /* hashtable entry */ + return sizeof(struct stm_hashtable_entry_s); + } /* basic case: tid equals 42 plus the size of the object */ assert(myobj->type_id >= 42 + sizeof(struct myobj_s)); assert((myobj->type_id - 42) >= 16); @@ -371,11 +435,21 @@ } } - void stmcb_trace(struct object_s *obj, void visit(object_t **)) { int i; struct myobj_s *myobj = (struct myobj_s*)obj; + if (myobj->type_id == 421419) { + /* hashtable */ + stm_hashtable_t *h = *((stm_hashtable_t **)(myobj + 1)); + stm_hashtable_tracefn(h, visit); + return; + } + if (myobj->type_id == 421418) { + /* hashtable entry */ + object_t **ref = &((struct stm_hashtable_entry_s *)myobj)->object; + visit(ref); + } if (myobj->type_id < 421420) { /* basic case: no references */ return; @@ -396,6 +470,7 @@ { int i; struct myobj_s *myobj = (struct myobj_s*)obj; + assert(myobj->type_id != 0); assert(myobj->type_id != 421419); assert(myobj->type_id != 421418); if (myobj->type_id < 421420) { @@ -413,6 +488,9 @@ uintptr_t offset_itemsize[2]) { struct myobj_s *myobj = (struct myobj_s*)obj; + assert(myobj->type_id != 0); + assert(myobj->type_id != 421419); + assert(myobj->type_id != 421418); if (myobj->type_id < 421420) { offset_itemsize[0] = SIZEOF_MYOBJ; offset_itemsize[1] = 1; @@ -467,6 +545,7 @@ CARD_CLEAR = 0 CARD_MARKED = lib._STM_CARD_MARKED CARD_MARKED_OLD = lib._stm_get_transaction_read_version +lib.stm_hashtable_entry_userdata = 421418 class Conflict(Exception): @@ -529,6 +608,18 @@ lib._set_type_id(o, tid) return o +def stm_allocate_hashtable(): + o = lib.stm_allocate(16) + tid = 421419 + lib._set_type_id(o, tid) + h = lib.stm_hashtable_create() + lib._set_hashtable(o, h) + return o + +def get_hashtable(o): + assert lib._get_type_id(o) == 421419 + return lib._get_hashtable(o) + def stm_get_weakref(o): return lib._get_weakref(o) diff --git a/c7/test/test_hashtable.py b/c8/test/test_hashtable.py copy from c7/test/test_hashtable.py copy to c8/test/test_hashtable.py _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit