[pypy-commit] stmgc default: first random-test version in C. may have some bugs..
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r195:bbf01c89fe52 Date: 2013-06-19 14:32 +0200 http://bitbucket.org/pypy/stmgc/changeset/bbf01c89fe52/ Log:first random-test version in C. may have some bugs.. diff --git a/c4/demo_random.c b/c4/demo_random.c new file mode 100644 --- /dev/null +++ b/c4/demo_random.c @@ -0,0 +1,316 @@ +#include stdlib.h +#include stdio.h +#include assert.h +#include pthread.h +#include semaphore.h +#include time.h + +#include stmgc.h +#include fprintcolor.h + + +#define NUMTHREADS 4 +#define STEPS 10 +#define NUMROOTS 10 +#define PREBUILT 3 +#define MAXROOTS 1000 +#define SHARED_ROOTS 5 + + +// SUPPORT +#define GCTID_STRUCT_ROOT 123 + +struct root { +struct stm_object_s hdr; +long value; +struct root *next; +}; +typedef struct root * rootptr; + +size_t stmcb_size(gcptr ob) +{ +assert(stm_get_tid(ob) == GCTID_STRUCT_ROOT); +return sizeof(struct root); +} +void stmcb_trace(gcptr ob, void visit(gcptr *)) +{ +rootptr n; +assert(stm_get_tid(ob) == GCTID_STRUCT_ROOT); +n = (rootptr)ob; +visit((gcptr *)n-next); +} + +// global and per-thread-data +time_t default_seed; +gcptr shared_roots[SHARED_ROOTS]; +__thread unsigned int thread_seed = 0; +__thread gcptr roots[MAXROOTS]; +__thread gcptr roots_outside_perform[MAXROOTS]; +__thread gcptr current_root = 0; +__thread int num_roots = 0; +__thread int num_roots_outside_perform = 0; +__thread int steps_left; +__thread int interruptible = 0; + + +// helper functions +int get_rand(int max) +{ +return (int)(rand_r(thread_seed) % (unsigned int)max); +} + +void copy_roots(gcptr *from, gcptr *to) +{ +int i; +for (i = 0; i num_roots; i++) +*(to++) = *(from++); +} + +gcptr allocate_pseudoprebuilt(size_t size, int tid) +{ +gcptr x = calloc(1, size); +x-h_tid = PREBUILT_FLAGS | tid; +x-h_revision = PREBUILT_REVISION; +return x; +} + +void push_roots() +{ +int i; +for (i = 0; i num_roots; i++) +stm_push_root(roots[i]); +} + +void pop_roots() +{ +int i; +for (i = num_roots - 1; i = 0; i--) +roots[i] = stm_pop_root(); +} + +void del_root(int idx) +{ +int i; +for (i = idx; i num_roots - 1; i++) +roots[i] = roots[i + 1]; +} + +gcptr allocate_root(size_t size, int tid) +{ +gcptr r; +push_roots(); +r = stm_allocate(size, tid); +pop_roots(); +return r; +} + + + +// THREAD TESTER +int interruptible_callback(gcptr arg1, int retry_counter); +int run_me(); +void transaction_break(); + +void setup_thread() +{ +int i; +thread_seed = default_seed; +steps_left = STEPS; +interruptible = 0; + +num_roots = PREBUILT + NUMROOTS; +for (i = 0; i PREBUILT; i++) { +roots[i] = allocate_pseudoprebuilt(sizeof(struct root), + GCTID_STRUCT_ROOT); +} +for (i = PREBUILT; i PREBUILT + NUMROOTS; i++) { +roots[i] = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); +} + +} + +gcptr do_step(gcptr p) +{ +fprintf(stdout, #); + +rootptr w_r, w_sr; +gcptr _r, _sr; +int num, k; + +num = get_rand(num_roots); +_r = roots[num]; + +num = get_rand(SHARED_ROOTS); +_sr = shared_roots[num]; + +k = get_rand(14); + +if (!p) // some parts expect it to be != 0 +p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); + +switch (k) { +case 0: // remove a root +if (num 0) +del_root(num); +break; +case 1: // set 'p' to point to a root +if (_r) +p = _r; +break; +case 2: // add 'p' to roots +if (num_roots MAXROOTS) +roots[num_roots++] = p; +break; +case 3: // allocate fresh 'p' +p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); +break; +case 4: // set 'p' as *next in one of the roots +w_r = (rootptr)stm_write_barrier(_r); +// XXX: do I have to read_barrier(p)? +w_r-next = (struct root*)p; +break; +case 5: // read and validate 'p' +stm_read_barrier(p); +break; +case 6: // transaction break +if (interruptible) +return -1; // break current +transaction_break(); +p = NULL; +break; +case 7: // only do a stm_write_barrier +p = stm_write_barrier(p); +break; +case 8: +p = (gcptr)(((rootptr)stm_read_barrier(p))-next); +break; +case 9: // XXX: rare events +break; +case 10: // only do a stm_read_barrier +p = stm_read_barrier(p); +break; +case 11: +stm_read_barrier(_sr); +break; +case 12: +stm_write_barrier(_sr); +break; +case 13: +w_sr = stm_write_barrier(_sr); +w_sr-next = shared_roots[get_rand(SHARED_ROOTS)]; +default: +break; +} +return p; +} + + +void transaction_break() +{ +push_roots(); +
[pypy-commit] stmgc default: add demo2 (bubble sort)
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r194:716b7629c9cd Date: 2013-06-19 11:20 +0200 http://bitbucket.org/pypy/stmgc/changeset/716b7629c9cd/ Log:add demo2 (bubble sort) diff --git a/c4/demo2.c b/c4/demo2.c new file mode 100644 --- /dev/null +++ b/c4/demo2.c @@ -0,0 +1,218 @@ +#include stdlib.h +#include stdio.h +#include assert.h +#include pthread.h +#include semaphore.h + +#include stmgc.h +#include fprintcolor.h + + +#define LIST_LENGTH 500 +#define NUMTHREADS 4 + + +#define GCTID_STRUCT_NODE 123 + +struct node { +struct stm_object_s hdr; +long value; +struct node *next; +}; +typedef struct node * nodeptr; + +size_t stmcb_size(gcptr ob) +{ +assert(stm_get_tid(ob) == GCTID_STRUCT_NODE); +return sizeof(struct node); +} + +void stmcb_trace(gcptr ob, void visit(gcptr *)) +{ +nodeptr n; +assert(stm_get_tid(ob) == GCTID_STRUCT_NODE); +n = (nodeptr)ob; +visit((gcptr *)n-next); +} + + +struct node global_chained_list = { +{ GCTID_STRUCT_NODE | PREBUILT_FLAGS, PREBUILT_REVISION }, +-1, +NULL, +}; + + +long check_sorted() +{ +nodeptr r_n; +long prev, sum; +r_n = (nodeptr)stm_read_barrier((gcptr)global_chained_list); +assert(r_n-value == -1); + +prev = -1; +sum = 0; +while (r_n-next) { +r_n = (nodeptr)stm_read_barrier((gcptr)r_n-next); +sum += r_n-value; + +if (prev = r_n-value) +return -1; + +prev = r_n-value; +} + +return sum; +} + +void swap_nodes(nodeptr prev, nodeptr current, nodeptr next) +{ +nodeptr w_prev, w_current, w_next; +w_prev = (nodeptr)stm_write_barrier((gcptr)prev); +w_current = (nodeptr)stm_write_barrier((gcptr)current); +w_next = (nodeptr)stm_write_barrier((gcptr)next); + +w_prev-next = w_next; +w_current-next = w_next-next; +w_next-next = w_current; +} + +int bubble_run(gcptr arg1, int retry_counter) +{ +nodeptr r_prev, r_current, r_next, tmp; + +r_prev = (nodeptr)stm_read_barrier(arg1); +r_current = (nodeptr)stm_read_barrier((gcptr)r_prev-next); +r_next = (nodeptr)stm_read_barrier((gcptr)r_current-next); + +while (r_next) { +if (r_next-value r_current-value) { +// swap current and next +swap_nodes(r_prev, r_current, r_next); +fprintf(stdout, #); + +// needs read barriers, because of write barriers in swap_nodes +r_prev = (struct node*)stm_read_barrier((gcptr)r_prev); +tmp = r_current; +r_current = (struct node*)stm_read_barrier((gcptr)r_next); +r_next = (struct node*)stm_read_barrier((gcptr)tmp); +} +// results from consecutive read_barriers can differ. needs Ptr_Eq() +/* assert(stm_read_barrier((gcptr)r_prev-next) == r_current */ +/* stm_read_barrier((gcptr)r_current-next) == r_next); */ +// for now: +assert(((nodeptr)stm_read_barrier((gcptr)r_prev-next))-value + == r_current-value + + ((nodeptr)stm_read_barrier((gcptr)r_current-next))-value + == r_next-value); + +r_prev = r_current; +r_current = r_next; +r_next = r_next-next; +if (r_next != NULL) +r_next = (nodeptr)stm_read_barrier((gcptr)r_next); +} + + +return 0; +} + + +static sem_t done; + +static int thr_mynum = 0; + +void *demo2(void *arg) +{ + +int status; +stm_initialize(); + +thr_mynum++; /* protected by being inevitable here */ +fprintf(stderr, THREAD STARTING\n); + + +while (check_sorted() == -1) { +stm_perform_transaction((gcptr)global_chained_list, bubble_run); +} + +stm_finalize(); + +status = sem_post(done); +assert(status == 0); +return NULL; +} + +void final_check(void) +{ +long sum; + +stm_initialize(); + +sum = check_sorted(); + +// little Gauss: +assert(sum == (1 + LIST_LENGTH) * (LIST_LENGTH / 2)); + +stm_finalize(); +printf(check ok\n); +} + + +void newthread(void*(*func)(void*), void *arg) +{ +pthread_t th; +int status = pthread_create(th, NULL, func, arg); +assert(status == 0); +pthread_detach(th); +printf(started new thread\n); +} + + +/* initialize list with values in decreasing order */ +void setup_list() +{ +int i; +nodeptr w_newnode, w_prev; +stm_initialize(); + +w_prev = global_chained_list; +for (i = 0; i LIST_LENGTH; i++) { +stm_push_root((gcptr)w_prev); +w_newnode = (nodeptr)stm_allocate(sizeof(struct node), + GCTID_STRUCT_NODE); +w_prev = (nodeptr)stm_pop_root(); +w_newnode-value = LIST_LENGTH - i; +w_newnode-next = NULL; + +w_prev = (nodeptr)stm_write_barrier((gcptr)w_prev); +w_prev-next =
[pypy-commit] stmgc default: demo_random: thread locals - thread descriptor
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r196:8d3cf9f0c450 Date: 2013-06-19 14:48 +0200 http://bitbucket.org/pypy/stmgc/changeset/8d3cf9f0c450/ Log:demo_random: thread locals - thread descriptor diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -40,29 +40,33 @@ visit((gcptr *)n-next); } + // global and per-thread-data time_t default_seed; gcptr shared_roots[SHARED_ROOTS]; -__thread unsigned int thread_seed = 0; -__thread gcptr roots[MAXROOTS]; -__thread gcptr roots_outside_perform[MAXROOTS]; -__thread gcptr current_root = 0; -__thread int num_roots = 0; -__thread int num_roots_outside_perform = 0; -__thread int steps_left; -__thread int interruptible = 0; +struct thread_data { +unsigned int thread_seed; +gcptr roots[MAXROOTS]; +gcptr roots_outside_perform[MAXROOTS]; +gcptr current_root; +int num_roots; +int num_roots_outside_perform; +int steps_left; +int interruptible; +}; +__thread struct thread_data td; // helper functions int get_rand(int max) { -return (int)(rand_r(thread_seed) % (unsigned int)max); +return (int)(rand_r(td.thread_seed) % (unsigned int)max); } -void copy_roots(gcptr *from, gcptr *to) +void copy_roots(gcptr *from, gcptr *to, int num) { int i; -for (i = 0; i num_roots; i++) +for (i = 0; i num; i++) *(to++) = *(from++); } @@ -77,22 +81,22 @@ void push_roots() { int i; -for (i = 0; i num_roots; i++) -stm_push_root(roots[i]); +for (i = 0; i td.num_roots; i++) +stm_push_root(td.roots[i]); } void pop_roots() { int i; -for (i = num_roots - 1; i = 0; i--) -roots[i] = stm_pop_root(); +for (i = td.num_roots - 1; i = 0; i--) +td.roots[i] = stm_pop_root(); } void del_root(int idx) { int i; -for (i = idx; i num_roots - 1; i++) -roots[i] = roots[i + 1]; +for (i = idx; i td.num_roots - 1; i++) +td.roots[i] = td.roots[i + 1]; } gcptr allocate_root(size_t size, int tid) @@ -114,17 +118,17 @@ void setup_thread() { int i; -thread_seed = default_seed; -steps_left = STEPS; -interruptible = 0; +td.thread_seed = default_seed; +td.steps_left = STEPS; +td.interruptible = 0; -num_roots = PREBUILT + NUMROOTS; +td.num_roots = PREBUILT + NUMROOTS; for (i = 0; i PREBUILT; i++) { -roots[i] = allocate_pseudoprebuilt(sizeof(struct root), - GCTID_STRUCT_ROOT); +td.roots[i] = allocate_pseudoprebuilt(sizeof(struct root), + GCTID_STRUCT_ROOT); } for (i = PREBUILT; i PREBUILT + NUMROOTS; i++) { -roots[i] = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); +td.roots[i] = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); } } @@ -137,8 +141,8 @@ gcptr _r, _sr; int num, k; -num = get_rand(num_roots); -_r = roots[num]; +num = get_rand(td.num_roots); +_r = td.roots[num]; num = get_rand(SHARED_ROOTS); _sr = shared_roots[num]; @@ -158,8 +162,8 @@ p = _r; break; case 2: // add 'p' to roots -if (num_roots MAXROOTS) -roots[num_roots++] = p; +if (td.num_roots MAXROOTS) +td.roots[td.num_roots++] = p; break; case 3: // allocate fresh 'p' p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); @@ -173,8 +177,8 @@ stm_read_barrier(p); break; case 6: // transaction break -if (interruptible) -return -1; // break current +if (td.interruptible) +return (gcptr)-1; // break current transaction_break(); p = NULL; break; @@ -196,8 +200,8 @@ stm_write_barrier(_sr); break; case 13: -w_sr = stm_write_barrier(_sr); -w_sr-next = shared_roots[get_rand(SHARED_ROOTS)]; +w_sr = (rootptr)stm_write_barrier(_sr); +w_sr-next = (rootptr)shared_roots[get_rand(SHARED_ROOTS)]; default: break; } @@ -208,32 +212,32 @@ void transaction_break() { push_roots(); -interruptible = 1; +td.interruptible = 1; -copy_roots(roots, roots_outside_perform); -num_roots_outside_perform = num_roots; +copy_roots(td.roots, td.roots_outside_perform, td.num_roots); +td.num_roots_outside_perform = td.num_roots; stm_perform_transaction(NULL, interruptible_callback); -num_roots = num_roots_outside_perform; -copy_roots(roots_outside_perform, roots); +td.num_roots = td.num_roots_outside_perform; +copy_roots(td.roots_outside_perform, td.roots, td.num_roots); -interruptible = 0; +td.interruptible = 0; pop_roots(); } int interruptible_callback(gcptr arg1, int retry_counter) { -num_roots = num_roots_outside_perform; -
[pypy-commit] stmgc default: demo_random: remove ambiguous naming
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r197:661b7c5a26c9 Date: 2013-06-19 14:54 +0200 http://bitbucket.org/pypy/stmgc/changeset/661b7c5a26c9/ Log:demo_random: remove ambiguous naming diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -18,25 +18,25 @@ // SUPPORT -#define GCTID_STRUCT_ROOT 123 +#define GCTID_STRUCT_NODE 123 -struct root { +struct node { struct stm_object_s hdr; long value; -struct root *next; +struct node *next; }; -typedef struct root * rootptr; +typedef struct node * nodeptr; size_t stmcb_size(gcptr ob) { -assert(stm_get_tid(ob) == GCTID_STRUCT_ROOT); -return sizeof(struct root); +assert(stm_get_tid(ob) == GCTID_STRUCT_NODE); +return sizeof(struct node); } void stmcb_trace(gcptr ob, void visit(gcptr *)) { -rootptr n; -assert(stm_get_tid(ob) == GCTID_STRUCT_ROOT); -n = (rootptr)ob; +nodeptr n; +assert(stm_get_tid(ob) == GCTID_STRUCT_NODE); +n = (nodeptr)ob; visit((gcptr *)n-next); } @@ -99,7 +99,7 @@ td.roots[i] = td.roots[i + 1]; } -gcptr allocate_root(size_t size, int tid) +gcptr allocate_node(size_t size, int tid) { gcptr r; push_roots(); @@ -124,11 +124,11 @@ td.num_roots = PREBUILT + NUMROOTS; for (i = 0; i PREBUILT; i++) { -td.roots[i] = allocate_pseudoprebuilt(sizeof(struct root), - GCTID_STRUCT_ROOT); +td.roots[i] = allocate_pseudoprebuilt(sizeof(struct node), + GCTID_STRUCT_NODE); } for (i = PREBUILT; i PREBUILT + NUMROOTS; i++) { -td.roots[i] = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); +td.roots[i] = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE); } } @@ -137,7 +137,7 @@ { fprintf(stdout, #); -rootptr w_r, w_sr; +nodeptr w_r, w_sr; gcptr _r, _sr; int num, k; @@ -150,7 +150,7 @@ k = get_rand(14); if (!p) // some parts expect it to be != 0 -p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); +p = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE); switch (k) { case 0: // remove a root @@ -166,12 +166,12 @@ td.roots[td.num_roots++] = p; break; case 3: // allocate fresh 'p' -p = allocate_root(sizeof(struct root), GCTID_STRUCT_ROOT); +p = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE); break; case 4: // set 'p' as *next in one of the roots -w_r = (rootptr)stm_write_barrier(_r); +w_r = (nodeptr)stm_write_barrier(_r); // XXX: do I have to read_barrier(p)? -w_r-next = (struct root*)p; +w_r-next = (struct node*)p; break; case 5: // read and validate 'p' stm_read_barrier(p); @@ -186,7 +186,7 @@ p = stm_write_barrier(p); break; case 8: -p = (gcptr)(((rootptr)stm_read_barrier(p))-next); +p = (gcptr)(((nodeptr)stm_read_barrier(p))-next); break; case 9: // XXX: rare events break; @@ -200,8 +200,8 @@ stm_write_barrier(_sr); break; case 13: -w_sr = (rootptr)stm_write_barrier(_sr); -w_sr-next = (rootptr)shared_roots[get_rand(SHARED_ROOTS)]; +w_sr = (nodeptr)stm_write_barrier(_sr); +w_sr-next = (nodeptr)shared_roots[get_rand(SHARED_ROOTS)]; default: break; } @@ -300,8 +300,8 @@ default_seed = time(NULL) / 3600 / 24; for (i = 0; i SHARED_ROOTS; i++) { -shared_roots[i] = allocate_pseudoprebuilt(sizeof(struct root), - GCTID_STRUCT_ROOT); +shared_roots[i] = allocate_pseudoprebuilt(sizeof(struct node), + GCTID_STRUCT_NODE); } status = sem_init(done, 0, 0); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: demo_random: more checks
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r199:b2ce4052626c Date: 2013-06-20 08:40 +0200 http://bitbucket.org/pypy/stmgc/changeset/b2ce4052626c/ Log:demo_random: more checks diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -6,15 +6,19 @@ #include time.h #include stmgc.h +#include stmimpl.h #include fprintcolor.h +extern revision_t get_private_rev_num(void); + #define NUMTHREADS 4 #define STEPS 10 -#define NUMROOTS 10 -#define PREBUILT 3 +#define NUMROOTS 10 // per thread +#define PREBUILT 3 // per thread #define MAXROOTS 1000 -#define SHARED_ROOTS 5 +#define SHARED_ROOTS 5 // shared by threads + // SUPPORT @@ -58,6 +62,9 @@ // helper functions +int classify(gcptr p); +void check(gcptr p); + int get_rand(int max) { return (int)(rand_r(td.thread_seed) % (unsigned int)max); @@ -81,15 +88,19 @@ void push_roots() { int i; -for (i = 0; i td.num_roots; i++) +for (i = 0; i td.num_roots; i++) { +check(td.roots[i]); stm_push_root(td.roots[i]); +} } void pop_roots() { int i; -for (i = td.num_roots - 1; i = 0; i--) +for (i = td.num_roots - 1; i = 0; i--) { td.roots[i] = stm_pop_root(); +check(td.roots[i]); +} } void del_root(int idx) @@ -99,15 +110,117 @@ td.roots[i] = td.roots[i + 1]; } -gcptr allocate_node(size_t size, int tid) +nodeptr allocate_node() { -gcptr r; +nodeptr r; push_roots(); -r = stm_allocate(size, tid); +r = (nodeptr)stm_allocate(sizeof(struct node), GCTID_STRUCT_NODE); pop_roots(); return r; } +int is_shared_prebuilt(gcptr p) +{ +int i; +for (i = 0; i SHARED_ROOTS; i++) +if (shared_roots[i] == p) +return 1; +return 0; +} + +void check_not_free(gcptr p) +{ +assert(p != NULL); +assert((p-h_tid 0x) == GCTID_STRUCT_NODE); +if (is_shared_prebuilt(p)) +assert(p-h_tid GCFLAG_PREBUILT_ORIGINAL); +} + +void check(gcptr p) +{ +if (p != NULL) { +check_not_free(p); +classify(p); // additional asserts +} +} + +gcptr read_barrier(gcptr p) +{ +gcptr r = p; +if (p != NULL) { +check(p); +r = stm_read_barrier(p); +check(r); +} +return r; +} + +gcptr write_barrier(gcptr p) +{ +gcptr w = p; +if (p != NULL) { +check(p); +w = stm_write_barrier(p); +check(w); +} +return w; +} + +int in_nursery(gcptr obj) +{ +struct tx_descriptor *d = thread_descriptor; +int result1 = (d-nursery_base = (char*)obj + ((char*)obj) d-nursery_end); +if (obj-h_tid GCFLAG_OLD) { +assert(result1 == 0); +} +else { +/* this assert() also fails if obj is in another nursery than + the one of the current thread. This is ok, because we + should not see such pointers. */ +assert(result1 == 1); +} +return result1; +} + +static const revision_t C_PRIVATE_FROM_PROTECTED = 1; +static const revision_t C_PRIVATE= 2; +static const revision_t C_STUB = 3; +static const revision_t C_PUBLIC = 4; +static const revision_t C_BACKUP = 5; +static const revision_t C_PROTECTED = 6; +int classify(gcptr p) +{ +int priv_from_prot = (p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) != 0; +int private_other = p-h_revision == get_private_rev_num(); +int public = (p-h_tid GCFLAG_PUBLIC) != 0; +int backup = (p-h_tid GCFLAG_BACKUP_COPY) != 0; +int stub = (p-h_tid GCFLAG_STUB) != 0; +assert(priv_from_prot + private_other + public + backup = 1); +assert(public || !stub); + +if (priv_from_prot) +return C_PRIVATE_FROM_PROTECTED; +if (private_other) +return C_PRIVATE; +if (public) { +if (stub) { +assert(!in_nursery(p)); +} +else { +if (in_nursery(p)) { +assert(p-h_tid GCFLAG_NURSERY_MOVED); +assert(!(p-h_revision 1)); +} +return C_PUBLIC; +} +} +if (backup) +return C_BACKUP; +return C_PROTECTED; +} + + // THREAD TESTER @@ -128,7 +241,7 @@ GCTID_STRUCT_NODE); } for (i = PREBUILT; i PREBUILT + NUMROOTS; i++) { -td.roots[i] = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE); +td.roots[i] = (gcptr)allocate_node(); } } @@ -149,9 +262,6 @@ k = get_rand(14); -if (!p) // some parts expect it to be != 0 -p = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE); - switch (k) { case 0: // remove a root if (num 0) @@ -162,19 +272,21 @@ p = _r; break; case 2: // add 'p' to roots -if (td.num_roots MAXROOTS) +if (p td.num_roots MAXROOTS) td.roots[td.num_roots++]
[pypy-commit] stmgc default: add more stm_normalize_stolen_objects where needed
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r200:0efe1499373f Date: 2013-06-20 09:30 +0200 http://bitbucket.org/pypy/stmgc/changeset/0efe1499373f/ Log:add more stm_normalize_stolen_objects where needed diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -698,8 +698,12 @@ long long elapsed_time; /* acquire the lock, but don't double-acquire it if already committing */ - if (d-public_descriptor-collection_lock != 'C') + if (d-public_descriptor-collection_lock != 'C') { spinlock_acquire(d-public_descriptor-collection_lock, 'C'); +if (d-public_descriptor-stolen_objects.size != 0) + stm_normalize_stolen_objects(d); + } + assert(d-active != 0); assert(!is_inevitable(d)); @@ -870,6 +874,8 @@ revision_t my_lock = d-my_lock; wlog_t *item; + assert(d-public_descriptor-stolen_objects.size == 0); + if (!g2l_any_entry(d-public_to_private)) return; @@ -1025,6 +1031,7 @@ gcptr *items = d-private_from_protected.items; revision_t new_revision = cur_time + 1; // make an odd number assert(new_revision 1); + assert(d-public_descriptor-stolen_objects.size == 0); for (i = 0; i size; i++) { @@ -1125,7 +1132,6 @@ spinlock_acquire(d-public_descriptor-collection_lock, 'C'); /*committing*/ if (d-public_descriptor-stolen_objects.size != 0) stm_normalize_stolen_objects(d); - AcquireLocks(d); if (is_inevitable(d)) @@ -1151,6 +1157,9 @@ inev_mutex_acquire(); // wait until released inev_mutex_release(); spinlock_acquire(d-public_descriptor-collection_lock, 'C'); + if (d-public_descriptor-stolen_objects.size != 0) +stm_normalize_stolen_objects(d); + AcquireLocks(d); continue; } @@ -1162,6 +1171,7 @@ if (!ValidateDuringTransaction(d, 1)) AbortTransaction(ABRT_VALIDATE_COMMIT); } + CommitPrivateFromProtected(d, cur_time); /* we cannot abort any more from here */ ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: doesn't crash
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r218:7ed5c33f287e Date: 2013-06-20 21:09 +0200 http://bitbucket.org/pypy/stmgc/changeset/7ed5c33f287e/ Log:doesn't crash diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -59,7 +59,7 @@ assert(tid == (tid STM_USER_TID_MASK)); P-h_tid = tid; P-h_revision = stm_private_rev_num; -P-h_original = NULL; +P-h_original = 0; return P; } @@ -77,7 +77,7 @@ if (P-h_original) L-h_original = P-h_original; else -L-h_original = P; +L-h_original = (revision_t)P; return L; } @@ -93,7 +93,7 @@ if (P-h_original) L-h_original = P-h_original; else -L-h_original = P; +L-h_original = (revision_t)P; return L; } @@ -114,28 +114,21 @@ //p-h_original == NULL if (!(p-h_tid GCFLAG_OLD)) {//(is_in_nursery(p)) { -// preallocate old original outside +struct tx_descriptor *d = thread_descriptor; +spinlock_acquire(d-public_descriptor-collection_lock, 'I'); +// preallocate old original outside; // like stealing -gcptr O = stmgc_duplicate_old(L); -L-h_revision = (revision_t)O; -L-h_original = O; -L-h_tid |= GCFLAG_HAS_ID; +gcptr O = stmgc_duplicate_old(p); +p-h_revision = (revision_t)O; +p-h_original = (revision_t)O; +p-h_tid |= GCFLAG_HAS_ID; - -// could be stolen -if (p-h_tid GCFLAG_NURSERY_MOVED) { - -} -} -else if (p-h_tid GCFLAG_NURSERY_MOVED) { -if (p-h_tid GCFLAG_PUBLIC) { -// moved by stealing - -} - +spinlock_release(d-public_descriptor-collection_lock); +return (revision_t)O; } else { -assert(0); +// p is the original itself +return (revision_t)p; } } @@ -161,7 +154,7 @@ return fresh_old_copy; } -static inline void copy_to_old_id_copy(gcptr obj, gcptr id) +inline void copy_to_old_id_copy(gcptr obj, gcptr id) { size_t size = stmcb_size(obj); memcpy(id, obj, size); @@ -191,7 +184,8 @@ if (obj-h_tid GCFLAG_HAS_ID) { /* already has a place to go to */ -fresh_old_copy = copy_to_old_id_copy(obj, obj-h_original); +copy_to_old_id_copy(obj, (gcptr)obj-h_original); +fresh_old_copy = (gcptr)obj-h_original; } else { /* make a copy of it outside */ diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -11,6 +11,8 @@ struct stm_object_s stubs[STUB_NB_OBJS]; }; +inline void copy_to_old_id_copy(gcptr obj, gcptr id); + gcptr stm_stub_malloc(struct tx_public_descriptor *pd) { assert(pd-collection_lock != 0); @@ -152,16 +154,16 @@ if (!(L-h_tid GCFLAG_OLD)) { gcptr O; if (L-h_tid GCFLAG_HAS_ID) { +O = (gcptr)L-h_original; L-h_tid = ~GCFLAG_HAS_ID; -L-h_revision = (revision_t)L-h_original; -copy_to_old_id_copy(L, L-h_original); -O = L-h_original; +L-h_revision = (revision_t)O; +copy_to_old_id_copy(L, (gcptr)L-h_original); } else { /* Copy the object out of the other thread's nursery, if needed */ O = stmgc_duplicate_old(L); L-h_revision = (revision_t)O; -L-h_original = O; +L-h_original = (revision_t)O; } L-h_tid |= GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED; /* subtle: we need to remove L from the fxcache of the target diff --git a/c4/steal.h b/c4/steal.h --- a/c4/steal.h +++ b/c4/steal.h @@ -2,7 +2,7 @@ #define _SRCSTM_STEAL_H -#define STUB_BLOCK_SIZE (16 * WORD)/* power of two */ +#define STUB_BLOCK_SIZE (32 * WORD)/* power of two */ #define STUB_THREAD(h)(*(struct tx_public_descriptor **) \ (((revision_t)(h)) ~(STUB_BLOCK_SIZE-1))) diff --git a/c4/stmgc.h b/c4/stmgc.h --- a/c4/stmgc.h +++ b/c4/stmgc.h @@ -10,7 +10,7 @@ typedef struct stm_object_s { revision_t h_tid; revision_t h_revision; -gcptr h_original; +revision_t h_original; } *gcptr; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: intermediate backup before rewrite
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r219:589d41f3af88 Date: 2013-06-21 11:50 +0200 http://bitbucket.org/pypy/stmgc/changeset/589d41f3af88/ Log:intermediate backup before rewrite diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -27,6 +27,7 @@ struct node { struct stm_object_s hdr; long value; +revision_t id; struct node *next; }; typedef struct node * nodeptr; @@ -82,6 +83,7 @@ gcptr x = calloc(1, size); x-h_tid = PREBUILT_FLAGS | tid; x-h_revision = PREBUILT_REVISION; +x-h_original = 0; return x; } @@ -260,7 +262,7 @@ num = get_rand(SHARED_ROOTS); _sr = shared_roots[num]; -k = get_rand(15); +k = get_rand(16); switch (k) { case 0: // remove a root @@ -322,6 +324,17 @@ pop_roots(); p = NULL; break; +case 15: +w_r = (nodeptr)read_barrier(_r); +if (w_r-id) { +assert(w_r-id == stm_id((gcptr)w_r)); +assert(w_r-id == stm_id((gcptr)_r)); +} +else { +w_r = (nodeptr)write_barrier(_r); +w_r-id = stm_id((gcptr)w_r); +assert(w_r-id == stm_id((gcptr)_r)); +} } return p; } @@ -348,8 +361,8 @@ int interruptible_callback(gcptr arg1, int retry_counter) { td.num_roots = td.num_roots_outside_perform; -// done by the following pop_roots(): -//copy_roots(td.roots_outside_perform, td.roots, td.num_roots); +// done overwritten by the following pop_roots(): +// copy_roots(td.roots_outside_perform, td.roots, td.num_roots); // refresh td.roots: arg1 = stm_pop_root(); diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -446,7 +446,9 @@ B = stmgc_duplicate_old(P); B-h_tid |= GCFLAG_BACKUP_COPY; - + if (P-h_tid GCFLAG_OLD) +B-h_original = P; + P-h_tid |= GCFLAG_PRIVATE_FROM_PROTECTED; P-h_revision = (revision_t)B; @@ -473,6 +475,9 @@ /* note that stmgc_duplicate() usually returns a young object, but may return an old one if the nursery is full at this moment. */ gcptr L = stmgc_duplicate(R); + if (!(L-h_original)) +L-h_original = (revision_t)R; + assert(!(L-h_tid GCFLAG_BACKUP_COPY)); assert(!(L-h_tid GCFLAG_STUB)); assert(!(L-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); @@ -1003,7 +1008,12 @@ stub-h_tid = (L-h_tid STM_USER_TID_MASK) | GCFLAG_PUBLIC | GCFLAG_STUB | GCFLAG_OLD; + assert(!(L-h_tid GCFLAG_HAS_ID)); stub-h_revision = ((revision_t)L) | 2; + if (L-h_original) +stub-h_original = L-h_original; + else +L-h_original = (revision_t)stub; item-val = stub; } G2L_LOOP_END; @@ -1069,6 +1079,8 @@ if (B-h_tid GCFLAG_PUBLIC) { + assert(!(P-h_tid GCFLAG_HAS_ID)); + /* B was stolen */ while (1) { @@ -1080,6 +1092,13 @@ break; } } + else if (P-h_tid GCFLAG_HAS_ID) { +/* The backup is the id object. */ +B-h_tid = ~GCFLAG_BACKUP_COPY; +B-h_tid |= GCFLAG_PUBLIC; +P-h_tid = ~GCFLAG_HAS_ID; +B-h_revision = (revision_t)P; + } else { stmgcpage_free(B); @@ -,6 +1130,7 @@ { assert(!(B-h_tid GCFLAG_BACKUP_COPY)); P-h_tid |= GCFLAG_PUBLIC; + P-h_tid = ~GCFLAG_HAS_ID; // just in case if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; /* P becomes a public outdated object. It may create an exception documented in doc-objects.txt: a public but young @@ -1119,10 +1139,20 @@ stealing will follow its h_revision (to B). */ } + else if (P-h_tid GCFLAG_HAS_ID) { +/* The backup is the id object. P becomes outdated. */ +P-h_tid |= GCFLAG_PUBLIC; +P-h_tid = ~GCFLAG_HAS_ID; +B-h_tid |= GCFLAG_PUBLIC; +B-h_tid = ~GCFLAG_BACKUP_COPY; +if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; +fprintf(stderr, %p made outdated, %p is current\n, P, B); + } else { /* copy the backup copy B back over the now-protected object P, and then free B, which will not be used any more. */ + assert(B-h_original == P); size_t size = stmcb_size(B); assert(B-h_tid GCFLAG_BACKUP_COPY); memcpy(((char *)P) + offsetof(struct stm_object_s, h_revision), diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -74,11 +74,6 @@ L-h_tid = ~GCFLAG_OLD; L-h_tid = ~GCFLAG_HAS_ID; -if (P-h_original) -L-h_original = P-h_original; -else -L-h_original = (revision_t)P; - return L; } @@ -88,12 +83,7 @@ gcptr
[pypy-commit] stmgc implement-id: merge default
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r222:2fe2cb9597de Date: 2013-06-21 13:25 +0200 http://bitbucket.org/pypy/stmgc/changeset/2fe2cb9597de/ Log:merge default diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -199,6 +199,7 @@ } fprintf(stderr, readobj: %p\n, P); + assert(!(P-h_tid GCFLAG_STUB)); gcptrlist_insert(d-list_of_read_objects, P); add_in_recent_reads_cache: @@ -492,6 +493,8 @@ GCFLAG_WRITE_BARRIER | 0); L-h_revision = stm_private_rev_num; + assert(stm_private_rev_num 0); + assert(stm_private_rev_num 1); g2l_insert(d-public_to_private, R, L); fprintf(stderr, write_barrier: adding %p - %p to public_to_private\n, R, L); diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -195,8 +195,11 @@ return; restart: -if (obj-h_tid GCFLAG_VISITED) +if (obj-h_tid GCFLAG_VISITED) { +fprintf(stderr, [already visited: %p]\n, obj); +assert(obj == *pobj); return;/* already seen */ +} if (obj-h_revision 1) { assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); @@ -223,7 +226,8 @@ assert(*pobj == prev_obj); gcptr obj1 = obj; visit(obj1); /* recursion, but should be only once */ -prev_obj-h_revision = ((revision_t)obj1) + 2; +assert(prev_obj-h_tid GCFLAG_STUB); +prev_obj-h_revision = ((revision_t)obj1) | 2; return; } } @@ -245,8 +249,11 @@ B-h_tid |= GCFLAG_VISITED; } else { +/* a private_from_protected with a stolen backup copy B */ assert(!(B-h_tid GCFLAG_BACKUP_COPY)); -abort(); // XXX +gcptr obj1 = B; +visit(obj1); /* xxx recursion? */ +obj-h_revision = (revision_t)obj1; } } obj-h_tid |= GCFLAG_VISITED; @@ -286,8 +293,12 @@ { //assert(*root == END_MARKER); //root++; -while (root != end) -visit(root++); +while (root != end) { +gcptr o = *root; +visit(root); +fprintf(stderr, visit stack root: %p - %p\n, o, *root); +root++; +} } static void mark_all_stack_roots(void) @@ -346,14 +357,20 @@ for (i = d-list_of_read_objects.size - 1; i = 0; --i) { gcptr obj = items[i]; +assert(!(obj-h_tid GCFLAG_STUB)); /* Warning: in case the object listed is outdated and has been replaced with a more recent revision, then it might be the case that obj-h_revision doesn't have GCFLAG_VISITED, but just removing it is very wrong --- we want 'd' to abort. */ +if (obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { +assert(IS_POINTER(obj-h_revision)); +obj = (gcptr)obj-h_revision; +} + revision_t v = obj-h_revision; -if (IS_POINTER(v) !(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)) { +if (IS_POINTER(v)) { /* has a more recent revision. Oups. */ fprintf(stderr, ABRT_COLLECT_MAJOR: %p was read but modified already\n, @@ -528,6 +545,7 @@ struct tx_descriptor *d; struct tx_descriptor *saved = thread_descriptor; revision_t saved_private_rev = stm_private_rev_num; +char *read_barrier_cache = stm_read_barrier_cache; assert(saved_private_rev == *saved-private_revision_ref); for (d = stm_tx_head; d; d = d-tx_next) { @@ -536,16 +554,19 @@ collection was not preceeded by a minor collection if the thread is busy in a system call for example. */ -if (stmgc_minor_collect_anything_to_do(d)) { +if (stmgc_minor_collect_anything_to_do(d) || +(d-public_descriptor-stolen_objects.size != 0)) { /* Hack: temporarily pretend that we are the other thread... */ thread_descriptor = d; stm_private_rev_num = *d-private_revision_ref; +fxcache_install(d-recent_reads_cache); //assert(stmgc_nursery_hiding(d, 0)); stmgc_minor_collect_no_abort(); //assert(stmgc_nursery_hiding(d, 1)); thread_descriptor = saved; stm_private_rev_num = saved_private_rev; +stm_read_barrier_cache = read_barrier_cache; } } } @@ -582,7 +603,7 @@ countdown_next_major_coll = next; } -void stm_major_collect(void) +static void major_collect(void) { stmgcpage_acquire_global_lock(); fprintf(stderr, ,-\n| running major collection...\n); @@ -628,7 +649,7 @@ threads will also acquire the RW lock in exclusive mode, but won't do anything. */ if (countdown_next_major_coll == 0) -stm_major_collect(); +major_collect(); stm_stop_single_thread(); diff --git
[pypy-commit] stmgc implement-id: minor changes
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r221:16af90468dcd Date: 2013-06-21 13:23 +0200 http://bitbucket.org/pypy/stmgc/changeset/16af90468dcd/ Log:minor changes diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -446,6 +446,7 @@ B = stmgc_duplicate_old(P); B-h_tid |= GCFLAG_BACKUP_COPY; + B-h_tid = ~GCFLAG_HAS_ID; if (!(P-h_original) (P-h_tid GCFLAG_OLD)) { B-h_original = (revision_t)P; } @@ -1021,6 +1022,7 @@ } else { L-h_original = (revision_t)stub; +assert(0); } item-val = stub; diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -83,7 +83,6 @@ gcptr L = (gcptr)stmgcpage_malloc(size); memcpy(L, P, size); L-h_tid |= GCFLAG_OLD; -assert(!(L-h_tid GCFLAG_HAS_ID)); return L; } diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -89,6 +89,7 @@ } else { obj-h_original = (revision_t)stub; +assert(0); } g2l_insert(sd-all_stubs, obj, stub); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: merge
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r217:74a48c97a3f6 Date: 2013-06-20 16:53 +0200 http://bitbucket.org/pypy/stmgc/changeset/74a48c97a3f6/ Log:merge diff --git a/c4/demo2.c b/c4/demo2.c --- a/c4/demo2.c +++ b/c4/demo2.c @@ -105,7 +105,7 @@ stm_read_barrier((gcptr)r_next))) { asm volatile (pause:::memory); /* smp_spinloop() */ i++; -assert(i 1000); +assert(i 100); } // for now: assert(((nodeptr)stm_read_barrier((gcptr)r_prev-next))-value diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -972,7 +972,7 @@ } G2L_LOOP_END; } -//static pthread_mutex_t mutex_prebuilt_gcroots = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex_prebuilt_gcroots = PTHREAD_MUTEX_INITIALIZER; static void UpdateChainHeads(struct tx_descriptor *d, revision_t cur_time, revision_t localrev) @@ -1028,16 +1028,13 @@ #endif ACCESS_ONCE(R-h_revision) = v; -#if 0 if (R-h_tid GCFLAG_PREBUILT_ORIGINAL) { /* cannot possibly get here more than once for a given value of R */ pthread_mutex_lock(mutex_prebuilt_gcroots); gcptrlist_insert(stm_prebuilt_gcroots, R); pthread_mutex_unlock(mutex_prebuilt_gcroots); - /*mark*/ } -#endif } G2L_LOOP_END; @@ -1433,6 +1430,8 @@ /* we are reusing 'pd' */ descriptor_array_free_list = pd-free_list_next; assert(descriptor_array_free_list = 0); + assert(pd-stolen_objects.size == 0); + assert(pd-stolen_young_stubs.size == 0); assert(pd-collection_lock == 0 || pd-collection_lock == -1); pd-collection_lock = 0; } @@ -1483,8 +1482,12 @@ assert(d-active == 0); stmgcpage_acquire_global_lock(); -/* our nursery is empty at this point */ +/* our nursery is empty at this point. The list 'stolen_objects' + should have been emptied at the previous minor collection and + should remain empty because we don't have any young object. */ +assert(d-public_descriptor-stolen_objects.size == 0); assert(d-public_descriptor-stolen_young_stubs.size == 0); +gcptrlist_delete(d-public_descriptor-stolen_objects); gcptrlist_delete(d-public_descriptor-stolen_young_stubs); stmgcpage_done_tls(); diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -199,21 +199,56 @@ return;/* already seen */ if (obj-h_revision 1) { +assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see also fix_outdated() */ } -else { +else if (obj-h_tid GCFLAG_PUBLIC) { /* h_revision is a ptr: we have a more recent version */ -assert(!(obj-h_tid GCFLAG_STUB)); gcptr prev_obj = obj; -obj = (gcptr)obj-h_revision; /* go visit the more recent version */ -if (!(obj-h_tid GCFLAG_VISITED) IS_POINTER(obj-h_revision)) { +if (!(obj-h_revision 2)) { +/* go visit the more recent version */ obj = (gcptr)obj-h_revision; +} +else { +/* it's a stub: keep it if it points to a protected version, + because we need to keep the effect of stealing if it is + later accessed by the wrong thread. If it points to a + public object (possibly outdated), we can ignore the stub. +*/ +assert(obj-h_tid GCFLAG_STUB); +obj = (gcptr)(obj-h_revision - 2); +if (!(obj-h_tid GCFLAG_PUBLIC)) { +prev_obj-h_tid |= GCFLAG_VISITED; +assert(*pobj == prev_obj); +gcptr obj1 = obj; +visit(obj1); /* recursion, but should be only once */ +prev_obj-h_revision = ((revision_t)obj1) + 2; +return; +} +} + +if (!(obj-h_revision 3)) { +obj = (gcptr)obj-h_revision; +assert(obj-h_tid GCFLAG_PUBLIC); prev_obj-h_revision = (revision_t)obj; } *pobj = obj; goto restart; } +else { +assert(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED); +gcptr B = (gcptr)obj-h_revision; +if (!(B-h_tid GCFLAG_PUBLIC)) { +/* a regular private_from_protected object with a backup copy B */ +assert(B-h_tid GCFLAG_BACKUP_COPY); +B-h_tid |= GCFLAG_VISITED; +} +else { +assert(!(B-h_tid GCFLAG_BACKUP_COPY)); +abort(); // XXX +} +} obj-h_tid |= GCFLAG_VISITED; gcptrlist_insert(objects_to_trace, obj); } @@ -304,6 +339,11 @@ if (d-active 0) return; /* already aborted during forced minor collection */ +if (d-active == 2) { +/* inevitable transaction: clear the
[pypy-commit] stmgc default: minor changes
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r215:a295fa0455e1 Date: 2013-06-20 14:18 +0200 http://bitbucket.org/pypy/stmgc/changeset/a295fa0455e1/ Log:minor changes diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -183,12 +183,12 @@ return result1; } -static const revision_t C_PRIVATE_FROM_PROTECTED = 1; -static const revision_t C_PRIVATE= 2; -static const revision_t C_STUB = 3; -static const revision_t C_PUBLIC = 4; -static const revision_t C_BACKUP = 5; -static const revision_t C_PROTECTED = 6; +static const int C_PRIVATE_FROM_PROTECTED = 1; +static const int C_PRIVATE= 2; +static const int C_STUB = 3; +static const int C_PUBLIC = 4; +static const int C_BACKUP = 5; +static const int C_PROTECTED = 6; int classify(gcptr p) { int priv_from_prot = (p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) != 0; @@ -260,7 +260,7 @@ num = get_rand(SHARED_ROOTS); _sr = shared_roots[num]; -k = get_rand(14); +k = get_rand(15); switch (k) { case 0: // remove a root @@ -316,7 +316,11 @@ w_sr = (nodeptr)write_barrier(_sr); w_sr-next = (nodeptr)shared_roots[get_rand(SHARED_ROOTS)]; break; -default: +case 14: +push_roots(); +stmgc_minor_collect(); +pop_roots(); +p = NULL; break; } return p; @@ -344,17 +348,21 @@ int interruptible_callback(gcptr arg1, int retry_counter) { td.num_roots = td.num_roots_outside_perform; -copy_roots(td.roots_outside_perform, td.roots, td.num_roots); +// done by the following pop_roots(): +//copy_roots(td.roots_outside_perform, td.roots, td.num_roots); +// refresh td.roots: arg1 = stm_pop_root(); +assert(arg1 == NULL); pop_roots(); push_roots(); stm_push_root(arg1); int p = run_me(); -int restart = p == -1 ? get_rand(3) != 1 : 0; +if (p == -1) // maybe restart transaction +return get_rand(3) != 1; -return restart; +return 0; } int run_me() ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: amazingly seems to not crash..
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r220:c0ff042ed265 Date: 2013-06-21 13:08 +0200 http://bitbucket.org/pypy/stmgc/changeset/c0ff042ed265/ Log:amazingly seems to not crash.. diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -446,8 +446,9 @@ B = stmgc_duplicate_old(P); B-h_tid |= GCFLAG_BACKUP_COPY; - if (P-h_tid GCFLAG_OLD) -B-h_original = P; + if (!(P-h_original) (P-h_tid GCFLAG_OLD)) { + B-h_original = (revision_t)P; + } P-h_tid |= GCFLAG_PRIVATE_FROM_PROTECTED; P-h_revision = (revision_t)B; @@ -475,8 +476,10 @@ /* note that stmgc_duplicate() usually returns a young object, but may return an old one if the nursery is full at this moment. */ gcptr L = stmgc_duplicate(R); - if (!(L-h_original)) + if (!(L-h_original)) { +assert(R-h_tid GCFLAG_OLD); // if not, force stm_id?? L-h_original = (revision_t)R; + } assert(!(L-h_tid GCFLAG_BACKUP_COPY)); assert(!(L-h_tid GCFLAG_STUB)); @@ -1010,10 +1013,16 @@ | GCFLAG_OLD; assert(!(L-h_tid GCFLAG_HAS_ID)); stub-h_revision = ((revision_t)L) | 2; - if (L-h_original) + if (L-h_original) { stub-h_original = L-h_original; - else + } + else if (L-h_tid GCFLAG_OLD) { +stub-h_original = (revision_t)L; + } + else { L-h_original = (revision_t)stub; + } + item-val = stub; } G2L_LOOP_END; @@ -1091,12 +1100,13 @@ if (bool_cas(B-h_revision, v, (revision_t)P)) break; } -} - else if (P-h_tid GCFLAG_HAS_ID) { -/* The backup is the id object. */ +} + else if (P-h_original == (revision_t)B) { +/* The backup is the id object */ +assert(!(P-h_tid GCFLAG_HAS_ID)); + B-h_tid = ~GCFLAG_BACKUP_COPY; B-h_tid |= GCFLAG_PUBLIC; -P-h_tid = ~GCFLAG_HAS_ID; B-h_revision = (revision_t)P; } else @@ -1139,10 +1149,10 @@ stealing will follow its h_revision (to B). */ } - else if (P-h_tid GCFLAG_HAS_ID) { + else if (P-h_original == (revision_t)B) { /* The backup is the id object. P becomes outdated. */ +assert(!(P-h_tid GCFLAG_HAS_ID)); P-h_tid |= GCFLAG_PUBLIC; -P-h_tid = ~GCFLAG_HAS_ID; B-h_tid |= GCFLAG_PUBLIC; B-h_tid = ~GCFLAG_BACKUP_COPY; if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; @@ -1152,7 +1162,8 @@ { /* copy the backup copy B back over the now-protected object P, and then free B, which will not be used any more. */ - assert(B-h_original == P); + assert(!(P-h_original) + || (B-h_original == (revision_t)P-h_original)); size_t size = stmcb_size(B); assert(B-h_tid GCFLAG_BACKUP_COPY); memcpy(((char *)P) + offsetof(struct stm_object_s, h_revision), diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -101,93 +101,51 @@ struct tx_descriptor *d = thread_descriptor; revision_t result; +spinlock_acquire(d-public_descriptor-collection_lock, 'I'); if (p-h_original) { -fprintf(stderr, stm_id(%p) has original: %p\n, p, (gcptr)p-h_original); +spinlock_release(d-public_descriptor-collection_lock); return p-h_original; } -spinlock_acquire(d-public_descriptor-collection_lock, 'I'); +/* old objects must have an h_original OR be + the original itself. + if some thread stole p when it was still young, + it must have set h_original. stealing an old obj + makes the old obj original. +*/ if (p-h_tid GCFLAG_OLD) { /* it must be this exact object */ result = (revision_t)p; } else { -/* must create shadow original object */ -gcptr O = stmgc_duplicate_old(p); -p-h_original = (revision_t)O; -p-h_tid |= GCFLAG_HAS_ID; -O-h_tid |= GCFLAG_PUBLIC; - -result = (revision_t)O; - -fprintf(stderr, stm_id(%p): is young, preallocate old id-copy %p\n, -p, O); -} - - -if (p-h_original) { -// maybe in the meantime? -fprintf(stderr, stm_id(%p) has original NOW: %p\n, p, (gcptr)p-h_original); -spinlock_release(d-public_descriptor-collection_lock); -return p-h_original; -} - -//p-h_original == NULL - -if (p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { -gcptr B = (gcptr)p-h_revision; -if (p-h_tid GCFLAG_OLD) { -/* may have become old after becoming priv_from_prot */ -if (B-h_tid GCFLAG_BACKUP_COPY) { -B-h_original = p; -result = (revision_t)p; -fprintf(stderr, stm_id(%p): is priv_from_prot and old. make ); -
[pypy-commit] stmgc implement-id: work in progress
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r216:04f0776e142a Date: 2013-06-20 16:51 +0200 http://bitbucket.org/pypy/stmgc/changeset/04f0776e142a/ Log:work in progress diff --git a/c4/et.h b/c4/et.h --- a/c4/et.h +++ b/c4/et.h @@ -57,6 +57,9 @@ * but converted from a protected. These are precisely the objects * that have a backup copy (in h_revision), which gives a copy of the * original protected object. + * + * GCFLAG_HAS_ID is set on young objects that have an old reserved + * memory to be copied to in minor collections (obj-h_original) */ static const revision_t GCFLAG_OLD= STM_FIRST_GCFLAG 0; static const revision_t GCFLAG_VISITED= STM_FIRST_GCFLAG 1; @@ -68,6 +71,7 @@ static const revision_t GCFLAG_BACKUP_COPY /*debug*/ = STM_FIRST_GCFLAG 7; static const revision_t GCFLAG_STUB /*debug*/ = STM_FIRST_GCFLAG 8; static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG 9; +static const revision_t GCFLAG_HAS_ID = STM_FIRST_GCFLAG 10; /* this value must be reflected in PREBUILT_FLAGS in stmgc.h */ #define GCFLAG_PREBUILT (GCFLAG_VISITED | \ diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -59,6 +59,7 @@ assert(tid == (tid STM_USER_TID_MASK)); P-h_tid = tid; P-h_revision = stm_private_rev_num; +P-h_original = NULL; return P; } @@ -71,6 +72,13 @@ memcpy(L, P, size); L-h_tid = ~GCFLAG_OLD; +L-h_tid = ~GCFLAG_HAS_ID; + +if (P-h_original) +L-h_original = P-h_original; +else +L-h_original = P; + return L; } @@ -80,11 +88,64 @@ gcptr L = (gcptr)stmgcpage_malloc(size); memcpy(L, P, size); L-h_tid |= GCFLAG_OLD; +L-h_tid = ~GCFLAG_HAS_ID; + +if (P-h_original) +L-h_original = P-h_original; +else +L-h_original = P; + return L; } // + +revision_t stm_hash(gcptr p) +{ +return stm_id(p); +} + +revision_t stm_id(gcptr p) +{ +if (p-h_original) { +return p-h_original; +} + +//p-h_original == NULL +if (!(p-h_tid GCFLAG_OLD)) {//(is_in_nursery(p)) { +// preallocate old original outside +// like stealing +gcptr O = stmgc_duplicate_old(L); +L-h_revision = (revision_t)O; +L-h_original = O; +L-h_tid |= GCFLAG_HAS_ID; + + +// could be stolen +if (p-h_tid GCFLAG_NURSERY_MOVED) { + +} +} +else if (p-h_tid GCFLAG_NURSERY_MOVED) { +if (p-h_tid GCFLAG_PUBLIC) { +// moved by stealing + +} + +} +else { +assert(0); +} +} + +revision_t stm_pointer_equal(gcptr p1, gcptr p2) +{ +return stm_id(p1) == stm_id(p2); +} + +// + static inline gcptr create_old_object_copy(gcptr obj) { assert(!(obj-h_tid GCFLAG_PUBLIC)); @@ -100,6 +161,13 @@ return fresh_old_copy; } +static inline void copy_to_old_id_copy(gcptr obj, gcptr id) +{ +size_t size = stmcb_size(obj); +memcpy(id, obj, size); +id-h_tid = ~GCFLAG_HAS_ID; +} + static void visit_if_young(gcptr *root) { gcptr obj = *root; @@ -111,17 +179,25 @@ } else { /* it's a nursery object. Was it already moved? */ - if (UNLIKELY(obj-h_tid GCFLAG_NURSERY_MOVED)) { /* yes. Such an object can be a public object in the nursery too (such objects are always NURSERY_MOVED). For all cases, - we can just fix the ref. */ + we can just fix the ref. + Can be stolen objects or those we already moved. +*/ *root = (gcptr)obj-h_revision; return; } -/* make a copy of it outside */ -fresh_old_copy = create_old_object_copy(obj); +if (obj-h_tid GCFLAG_HAS_ID) { +/* already has a place to go to */ +fresh_old_copy = copy_to_old_id_copy(obj, obj-h_original); +} +else { +/* make a copy of it outside */ +fresh_old_copy = create_old_object_copy(obj); +} + obj-h_tid |= GCFLAG_NURSERY_MOVED; obj-h_revision = (revision_t)fresh_old_copy; diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -149,10 +149,20 @@ fprintf(stderr, stolen: %p - %p\n, P, L); -/* Copy the object out of the other thread's nursery, if needed */ -if (!(L-h_tid GCFLAG_OLD)) { -gcptr O = stmgc_duplicate_old(L); -L-h_revision = (revision_t)O; +if (!(L-h_tid GCFLAG_OLD)) { +gcptr O; +if (L-h_tid GCFLAG_HAS_ID) { +L-h_tid = ~GCFLAG_HAS_ID; +L-h_revision = (revision_t)L-h_original; +
[pypy-commit] stmgc implement-id: mark some paths with assert(0) because they don't seem to be reached in demo_random.c
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r225:08871aa2ccfe Date: 2013-06-21 14:11 +0200 http://bitbucket.org/pypy/stmgc/changeset/08871aa2ccfe/ Log:mark some paths with assert(0) because they don't seem to be reached in demo_random.c diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -449,7 +449,11 @@ B-h_tid |= GCFLAG_BACKUP_COPY; B-h_tid = ~GCFLAG_HAS_ID; if (!(P-h_original) (P-h_tid GCFLAG_OLD)) { - B-h_original = (revision_t)P; +/* if P is old, it must be the original + if P is young, it will create a shadow original later + or it's getting decided when backup gets stolen. +*/ +B-h_original = (revision_t)P; } P-h_tid |= GCFLAG_PRIVATE_FROM_PROTECTED; @@ -479,6 +483,8 @@ return an old one if the nursery is full at this moment. */ gcptr L = stmgc_duplicate(R); if (!(L-h_original)) { +/* if we don't have an original object yet, + it must be the old public R */ assert(R-h_tid GCFLAG_OLD); // if not, force stm_id?? L-h_original = (revision_t)R; } @@ -1161,7 +1167,6 @@ B-h_tid |= GCFLAG_PUBLIC; B-h_tid = ~GCFLAG_BACKUP_COPY; if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; -fprintf(stderr, %p made outdated, %p is current\n, P, B); } else { diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -100,12 +100,15 @@ struct tx_descriptor *d = thread_descriptor; revision_t result; +if (p-h_original) { /* fast path */ +return p-h_original; +} + spinlock_acquire(d-public_descriptor-collection_lock, 'I'); -if (p-h_original) { +if (p-h_original) { /* maybe now? */ spinlock_release(d-public_descriptor-collection_lock); return p-h_original; } - /* old objects must have an h_original OR be the original itself. if some thread stole p when it was still young, diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -84,9 +84,11 @@ stub-h_revision = ((revision_t)obj) | 2; if (obj-h_original) { stub-h_original = obj-h_original; +assert(0); } else if (obj-h_tid GCFLAG_OLD) { stub-h_original = (revision_t)obj; +assert(0); } else { obj-h_original = (revision_t)stub; @@ -122,17 +124,21 @@ gcptr B = (gcptr)L-h_revision; /* the backup copy */ if (L-h_original) { -/* may have HAS_ID */ +/* L has an original, may be GCFLAG_HAS_ID */ B-h_original = L-h_original; } else if (L-h_tid GCFLAG_OLD) { +/* If old, it must be the original */ assert(!(L-h_tid GCFLAG_HAS_ID)); /* original must be L */ B-h_original = (revision_t)L; +assert(0); } else { -/* we can make the backup the original */ +/* we can make the backup the original + since L hasn't decided yet */ L-h_original = (revision_t)B; +assert(0); } /* B is now a backup copy, i.e. a protected object, and we own ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: close anonymous
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r224:348eb80ca0c9 Date: 2013-06-21 13:37 +0200 http://bitbucket.org/pypy/stmgc/changeset/348eb80ca0c9/ Log:close anonymous ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: fix tests and remove some of the assert(0), as they at least seem to be hit in tests
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r226:98c1eebad13c Date: 2013-06-21 14:18 +0200 http://bitbucket.org/pypy/stmgc/changeset/98c1eebad13c/ Log:fix tests and remove some of the assert(0), as they at least seem to be hit in tests diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -84,15 +84,12 @@ stub-h_revision = ((revision_t)obj) | 2; if (obj-h_original) { stub-h_original = obj-h_original; -assert(0); } else if (obj-h_tid GCFLAG_OLD) { stub-h_original = (revision_t)obj; -assert(0); } else { obj-h_original = (revision_t)stub; -assert(0); } g2l_insert(sd-all_stubs, obj, stub); diff --git a/c4/test/support.py b/c4/test/support.py --- a/c4/test/support.py +++ b/c4/test/support.py @@ -32,6 +32,7 @@ typedef struct stm_object_s { revision_t h_tid; revision_t h_revision; +revision_t h_original; } *gcptr; int gettid(gcptr); diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py --- a/c4/test/test_gcpage.py +++ b/c4/test/test_gcpage.py @@ -12,7 +12,7 @@ def test_HDR(): import struct -assert HDR == struct.calcsize(PP) +assert HDR == struct.calcsize(PPP) def test_malloc_simple(): assert count_pages() == 0 ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: fix issue when HAS_ID flag gets removed
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r227:17d1d1ba2d0d Date: 2013-06-21 15:11 +0200 http://bitbucket.org/pypy/stmgc/changeset/17d1d1ba2d0d/ Log:fix issue when HAS_ID flag gets removed * updated demo_random diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -262,7 +262,7 @@ num = get_rand(SHARED_ROOTS); _sr = shared_roots[num]; -k = get_rand(16); +k = get_rand(17); switch (k) { case 0: // remove a root @@ -324,7 +324,7 @@ pop_roots(); p = NULL; break; -case 15: +case 15: /* test stm_id on non-shared roots */ w_r = (nodeptr)read_barrier(_r); if (w_r-id) { assert(w_r-id == stm_id((gcptr)w_r)); @@ -335,6 +335,17 @@ w_r-id = stm_id((gcptr)w_r); assert(w_r-id == stm_id((gcptr)_r)); } +case 16: /* test stm_id on shared roots */ +w_sr = (nodeptr)read_barrier(_sr); +if (w_sr-id) { +assert(w_sr-id == stm_id((gcptr)w_sr)); +assert(w_sr-id == stm_id((gcptr)_sr)); +} +else { +w_sr = (nodeptr)write_barrier(_sr); +w_sr-id = stm_id((gcptr)w_sr); +assert(w_sr-id == stm_id((gcptr)_sr)); +} } return p; } diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -100,24 +100,34 @@ struct tx_descriptor *d = thread_descriptor; revision_t result; + if (p-h_original) { /* fast path */ +fprintf(stderr, stm_id(%p) has orig fst: %p\n, p, p-h_original); return p-h_original; +} +else if (!(p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) +(p-h_tid GCFLAG_OLD)) { +/* we can be sure that p-h_original doesn't + get set during the if and the else-if */ +fprintf(stderr, stm_id(%p) is old, orig=0 fst: %p\n, p, p); +return (revision_t)p; } spinlock_acquire(d-public_descriptor-collection_lock, 'I'); -if (p-h_original) { /* maybe now? */ -spinlock_release(d-public_descriptor-collection_lock); -return p-h_original; -} -/* old objects must have an h_original OR be +/* old objects must have an h_original xOR be the original itself. if some thread stole p when it was still young, it must have set h_original. stealing an old obj makes the old obj original. */ -if (p-h_tid GCFLAG_OLD) { +if (p-h_original) { /* maybe now? */ +result = p-h_original; +fprintf(stderr, stm_id(%p) has orig: %p\n, p, p-h_original); +} +else if (p-h_tid GCFLAG_OLD) { /* it must be this exact object */ result = (revision_t)p; +fprintf(stderr, stm_id(%p) is old, orig=0: %p\n, p, p); } else { /* must create shadow original object or use @@ -130,6 +140,8 @@ // B-h_tid |= GCFLAG_PUBLIC; done by CommitPrivateFromProtected result = (revision_t)B; +fprintf(stderr, stm_id(%p) young, pfp, use backup %p\n, +p, p-h_original); } else { gcptr O = stmgc_duplicate_old(p); @@ -138,6 +150,7 @@ O-h_tid |= GCFLAG_PUBLIC; result = (revision_t)O; +fprintf(stderr, stm_id(%p) young, make shadow %p\n, p, O); } } @@ -147,7 +160,9 @@ revision_t stm_pointer_equal(gcptr p1, gcptr p2) { -/* XXX: */ +/* types must be the same */ +if ((p1-h_tid STM_USER_TID_MASK) != (p2-h_tid STM_USER_TID_MASK)) +return 0; return stm_id(p1) == stm_id(p2); } diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -195,7 +195,11 @@ if needed */ O = stmgc_duplicate_old(L); L-h_revision = (revision_t)O; -L-h_original = (revision_t)O; + +/* young and without original? + we may lose the HAS_ID flag like above */ +if (!(L-h_original)) +L-h_original = (revision_t)O; } L-h_tid |= GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc implement-id: add simple tests
Author: Remi Meier meier...@student.ethz.ch Branch: implement-id Changeset: r228:d8b5144c17f4 Date: 2013-06-21 16:46 +0200 http://bitbucket.org/pypy/stmgc/changeset/d8b5144c17f4/ Log:add simple tests diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -13,7 +13,7 @@ #define NUMTHREADS 4 -#define STEPS 10 +#define STEPS 100 #define NUMROOTS 10 // per thread #define PREBUILT 3 // per thread #define MAXROOTS 1000 diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -102,7 +102,8 @@ if (p-h_original) { /* fast path */ -fprintf(stderr, stm_id(%p) has orig fst: %p\n, p, p-h_original); +fprintf(stderr, stm_id(%p) has orig fst: %p\n, +p, (gcptr)p-h_original); return p-h_original; } else if (!(p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) @@ -122,7 +123,8 @@ */ if (p-h_original) { /* maybe now? */ result = p-h_original; -fprintf(stderr, stm_id(%p) has orig: %p\n, p, p-h_original); +fprintf(stderr, stm_id(%p) has orig: %p\n, +p, (gcptr)p-h_original); } else if (p-h_tid GCFLAG_OLD) { /* it must be this exact object */ @@ -141,7 +143,7 @@ result = (revision_t)B; fprintf(stderr, stm_id(%p) young, pfp, use backup %p\n, -p, p-h_original); +p, (gcptr)p-h_original); } else { gcptr O = stmgc_duplicate_old(p); diff --git a/c4/test/support.py b/c4/test/support.py --- a/c4/test/support.py +++ b/c4/test/support.py @@ -42,6 +42,9 @@ #define PREBUILT_REVISION ... gcptr stm_allocate(size_t size, unsigned int tid); +revision_t stm_hash(gcptr); +revision_t stm_id(gcptr); +revision_t stm_pointer_equal(gcptr, gcptr); void stm_push_root(gcptr); gcptr stm_pop_root(void); void stm_set_max_aborts(int max_aborts); @@ -108,6 +111,7 @@ #define GCFLAG_NURSERY_MOVED ... #define GCFLAG_STUB ... #define GCFLAG_PRIVATE_FROM_PROTECTED ... +#define GCFLAG_HAS_ID... #define ABRT_MANUAL ... typedef struct { ...; } page_header_t; ''') @@ -607,4 +611,10 @@ assert (r % 4) == 0 return ffi.cast(gcptr, r) +def follow_original(p): +r = p.h_original +assert (r % 4) == 0 +return ffi.cast(gcptr, r) + + nrb_protected = ffi.cast(gcptr, -1) diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -198,6 +198,49 @@ assert p4 == p2 assert list_of_read_objects() == [p2] + +def test_id_young_to_old(): +# move out of nursery with shadow original +p = nalloc(HDR) +assert p.h_original == 0 +pid = lib.stm_id(p) +assert p.h_tid GCFLAG_HAS_ID +porig = follow_original(p) +assert porig.h_tid GCFLAG_OLD +lib.stm_push_root(p) +minor_collect() +p = lib.stm_pop_root() +assert not lib.in_nursery(p) +assert pid == lib.stm_id(p) + +def test_id_private_from_protected(): +# read and write from protected +p = oalloc(HDR) +pid = lib.stm_id(p) +porig = follow_original(p) +# impl detail { +# old objects have id==itself, if not set differently +assert porig == ffi.NULL +assert ffi.cast(gcptr, pid) == p +# } + +p1 = oalloc(HDR) +p1id = lib.stm_id(p1) +p1r = lib.stm_read_barrier(p1) +assert lib.stm_id(p1r) == p1id +p1w = lib.stm_write_barrier(p1) +assert lib.stm_id(p1w) == p1id + +p2 = oalloc(HDR) +p2w = lib.stm_write_barrier(p2) +p2id = lib.stm_id(p2) +assert p2id == lib.stm_id(p2w) +# impl detail { +assert p2w.h_original == 0 +assert follow_revision(p2w).h_original == lib.stm_id(p2w) +# } + + def test_stealing_old(): p = palloc(HDR + WORD) plist = [p] ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add some comments; add hash_mangling
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r248:78c58b8aabfa Date: 2013-06-24 09:10 +0200 http://bitbucket.org/pypy/stmgc/changeset/78c58b8aabfa/ Log:add some comments; add hash_mangling diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -88,13 +88,45 @@ } // - +/* Each object has a h_original pointer to an old copy of + the same object (e.g. an old revision), the original. + The memory location of this old object is used as the ID + for this object. If h_original is NULL *and* it is an + old object copy, it itself is the original. This invariant + must be upheld by all code dealing with h_original. + The original copy must never be moved again. Also, it may + be just a stub-object. + + If we want the ID of an object which is still young, + we must preallocate an old shadow-original that is used + as the target of the young object in a minor collection. + In this case, we set the HAS_ID flag on the young obj + to notify minor_collect. + This flag can be lost if the young obj is stolen. Then + the stealing thread uses the shadow-original itself and + minor_collect must not overwrite it again. + Also, if there is already a backup-copy around, we use + this instead of allocating another old object to use as + the shadow-original. + */ revision_t stm_hash(gcptr p) { return stm_id(p); } + +static revision_t mangle_hash(revision_t n) +{ +/* To hash pointers in dictionaries. Assumes that i shows some + alignment (to 4, 8, maybe 16 bytes), so we use the following + formula to avoid the trailing bits being always 0. + This formula is reversible: two different values of 'i' will + always give two different results. +*/ +return n ^ (n 4); +} + revision_t stm_id(gcptr p) { struct tx_descriptor *d = thread_descriptor; @@ -104,15 +136,23 @@ if (p-h_original) { /* fast path */ fprintf(stderr, stm_id(%p) has orig fst: %p\n, p, (gcptr)p-h_original); -return p-h_original; +return mangle_hash(p-h_original); } else if (!(p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) (p-h_tid GCFLAG_OLD)) { /* we can be sure that p-h_original doesn't - get set during the if and the else-if */ + get set during the if and the else-if + + XXX: check for priv_from_protected may not be + necessary. only if this func may be called on + another thread's young objects that are made + old at the same time, and we see the OLD flag + before h_original has been set. +*/ fprintf(stderr, stm_id(%p) is old, orig=0 fst: %p\n, p, p); -return (revision_t)p; +return mangle_hash((revision_t)p); } + spinlock_acquire(d-public_descriptor-collection_lock, 'I'); /* old objects must have an h_original xOR be @@ -137,7 +177,6 @@ if (p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { gcptr B = (gcptr)p-h_revision; /* don't set, otherwise nursery will copy over backup */ -//p-h_tid |= GCFLAG_HAS_ID; // see AbortPrivateFromProtected p-h_original = (revision_t)B; // B-h_tid |= GCFLAG_PUBLIC; done by CommitPrivateFromProtected @@ -157,7 +196,7 @@ } spinlock_release(d-public_descriptor-collection_lock); -return result; +return mangle_hash(result); } revision_t stm_pointer_equal(gcptr p1, gcptr p2) diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -93,7 +93,6 @@ assert(!(L-h_tid GCFLAG_HAS_ID)); /* original must be L */ B-h_original = (revision_t)L; -assert(0); } else { /* we can make the backup the original diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -216,12 +216,10 @@ def test_id_private_from_protected(): # read and write from protected p = oalloc(HDR) -pid = lib.stm_id(p) porig = follow_original(p) # impl detail { # old objects have id==itself, if not set differently assert porig == ffi.NULL -assert ffi.cast(gcptr, pid) == p # } p1 = oalloc(HDR) @@ -237,7 +235,6 @@ assert p2id == lib.stm_id(p2w) # impl detail { assert p2w.h_original == 0 -assert follow_revision(p2w).h_original == lib.stm_id(p2w) # } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add multiple thread start/finish to demo_random
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r249:c73629c0bb3c Date: 2013-06-24 09:41 +0200 http://bitbucket.org/pypy/stmgc/changeset/c73629c0bb3c/ Log:add multiple thread start/finish to demo_random diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -13,7 +13,8 @@ #define NUMTHREADS 4 -#define STEPS 100 +#define STEPS_PER_THREAD 5000 +#define THREAD_STARTS 100 // how many restarts of threads #define NUMROOTS 10 // per thread #define PREBUILT 3 // per thread #define MAXROOTS 1000 @@ -234,7 +235,7 @@ { int i; td.thread_seed = default_seed; -td.steps_left = STEPS; +td.steps_left = STEPS_PER_THREAD; td.interruptible = 0; td.num_roots = PREBUILT + NUMROOTS; @@ -250,8 +251,6 @@ gcptr do_step(gcptr p) { -fprintf(stdout, #); - nodeptr w_r, w_sr; gcptr _r, _sr; int num, k; @@ -394,6 +393,10 @@ gcptr p = NULL; while (td.steps_left) { td.steps_left--; + +if (td.steps_left % 8 == 0) +fprintf(stdout, #); + p = do_step(p); if (p == (gcptr)-1) @@ -453,13 +456,20 @@ status = sem_init(done, 0, 0); assert(status == 0); -for (i = 0; i NUMTHREADS; i++) +int thread_starts = NUMTHREADS * THREAD_STARTS; +for (i = 0; i NUMTHREADS; i++) { newthread(demo, NULL); +thread_starts--; +} -for (i=0; i NUMTHREADS; i++) { +for (i=0; i NUMTHREADS * THREAD_STARTS; i++) { status = sem_wait(done); assert(status == 0); printf(thread finished\n); +if (thread_starts) { +thread_starts--; +newthread(demo, NULL); +} } return 0; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: remove assert
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r252:6effbf62467f Date: 2013-06-24 10:48 +0200 http://bitbucket.org/pypy/stmgc/changeset/6effbf62467f/ Log:remove assert diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -1501,8 +1501,11 @@ assert(descriptor_array_free_list = 0); assert(pd-stolen_objects.size == 0); assert(pd-stolen_young_stubs.size == 0); - assert(pd-collection_lock == 0); pd-shutdown = 0; + /* there may be a thread holding the collection lock + because it steals a stub belonging to the thread + that previously owned this descriptor. + */ } else { /* no item in the free list */ ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: fix
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r253:500b2ca07505 Date: 2013-06-24 12:30 +0200 http://bitbucket.org/pypy/stmgc/changeset/500b2ca07505/ Log:fix diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -160,19 +160,18 @@ /* use id-copy for us */ O = (gcptr)L-h_original; L-h_tid = ~GCFLAG_HAS_ID; -L-h_revision = (revision_t)O; -copy_to_old_id_copy(L, (gcptr)L-h_original); +copy_to_old_id_copy(L, O); +O-h_original = 0; } else { /* Copy the object out of the other thread's nursery, if needed */ O = stmgc_duplicate_old(L); -L-h_revision = (revision_t)O; -/* young and without original? - we may lose the HAS_ID flag like above */ +/* young and without original? */ if (!(L-h_original)) L-h_original = (revision_t)O; } +L-h_revision = (revision_t)O; L-h_tid |= GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED; /* subtle: we need to remove L from the fxcache of the target diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -22,6 +22,7 @@ assert p.h_revision == r assert p.h_tid == lib.gettid(p) | 0# no GC flags assert classify(p) == private +assert lib.stm_id(p) != 0 def test_write_barrier_private(): p = nalloc(HDR) @@ -84,17 +85,20 @@ GCFLAG_PUBLIC | GCFLAG_PREBUILT_ORIGINAL) assert classify(p) == public +assert lib.stm_id(p) != 0 def test_prebuilt_object_to_private(): p = palloc(HDR) flags = p.h_tid assert (flags GCFLAG_PUBLIC_TO_PRIVATE) == 0 +pid = lib.stm_id(p) assert classify(p) == public p2 = lib.stm_write_barrier(p) assert p2 != p assert classify(p) == public assert classify(p2) == private assert p.h_tid == flags | GCFLAG_PUBLIC_TO_PRIVATE +assert pid == lib.stm_id(p2) def test_commit_change_to_prebuilt_object(): p = palloc(HDR + WORD) @@ -155,6 +159,7 @@ def test_read_barrier_public_to_private(): p = palloc(HDR) +pid = lib.stm_id(p) p2 = lib.stm_write_barrier(p) assert p2 != p assert classify(p) == public @@ -165,6 +170,7 @@ p3 = lib.stm_read_barrier(p) assert p3 == p2 assert list_of_read_objects() == [p] +assert pid == lib.stm_id(p2) def test_read_barrier_handle_protected(): p = palloc(HDR) @@ -231,8 +237,8 @@ p2 = oalloc(HDR) p2w = lib.stm_write_barrier(p2) -p2id = lib.stm_id(p2) -assert p2id == lib.stm_id(p2w) +p2id = lib.stm_id(p2w) +assert p2id == lib.stm_id(p2) # impl detail { assert p2w.h_original == 0 # } @@ -255,6 +261,8 @@ lib.rawsetlong(p1, 0, 2782172) lib.stm_commit_transaction() lib.stm_begin_inevitable_transaction() +p1id = lib.stm_id(p1) +assert p1id == lib.stm_id(p) assert classify(p) == public assert classify(p1) == protected plist.append(p1) # now p's most recent revision is protected @@ -265,9 +273,11 @@ assert classify(p1) == public assert lib.stm_read_barrier(p) == p1 assert lib.stm_read_barrier(p1) == p1 +assert lib.stm_id(p1) == p1id def f2(r): r.wait(2) p2 = lib.stm_read_barrier(p)# steals +assert lib.stm_id(p) == lib.stm_id(p2) assert classify(p2) == public assert lib.rawgetlong(p2, 0) == 2782172 assert p2 == lib.stm_read_barrier(p)# short-circuit h_revision @@ -297,8 +307,10 @@ plist.append(p1) # now p's most recent revision is protected assert classify(follow_revision(p)) == stub assert p1.h_revision 1 +p1id = lib.stm_id(p1) r.set(2) r.wait(3) +assert p1id == lib.stm_id(p1) assert classify(p1) == public assert (p1.h_revision 1) == 0# outdated p2 = ffi.cast(gcptr, p1.h_revision) @@ -310,6 +322,7 @@ def f2(r): r.wait(2) p2 = lib.stm_read_barrier(p)# steals +assert lib.stm_id(p) == lib.stm_id(p2) assert classify(p2) == public assert lib.rawgetlong(p2, 0) == 2782172 assert p2 == lib.stm_read_barrier(p)# short-circuit h_revision @@ -425,6 +438,8 @@ def test_stub_for_refs_from_stolen(old=False): p = palloc_refs(1) qlist = [] +qid = [] +pid = [] def f1(r): q1 = nalloc(HDR + WORD) if old: @@ -446,6 +461,16 @@ assert classify(p1) == protected assert classify(follow_revision(p)) == stub assert p1.h_revision 1 +pid.append(lib.stm_id(p1)) +assert classify(q1) == protected
[pypy-commit] stmgc default: more tests
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r254:78560280729a Date: 2013-06-24 13:42 +0200 http://bitbucket.org/pypy/stmgc/changeset/78560280729a/ Log:more tests diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -176,7 +176,7 @@ backup, if exists */ if (p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { gcptr B = (gcptr)p-h_revision; -/* don't set, otherwise nursery will copy over backup */ +/* don't set HAS_ID, otherwise nursery will copy over backup */ p-h_original = (revision_t)B; // B-h_tid |= GCFLAG_PUBLIC; done by CommitPrivateFromProtected diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -496,3 +496,77 @@ def test_stub_for_refs_from_stolen_old(): test_stub_for_refs_from_stolen(old=True) + + +def id_with_stealing(a=0, b=0): +p = palloc_refs(2) +qlist = [] +rlist = [] +qid = [] +pid = [] +rid = [] +def f1(r): +r1 = nalloc(HDR) +q1 = nalloc(HDR) +p1 = lib.stm_write_barrier(p) # private copy +qlist.append(q1) +rlist.append(r1) +if a: +# id on young priv +qid.append(lib.stm_id(q1)) +assert q1.h_tid GCFLAG_HAS_ID +if b: +# id on pub_to_priv +assert follow_original(p1) == p +pid.append(lib.stm_id(p1)) +assert not (p1.h_tid GCFLAG_HAS_ID) +lib.setptr(p1, 0, q1) +lib.setptr(p1, 1, r1) +lib.stm_commit_transaction() +lib.stm_begin_inevitable_transaction() +# p old public - stub - p1 young prot +# q1 young prot, r1 young prot +if not a: +# id on young prot +qid.append(lib.stm_id(q1)) +assert q1.h_tid GCFLAG_HAS_ID +if not b: +# id on young prot +assert follow_original(p1) == p +pid.append(lib.stm_id(p1)) +assert not (p1.h_tid GCFLAG_HAS_ID) + +r1w = lib.stm_write_barrier(r1) # priv_from_prot +assert r1w.h_tid GCFLAG_PRIVATE_FROM_PROTECTED +rid.append(lib.stm_id(r1w)) +assert not (r1w.h_tid GCFLAG_HAS_ID) # use backup +assert follow_original(r1w) == follow_revision(r1w) + +r.set(2) +r.wait(3) # wait until the other thread really started +def f2(r): +r.wait(2) +r.set(3) + +p2 = lib.stm_read_barrier(p)# steals +assert pid[-1] == lib.stm_id(p2) + +r2 = lib.getptr(p2, 1) +r3 = lib.stm_read_barrier(r2) +assert lib.stm_id(r3) == rid[-1] + +q2 = lib.getptr(p2, 0) +assert lib.stm_id(q2) == qid[-1] + +q3 = lib.stm_read_barrier(q2) +assert lib.stm_id(q3) == qid[-1] + +run_parallel(f1, f2) + +def test_id_with_stealing(): +id_with_stealing(1, 1) +id_with_stealing(1, 0) +id_with_stealing(0, 1) +id_with_stealing(0, 0) + + ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add support for predefined hash in prebuilt objects
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r256:67200f7bca96 Date: 2013-06-24 14:39 +0200 http://bitbucket.org/pypy/stmgc/changeset/67200f7bca96/ Log:add support for predefined hash in prebuilt objects diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -489,9 +489,13 @@ /* note that stmgc_duplicate() usually returns a young object, but may return an old one if the nursery is full at this moment. */ gcptr L = stmgc_duplicate(R); - if (!(L-h_original)) { -/* if we don't have an original object yet, - it must be the old public R */ + if (!(L-h_original) || L-h_tid GCFLAG_PREBUILT_ORIGINAL) { +/* if we don't have an original object yet, it must be the + old public R + Also, prebuilt objects may have a predefined hash stored + in the h_original. - point to the original copy on copies + of the prebuilt. +*/ assert(R-h_tid GCFLAG_OLD); // if not, force stm_id?? L-h_original = (revision_t)R; } diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -110,12 +110,6 @@ the shadow-original. */ -revision_t stm_hash(gcptr p) -{ -return stm_id(p); -} - - static revision_t mangle_hash(revision_t n) { /* To hash pointers in dictionaries. Assumes that i shows some @@ -127,13 +121,40 @@ return n ^ (n 4); } + +revision_t stm_hash(gcptr p) +{ +/* Prebuilt objects may have a specific hash stored in an extra + field. For now, we will simply always follow h_original and + see, if it is a prebuilt object (XXX: maybe propagate a flag + to all copies of a prebuilt to avoid this cache miss). + */ +if (p-h_original) { +if (p-h_tid GCFLAG_PREBUILT_ORIGINAL) { +return p-h_original; +} +gcptr orig = (gcptr)p-h_original; +if ((orig-h_tid GCFLAG_PREBUILT_ORIGINAL) orig-h_original) { +return orig-h_original; +} +} +return stm_id(p); +} + + revision_t stm_id(gcptr p) { struct tx_descriptor *d = thread_descriptor; revision_t result; - if (p-h_original) { /* fast path */ +if (p-h_tid GCFLAG_PREBUILT_ORIGINAL) { +/* h_original may contain a specific hash value, + but in case of the prebuilt original version, + its memory location is the id */ +return mangle_hash((revision_t)p); +} + fprintf(stderr, stm_id(%p) has orig fst: %p\n, p, (gcptr)p-h_original); return mangle_hash(p-h_original); @@ -152,6 +173,7 @@ fprintf(stderr, stm_id(%p) is old, orig=0 fst: %p\n, p, p); return mangle_hash((revision_t)p); } + spinlock_acquire(d-public_descriptor-collection_lock, 'I'); diff --git a/c4/test/support.py b/c4/test/support.py --- a/c4/test/support.py +++ b/c4/test/support.py @@ -91,6 +91,7 @@ void rawsetlong(gcptr, long, long); gcptr pseudoprebuilt(size_t size, int tid); +gcptr pseudoprebuilt_with_hash(size_t size, int tid, revision_t hash); revision_t get_private_rev_num(void); revision_t get_start_time(void); void *my_stub_thread(void); @@ -217,6 +218,13 @@ return x; } +gcptr pseudoprebuilt_with_hash(size_t size, int tid, revision_t hash) +{ +gcptr x = pseudoprebuilt(size, tid); +x-h_original = hash; +return x; +} + revision_t get_start_time(void) { return thread_descriptor-start_time; @@ -473,15 +481,22 @@ assert rawgetptr(p, i) == ffi.NULL # must already be zero-filled return p -def palloc(size): +def palloc(size, prehash=None): Get a ``prebuilt'' object. -p = lib.pseudoprebuilt(size, 42 + size) +if prehash is None: +p = lib.pseudoprebuilt(size, 42 + size) +else: +p = lib.pseudoprebuilt_with_hash(size, 42 + size, prehash) assert p.h_revision == 1 return p -def palloc_refs(nrefs): +def palloc_refs(nrefs, prehash=None): Get a ``prebuilt'' object with nrefs pointers. -p = lib.pseudoprebuilt(HDR + WORD * nrefs, 421 + nrefs) +if prehash is None: +p = lib.pseudoprebuilt(HDR + WORD * nrefs, 421 + nrefs) +else: +p = lib.pseudoprebuilt_with_hash(HDR + WORD * nrefs, + 421 + nrefs, prehash) return p gettid = lib.gettid diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -569,4 +569,44 @@ id_with_stealing(0, 1) id_with_stealing(0, 0) + +def test_prehash_simple(): +p = palloc(HDR, 99) +assert lib.stm_hash(p) == 99 +assert lib.stm_id(p) != lib.stm_hash(p) +pr = lib.stm_read_barrier(p) +assert lib.stm_hash(pr) == 99 +assert lib.stm_id(p) == lib.stm_id(pr) +pw = lib.stm_write_barrier(p) +assert lib.stm_hash(pw) == 99 +assert lib.stm_id(p) == lib.stm_id(pw) +lib.stm_push_root(pw) +
[pypy-commit] stmgc default: merge
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r259:076863fce4d4 Date: 2013-06-24 15:01 +0200 http://bitbucket.org/pypy/stmgc/changeset/076863fce4d4/ Log:merge diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py --- a/c4/test/test_gcpage.py +++ b/c4/test/test_gcpage.py @@ -383,3 +383,33 @@ p1 = lib.stm_pop_root() check_not_free(p1) check_not_free(lib.getptr(p1, 0)) + +def test_prebuilt_modified_during_transaction(): +p1 = palloc(HDR) +p2 = nalloc_refs(1) +lib.setptr(p2, 0, p1) +lib.stm_push_root(p2) +major_collect() +major_collect() +p1b = lib.stm_write_barrier(p1) +assert p1b != p1 +major_collect() +lib.stm_pop_root() +p1b = lib.stm_read_barrier(p1) +check_not_free(p1b) + +def test_prebuilt_modified_later(): +p1 = palloc(HDR) +p2 = nalloc_refs(1) +lib.setptr(p2, 0, p1) +lib.stm_push_root(p2) +major_collect() +major_collect() +p1b = lib.stm_write_barrier(p1) +assert p1b != p1 +lib.stm_commit_transaction() +lib.stm_begin_inevitable_transaction() +major_collect() +lib.stm_pop_root() +p1b = lib.stm_read_barrier(p1) +check_not_free(p1b) diff --git a/c4/test/test_random.py b/c4/test/test_random.py --- a/c4/test/test_random.py +++ b/c4/test/test_random.py @@ -522,4 +522,4 @@ def test_more_multi_thread(): #py.test.skip(more random tests) for i in range(200): -yield test_multi_thread, 1690 + i +yield test_multi_thread, 1751 + i ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add hash to demo_random, crashes sometimes..
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r263:05dae094fa06 Date: 2013-06-24 16:14 +0200 http://bitbucket.org/pypy/stmgc/changeset/05dae094fa06/ Log:add hash to demo_random, crashes sometimes.. diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -29,6 +29,7 @@ struct stm_object_s hdr; long value; revision_t id; +revision_t hash; struct node *next; }; typedef struct node * nodeptr; @@ -84,7 +85,14 @@ gcptr x = calloc(1, size); x-h_tid = PREBUILT_FLAGS | tid; x-h_revision = PREBUILT_REVISION; -x-h_original = 0; +return x; +} + +gcptr allocate_pseudoprebuilt_with_hash(size_t size, int tid, +revision_t hash) +{ +gcptr x = allocate_pseudoprebuilt(size, tid); +x-h_original = hash; return x; } @@ -240,8 +248,17 @@ td.num_roots = PREBUILT + NUMROOTS; for (i = 0; i PREBUILT; i++) { -td.roots[i] = allocate_pseudoprebuilt(sizeof(struct node), - GCTID_STRUCT_NODE); +if (i % 3 == 0) { +td.roots[i] = allocate_pseudoprebuilt_with_hash( + sizeof(struct node), + GCTID_STRUCT_NODE, + i); +((nodeptr)td.roots[i])-hash = i; +} +else { +td.roots[i] = allocate_pseudoprebuilt(sizeof(struct node), + GCTID_STRUCT_NODE); +} } for (i = PREBUILT; i PREBUILT + NUMROOTS; i++) { td.roots[i] = (gcptr)allocate_node(); @@ -251,17 +268,19 @@ gcptr do_step(gcptr p) { -nodeptr w_r, w_sr; -gcptr _r, _sr; +nodeptr w_r, w_sr, w_t; +gcptr _r, _sr, _t; int num, k; +_t = NULL; num = get_rand(td.num_roots); _r = td.roots[num]; - + num = get_rand(SHARED_ROOTS); _sr = shared_roots[num]; -k = get_rand(17); +k = get_rand(19); +check(p); switch (k) { case 0: // remove a root @@ -323,28 +342,42 @@ pop_roots(); p = NULL; break; -case 15: /* test stm_id on non-shared roots */ -w_r = (nodeptr)read_barrier(_r); -if (w_r-id) { -assert(w_r-id == stm_id((gcptr)w_r)); -assert(w_r-id == stm_id((gcptr)_r)); +case 15: /* test stm_id on (non-)shared roots */ +_t = _r; +case 16: +if (!_t) +_t = _sr; +w_t = (nodeptr)read_barrier(_t); +if (w_t-id) { +assert(w_t-id == stm_id((gcptr)w_t)); +assert(w_t-id == stm_id((gcptr)_t)); } else { -w_r = (nodeptr)write_barrier(_r); -w_r-id = stm_id((gcptr)w_r); -assert(w_r-id == stm_id((gcptr)_r)); +w_t = (nodeptr)write_barrier(_t); +w_t-id = stm_id((gcptr)w_t); +assert(w_t-id == stm_id((gcptr)_t)); } -case 16: /* test stm_id on shared roots */ -w_sr = (nodeptr)read_barrier(_sr); -if (w_sr-id) { -assert(w_sr-id == stm_id((gcptr)w_sr)); -assert(w_sr-id == stm_id((gcptr)_sr)); -} +break; +case 17: /* test stm_hash on (non-)shared roots */ +_t = _r; +case 18: +if (!_t) +_t = _sr; +w_t = (nodeptr)read_barrier(_t); +if (w_t-hash) { +assert(w_t-hash == stm_hash((gcptr)w_t)); +assert(w_t-hash == stm_hash((gcptr)_t)); +} else { -w_sr = (nodeptr)write_barrier(_sr); -w_sr-id = stm_id((gcptr)w_sr); -assert(w_sr-id == stm_id((gcptr)_sr)); +w_t = (nodeptr)write_barrier(_t); +w_t-hash = stm_hash((gcptr)w_t); +assert(w_t-hash == stm_hash((gcptr)_t)); } +if (w_t-hash PREBUILT || w_t-hash SHARED_ROOTS) { +// should be with predefined hash +assert (stm_id((gcptr)w_t) != stm_hash((gcptr)w_t)); +} +break; } return p; } @@ -449,8 +482,17 @@ default_seed = time(NULL) / 3600 / 24; for (i = 0; i SHARED_ROOTS; i++) { -shared_roots[i] = allocate_pseudoprebuilt(sizeof(struct node), - GCTID_STRUCT_NODE); +if (i % 3 == 0) { +shared_roots[i] = allocate_pseudoprebuilt_with_hash( + sizeof(struct node), + GCTID_STRUCT_NODE, + i); +((nodeptr)shared_roots[i])-hash = i; +} +else { +shared_roots[i] = allocate_pseudoprebuilt(sizeof(struct node), + GCTID_STRUCT_NODE); +} } status = sem_init(done, 0, 0);
[pypy-commit] stmgc default: merge
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r274:5634ab8d11f6 Date: 2013-06-25 14:01 +0200 http://bitbucket.org/pypy/stmgc/changeset/5634ab8d11f6/ Log:merge diff --git a/c4/Makefile b/c4/Makefile --- a/c4/Makefile +++ b/c4/Makefile @@ -2,14 +2,16 @@ # Makefile for the demos. # +DEBUG_EXE = debug-demo1 debug-demo2 debug-demo_random BUILD_EXE = build-demo1 build-demo2 build-demo_random -DEBUG_EXE = debug-demo1 debug-demo2 debug-demo_random +RELEASE_EXE = release-demo1 release-demo2 release-demo_random -build: $(BUILD_EXE) -debug: $(DEBUG_EXE) +debug: $(DEBUG_EXE) # with prints and asserts +build: $(BUILD_EXE) # without prints, but with asserts +release: $(RELEASE_EXE) # without prints nor asserts clean: - rm -f $(BUILD_EXE) $(DEBUG_EXE) + rm -f $(BUILD_EXE) $(DEBUG_EXE) $(RELEASE_EXE) H_FILES = atomic_ops.h stmgc.h stmimpl.h \ @@ -29,5 +31,8 @@ debug-%: %.c ${H_FILES} ${C_FILES} gcc -lrt -pthread ${DEBUG} $ -o debug-$* -Wall ${C_FILES} +release-%: %.c ${H_FILES} ${C_FILES} stmgc.c + gcc -lrt -pthread -DNDEBUG -O2 -g $ -o release-$* -Wall stmgc.c + test-%: ./$* 2/dev/null | grep check ok diff --git a/c4/demo1.c b/c4/demo1.c --- a/c4/demo1.c +++ b/c4/demo1.c @@ -11,7 +11,11 @@ #include fprintcolor.h -#define UPPER_BOUND 100 +#ifdef _GC_DEBUG +# define UPPER_BOUND 100 +#else +# define UPPER_BOUND 5000 +#endif #define NUMTHREADS 4 @@ -134,7 +138,8 @@ stm_finalize(); status = sem_post(done); -assert(status == 0); +if (status != 0) +stm_fatalerror(status != 0\n); return NULL; } @@ -158,7 +163,8 @@ { pthread_t th; int status = pthread_create(th, NULL, func, arg); - assert(status == 0); + if (status != 0) + stm_fatalerror(status != 0\n); pthread_detach(th); printf(started new thread\n); } @@ -168,7 +174,8 @@ int i, status; status = sem_init(done, 0, 0); - assert(status == 0); + if (status != 0) + stm_fatalerror(status != 0\n); for (i = 0; i NUMTHREADS; i++) newthread(demo1, NULL); @@ -176,7 +183,8 @@ for (i=0; i NUMTHREADS; i++) { status = sem_wait(done); - assert(status == 0); + if (status != 0) + stm_fatalerror(status != 0\n); printf(thread finished\n); } diff --git a/c4/demo2.c b/c4/demo2.c --- a/c4/demo2.c +++ b/c4/demo2.c @@ -97,23 +97,9 @@ r_current = (struct node*)stm_read_barrier((gcptr)r_next); r_next = (struct node*)stm_read_barrier((gcptr)tmp); } -// results from consecutive read_barriers can differ. needs Ptr_Eq() -int i = 0; -while (!(stm_read_barrier((gcptr)r_prev-next) == - stm_read_barrier((gcptr)r_current) - stm_read_barrier((gcptr)r_current-next) == - stm_read_barrier((gcptr)r_next))) { -asm volatile (pause:::memory); /* smp_spinloop() */ -i++; -assert(i 100); -} -// for now: -assert(((nodeptr)stm_read_barrier((gcptr)r_prev-next))-value - == r_current-value - - ((nodeptr)stm_read_barrier((gcptr)r_current-next))-value - == r_next-value); - +assert(stm_pointer_equal((gcptr)r_prev-next, (gcptr)r_current)); +assert(stm_pointer_equal((gcptr)r_current-next, (gcptr)r_next)); + r_prev = r_current; r_current = r_next; r_next = r_next-next; @@ -154,7 +140,8 @@ void final_check(void) { long sum; - + +printf(final check\n); stm_initialize(); sum = check_sorted(); @@ -171,7 +158,8 @@ { pthread_t th; int status = pthread_create(th, NULL, func, arg); -assert(status == 0); +if (status != 0) +stm_fatalerror(newthread: pthread_create failure\n); pthread_detach(th); printf(started new thread\n); } diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -473,7 +473,8 @@ { pthread_t th; int status = pthread_create(th, NULL, func, arg); -assert(status == 0); +if (status != 0) +stm_fatalerror(newthread: pthread_create failure\n); pthread_detach(th); printf(started new thread\n); } diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -305,6 +305,7 @@ static void _check_flags(gcptr P) { +#ifndef NDEBUG struct tx_descriptor *d = thread_descriptor; if (P-h_tid GCFLAG_STUB) { @@ -322,6 +323,7 @@ assert(is_old); dprintf((O )); } +#endif } gcptr _stm_nonrecord_barrier(gcptr P) @@ -962,7 +964,6 @@ static void CancelLocks(struct tx_descriptor *d) { - revision_t my_lock = d-my_lock; wlog_t *item; if (!g2l_any_entry(d-public_to_private)) @@ -984,7 +985,7 @@ if (v == expected) { - assert(R-h_revision != my_lock); + assert(R-h_revision != d-my_lock); break;/* done */
[pypy-commit] stmgc default: do not use backup as shadow-original, always use additional shadow
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r273:d01dac528994 Date: 2013-06-25 14:01 +0200 http://bitbucket.org/pypy/stmgc/changeset/d01dac528994/ Log:do not use backup as shadow-original, always use additional shadow diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -55,7 +55,6 @@ unsigned int thread_seed; gcptr roots[MAXROOTS]; gcptr roots_outside_perform[MAXROOTS]; -gcptr current_root; int num_roots; int num_roots_outside_perform; int steps_left; @@ -68,6 +67,12 @@ int classify(gcptr p); void check(gcptr p); +static int is_private(gcptr P) +{ + return (P-h_revision == stm_private_rev_num) || +(P-h_tid GCFLAG_PRIVATE_FROM_PROTECTED); +} + int get_rand(int max) { return (int)(rand_r(td.thread_seed) % (unsigned int)max); @@ -101,7 +106,8 @@ int i; for (i = 0; i td.num_roots; i++) { check(td.roots[i]); -stm_push_root(td.roots[i]); +if (td.roots[i]) +stm_push_root(td.roots[i]); } } @@ -109,7 +115,8 @@ { int i; for (i = td.num_roots - 1; i = 0; i--) { -td.roots[i] = stm_pop_root(); +if (td.roots[i]) +td.roots[i] = stm_pop_root(); check(td.roots[i]); } } @@ -173,6 +180,7 @@ check(p); w = stm_write_barrier(p); check(w); +assert(is_private(w)); } return w; } @@ -351,7 +359,7 @@ if (w_t-id) { assert(w_t-id == stm_id((gcptr)w_t)); assert(w_t-id == stm_id((gcptr)_t)); -} +} else { w_t = (nodeptr)write_barrier(_t); w_t-id = stm_id((gcptr)w_t); @@ -425,9 +433,7 @@ int run_me() { gcptr p = NULL; -while (td.steps_left) { -td.steps_left--; - +while (td.steps_left--0) { if (td.steps_left % 8 == 0) fprintf(stdout, #); diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -1120,14 +1120,6 @@ break; } } - else if (P-h_original == (revision_t)B) { -/* The backup is the id object */ -assert(!(P-h_tid GCFLAG_HAS_ID)); - -B-h_tid = ~GCFLAG_BACKUP_COPY; -B-h_tid |= GCFLAG_PUBLIC; -B-h_revision = (revision_t)P; - } else { stmgcpage_free(B); @@ -1159,7 +1151,7 @@ { assert(!(B-h_tid GCFLAG_BACKUP_COPY)); P-h_tid |= GCFLAG_PUBLIC; - P-h_tid = ~GCFLAG_HAS_ID; // just in case + assert(!(P-h_tid GCFLAG_HAS_ID)); if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; /* P becomes a public outdated object. It may create an exception documented in doc-objects.txt: a public but young @@ -1168,24 +1160,16 @@ stealing will follow its h_revision (to B). */ } - else if (P-h_original == (revision_t)B) { -/* The backup is the id object. P becomes outdated. */ -assert(!(P-h_tid GCFLAG_HAS_ID)); -P-h_tid |= GCFLAG_PUBLIC; -B-h_tid |= GCFLAG_PUBLIC; -B-h_tid = ~GCFLAG_BACKUP_COPY; -if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; - } else { /* copy the backup copy B back over the now-protected object P, and then free B, which will not be used any more. */ - + assert(!(P-h_original) + || (B-h_original == (revision_t)P-h_original)); + assert(!(P-h_original !B-h_original)); if (P-h_original !B-h_original) // might occur because of B-h_original = P-h_original; //replace_ptr_to_protected_with_stub - assert(!(P-h_original) - || (B-h_original == (revision_t)P-h_original)); size_t size = stmcb_size(B); assert(B-h_tid GCFLAG_BACKUP_COPY); memcpy(((char *)P) + offsetof(struct stm_object_s, h_revision), diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -159,18 +159,10 @@ p, (gcptr)p-h_original)); return p-h_original; } -else if (!(p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) -(p-h_tid GCFLAG_OLD)) { -/* we can be sure that p-h_original doesn't - get set during the if and the else-if - - XXX: check for priv_from_protected may not be - necessary. only if this func may be called on - another thread's young objects that are made - old at the same time, and we see the OLD flag - before h_original has been set. -*/ -dprintf((stm_id(%p) is old, orig=0 fst: %p\n, p, p)); +else if (p-h_tid GCFLAG_OLD) { +/* old objects must have an h_original xOR be + the original itself. */ +/* dprintf((stm_id(%p) is old, orig=0 fst: %p\n, p, p)); */ return (revision_t)p;
[pypy-commit] stmgc default: stm_id cleanups and fixes
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r275:d19d08d186b1 Date: 2013-06-25 15:31 +0200 http://bitbucket.org/pypy/stmgc/changeset/d19d08d186b1/ Log:stm_id cleanups and fixes diff --git a/c4/atomic_ops.h b/c4/atomic_ops.h --- a/c4/atomic_ops.h +++ b/c4/atomic_ops.h @@ -2,7 +2,7 @@ #define _SRCSTM_ATOMIC_OPS_ #include assert.h - +#define IMPLIES(a, b) (!(a) || (b)) /* Ask the compiler to really reload the revision_t argument from memory. That's all that this macro does; it does not imply any type of barrier. diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -1031,8 +1031,9 @@ stub-h_tid = (L-h_tid STM_USER_TID_MASK) | GCFLAG_PUBLIC | GCFLAG_STUB | GCFLAG_OLD; + stub-h_revision = ((revision_t)L) | 2; + assert(!(L-h_tid GCFLAG_HAS_ID)); - stub-h_revision = ((revision_t)L) | 2; if (L-h_original) { stub-h_original = L-h_original; } @@ -1040,8 +1041,14 @@ stub-h_original = (revision_t)L; } else { -L-h_original = (revision_t)stub; +/* There shouldn't be a public, young object without + a h_original. They only come from stealing which + always sets h_original */ assert(0); +/* L-h_original = (revision_t)stub; */ +/* if (L-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { */ +/* ((gcptr)L-h_revision)-h_original = (revision_t)stub; */ +/* } */ } item-val = stub; @@ -1165,12 +1172,6 @@ { /* copy the backup copy B back over the now-protected object P, and then free B, which will not be used any more. */ - assert(!(P-h_original) - || (B-h_original == (revision_t)P-h_original)); - assert(!(P-h_original !B-h_original)); - if (P-h_original !B-h_original) // might occur because of -B-h_original = P-h_original; //replace_ptr_to_protected_with_stub - size_t size = stmcb_size(B); assert(B-h_tid GCFLAG_BACKUP_COPY); memcpy(((char *)P) + offsetof(struct stm_object_s, h_revision), diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -162,7 +162,7 @@ else if (p-h_tid GCFLAG_OLD) { /* old objects must have an h_original xOR be the original itself. */ -/* dprintf((stm_id(%p) is old, orig=0 fst: %p\n, p, p)); */ +dprintf((stm_id(%p) is old, orig=0 fst: %p\n, p, p)); return (revision_t)p; } diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -53,7 +53,13 @@ stub-h_original = (revision_t)obj; } else { -obj-h_original = (revision_t)stub; +/* There shouldn't be a public, young object without + a h_original. But there can be protected ones. */ +assert(!(obj-h_tid GCFLAG_PUBLIC)); +obj-h_original = (revision_t)stub; +if (obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { +((gcptr)obj-h_revision)-h_original = (revision_t)stub; +} } g2l_insert(sd-all_stubs, obj, stub); @@ -93,23 +99,23 @@ if (L-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { gcptr B = (gcptr)L-h_revision; /* the backup copy */ -if (L-h_original) { -/* L has an original, may be GCFLAG_HAS_ID */ -B-h_original = L-h_original; -L-h_tid = ~GCFLAG_HAS_ID; -} -else if (L-h_tid GCFLAG_OLD) { -/* If old, it must be the original */ -assert(!(L-h_tid GCFLAG_HAS_ID)); -/* original must be L */ +/* On young objects here, h_original is always set + and never GCFLAG_HAS_ID. This is because a stealing + thread can only reach a priv_from_prot object through + public old stubs/objects that serve as originals if + needed. + If h_original is set, then it is already set in the + backup, too. +*/ +assert(!(L-h_tid GCFLAG_HAS_ID)); +assert(IMPLIES(!(L-h_tid GCFLAG_OLD), L-h_original)); +assert(IMPLIES(L-h_tid GCFLAG_OLD, + (B-h_original == (revision_t)L) + || (B-h_original == L-h_original))); +if (!L-h_original L-h_tid GCFLAG_OLD) { +/* If old, L must be the original */ B-h_original = (revision_t)L; } -else { -/* we can make the backup the original - since L hasn't decided yet */ -L-h_original = (revision_t)B; -assert(0); -} /* B is now a backup copy, i.e. a protected object, and we own the foreign thread's collection_lock, so we can read/write the diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -539,6 +539,7
[pypy-commit] stmgc default: clean only used part of nursery
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r279:0f3222c773e9 Date: 2013-06-25 16:51 +0200 http://bitbucket.org/pypy/stmgc/changeset/0f3222c773e9/ Log:clean only used part of nursery diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -516,7 +516,8 @@ dprintf((minor: nursery moved to [%p to %p]\n, d-nursery_base, d-nursery_end)); #else -memset(d-nursery_base, 0, GC_NURSERY); +memset(d-nursery_base, 0, + d-nursery_current - d-nursery_base); #endif d-nursery_current = d-nursery_base; diff --git a/c4/nursery.h b/c4/nursery.h --- a/c4/nursery.h +++ b/c4/nursery.h @@ -3,6 +3,7 @@ #ifndef GC_NURSERY #define GC_NURSERY4194304/* 4 MB */ +//#define GC_NURSERY(120)/* 1 MB */ #endif ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: fix validation of priv_from_prot
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r283:2e4480dc9707 Date: 2013-06-25 17:51 +0200 http://bitbucket.org/pypy/stmgc/changeset/2e4480dc9707/ Log:fix validation of priv_from_prot diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -330,6 +330,14 @@ p = (gcptr)(((nodeptr)read_barrier(p))-next); break; case 9: // XXX: rare events +k = get_rand(10); +if (k == 1) { +push_roots(); +stm_push_root(p); +stm_become_inevitable(fun); +p = stm_pop_root(); +pop_roots(); +} break; case 10: // only do a stm_read_barrier p = read_barrier(p); diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -652,12 +652,17 @@ { /* such an object R might be listed in list_of_read_objects before it was turned from protected to private */ - continue; + if(((gcptr)v)-h_tid GCFLAG_BACKUP_COPY) +continue; + /* the backup was stolen */ + return 0; } else if ((R-h_tid (GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED)) == (GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED)) { - /* such an object is identical to the one it points to */ + /* such an object is identical to the one it points to + (stolen protected young object with h_revision pointing + to the new copy) */ R = (gcptr)v; goto retry; } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: break the huge switch in demo_random
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r284:7b5404748520 Date: 2013-06-25 18:15 +0200 http://bitbucket.org/pypy/stmgc/changeset/7b5404748520/ Log:break the huge switch in demo_random diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -274,93 +274,97 @@ } -gcptr do_step(gcptr p) +gcptr rare_events(gcptr p, gcptr _r, gcptr _sr) { -nodeptr w_r, w_sr, w_t; -gcptr _r, _sr, _t; -int num, k; +int k = get_rand(10); +if (k == 1) { +push_roots(); +stm_push_root(p); +stm_become_inevitable(fun); +p = stm_pop_root(); +pop_roots(); +} +else if (k 4) { +push_roots(); +stmgc_minor_collect(); +pop_roots(); +p = NULL; +} +return p; +} -_t = NULL; -num = get_rand(td.num_roots); -_r = td.roots[num]; - -num = get_rand(SHARED_ROOTS); -_sr = shared_roots[num]; - -k = get_rand(19); -check(p); - +gcptr simple_events(gcptr p, gcptr _r, gcptr _sr) +{ +nodeptr w_r; +int k = get_rand(8); +int num = get_rand(td.num_roots); switch (k) { case 0: // remove a root if (num 0) del_root(num); break; -case 1: // set 'p' to point to a root +case 1: // add 'p' to roots +if (p td.num_roots MAXROOTS) +td.roots[td.num_roots++] = p; +break; +case 2: // set 'p' to point to a root if (_r) p = _r; break; -case 2: // add 'p' to roots -if (p td.num_roots MAXROOTS) -td.roots[td.num_roots++] = p; -break; case 3: // allocate fresh 'p' p = (gcptr)allocate_node(); break; -case 4: // set 'p' as *next in one of the roots +case 4: // read and validate 'p' +p = read_barrier(p); +break; +case 5: // only do a stm_write_barrier +p = write_barrier(p); +break; +case 6: // follow p-next +if (p) +p = (gcptr)(((nodeptr)read_barrier(p))-next); +break; +case 7: // set 'p' as *next in one of the roots check(_r); w_r = (nodeptr)write_barrier(_r); check((gcptr)w_r); check(p); w_r-next = (struct node*)p; break; -case 5: // read and validate 'p' -read_barrier(p); -break; -case 6: // transaction break -if (td.interruptible) -return (gcptr)-1; // break current -transaction_break(); -p = NULL; -break; -case 7: // only do a stm_write_barrier -p = write_barrier(p); -break; -case 8: -if (p) -p = (gcptr)(((nodeptr)read_barrier(p))-next); -break; -case 9: // XXX: rare events -k = get_rand(10); -if (k == 1) { -push_roots(); -stm_push_root(p); -stm_become_inevitable(fun); -p = stm_pop_root(); -pop_roots(); -} -break; -case 10: // only do a stm_read_barrier -p = read_barrier(p); -break; -case 11: +} +return p; +} + +gcptr shared_roots_events(gcptr p, gcptr _r, gcptr _sr) +{ +nodeptr w_sr; + +int k = get_rand(3); +switch (k) { +case 0: // read_barrier on shared root read_barrier(_sr); break; -case 12: +case 1: // write_barrier on shared root write_barrier(_sr); break; -case 13: +case 2: w_sr = (nodeptr)write_barrier(_sr); w_sr-next = (nodeptr)shared_roots[get_rand(SHARED_ROOTS)]; break; -case 14: -push_roots(); -stmgc_minor_collect(); -pop_roots(); -p = NULL; -break; -case 15: /* test stm_id on (non-)shared roots */ +} +return p; +} + +gcptr id_hash_events(gcptr p, gcptr _r, gcptr _sr) +{ +nodeptr w_t; +int k = get_rand(4); +gcptr _t = NULL; + +switch (k) { +case 0: /* test stm_id on (non-)shared roots */ _t = _r; -case 16: +case 1: if (!_t) _t = _sr; w_t = (nodeptr)read_barrier(_t); @@ -374,9 +378,9 @@ assert(w_t-id == stm_id((gcptr)_t)); } break; -case 17: /* test stm_hash on (non-)shared roots */ +case 2: /* test stm_hash on (non-)shared roots */ _t = _r; -case 18: +case 3: if (!_t) _t = _sr; w_t = (nodeptr)read_barrier(_t); @@ -400,6 +404,40 @@ } + +gcptr do_step(gcptr p) +{ +gcptr _r, _sr; +int num, k; + +num = get_rand(td.num_roots); +_r = td.roots[num]; + +num = get_rand(SHARED_ROOTS); +_sr = shared_roots[num]; + +k = get_rand(9); +check(p); + +if (k 3) +p = simple_events(p, _r, _sr); +else if (k 5) +p = shared_roots_events(p, _r, _sr); +else if (k 7) +p = id_hash_events(p, _r, _sr); +else if (k 8) +p =
[pypy-commit] stmgc default: add major collections to test
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r325:cf2cf2b3df21 Date: 2013-07-01 08:38 +0200 http://bitbucket.org/pypy/stmgc/changeset/cf2cf2b3df21/ Log:add major collections to test diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -19,6 +19,7 @@ #define PREBUILT 3 // per thread #define MAXROOTS 1000 #define SHARED_ROOTS 5 // shared by threads +#define DO_MAJOR_COLLECTS 1 @@ -276,19 +277,25 @@ gcptr rare_events(gcptr p, gcptr _r, gcptr _sr) { -int k = get_rand(10); -if (k == 1) { +int k = get_rand(100); +if (k 10) { push_roots(); stm_push_root(p); stm_become_inevitable(fun); p = stm_pop_root(); pop_roots(); } -else if (k 4) { +else if (k 40) { push_roots(); stmgc_minor_collect(); pop_roots(); p = NULL; +} else if (k 41 DO_MAJOR_COLLECTS) { +fprintf(stdout, major collect\n); +push_roots(); +stmgcpage_possibly_major_collect(1); +pop_roots(); +p = NULL; } return p; } @@ -418,6 +425,7 @@ k = get_rand(9); check(p); +assert(thread_descriptor-active); if (k 3) p = simple_events(p, _r, _sr); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: fix uninitialized shadowstack problem during major collection
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r326:18b8edd35778 Date: 2013-07-01 11:18 +0200 http://bitbucket.org/pypy/stmgc/changeset/18b8edd35778/ Log:fix uninitialized shadowstack problem during major collection diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -1504,7 +1504,6 @@ revision_t i; struct tx_descriptor *d = stm_malloc(sizeof(struct tx_descriptor)); memset(d, 0, sizeof(struct tx_descriptor)); - stmgcpage_acquire_global_lock(); struct tx_public_descriptor *pd; i = descriptor_array_free_list; @@ -1554,7 +1553,6 @@ (long)d-public_descriptor_index, (long)pthread_self())); stmgcpage_init_tls(); - stmgcpage_release_global_lock(); return 1; } else @@ -1567,7 +1565,6 @@ struct tx_descriptor *d = thread_descriptor; assert(d != NULL); assert(d-active == 0); -stmgcpage_acquire_global_lock(); /* our nursery is empty at this point. The list 'stolen_objects' should have been emptied at the previous minor collection and @@ -1585,7 +1582,6 @@ if (d-tx_prev != NULL) d-tx_prev-tx_next = d-tx_next; if (d-tx_next != NULL) d-tx_next-tx_prev = d-tx_prev; if (d == stm_tx_head) stm_tx_head = d-tx_next; -stmgcpage_release_global_lock(); thread_descriptor = NULL; diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -625,6 +625,7 @@ if (d != saved) { /* Hack: temporarily pretend that we are the other thread... */ +assert(d-shadowstack_end_ref *d-shadowstack_end_ref); thread_descriptor = d; stm_private_rev_num = *d-private_revision_ref; stm_read_barrier_cache = *d-read_barrier_cache_ref; diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -198,7 +198,8 @@ return (revision_t)p; } - +/* XXX: think about if p-h_original needs a volatile read + and if we need a memory fence (smp_wmb())... */ spinlock_acquire(d-public_descriptor-collection_lock, 'I'); /* old objects must have an h_original xOR be diff --git a/c4/stmsync.c b/c4/stmsync.c --- a/c4/stmsync.c +++ b/c4/stmsync.c @@ -79,12 +79,14 @@ void stm_initialize(void) { +stmgcpage_acquire_global_lock(); int r = DescriptorInit(); if (r != 1) stm_fatalerror(stm_initialize: DescriptorInit failure\n); stmgc_init_nursery(); init_shadowstack(); //stmgcpage_init_tls(); +stmgcpage_release_global_lock(); BeginInevitableTransaction(); } @@ -92,10 +94,12 @@ { stmgc_minor_collect(); /* force everything out of the nursery */ CommitTransaction(); +stmgcpage_acquire_global_lock(); //stmgcpage_done_tls(); done_shadowstack(); stmgc_done_nursery(); DescriptorDone(); +stmgcpage_release_global_lock(); } // ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add atomic transactions in demo_random
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r328:6eac0903bcb9 Date: 2013-07-01 12:32 +0200 http://bitbucket.org/pypy/stmgc/changeset/6eac0903bcb9/ Log:add atomic transactions in demo_random diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -60,6 +60,7 @@ int num_roots_outside_perform; int steps_left; int interruptible; +int atomic; }; __thread struct thread_data td; @@ -74,6 +75,24 @@ (P-h_tid GCFLAG_PRIVATE_FROM_PROTECTED); } +static void inc_atomic() +{ +assert(td.interruptible); +assert(stm_atomic(0) == td.atomic); +td.atomic++; +stm_atomic(1); +assert(stm_atomic(0) == td.atomic); +} + +static void dec_atomic() +{ +assert(td.interruptible); +assert(stm_atomic(0) == td.atomic); +td.atomic--; +stm_atomic(-1); +assert(stm_atomic(0) == td.atomic); +} + int get_rand(int max) { return (int)(rand_r(td.thread_seed) % (unsigned int)max); @@ -254,7 +273,8 @@ td.thread_seed = default_seed++; td.steps_left = STEPS_PER_THREAD; td.interruptible = 0; - +td.atomic = 0; + td.num_roots = PREBUILT + NUMROOTS; for (i = 0; i PREBUILT; i++) { if (i % 3 == 0) { @@ -303,7 +323,7 @@ gcptr simple_events(gcptr p, gcptr _r, gcptr _sr) { nodeptr w_r; -int k = get_rand(8); +int k = get_rand(11); int num = get_rand(td.num_roots); switch (k) { case 0: // remove a root @@ -338,6 +358,18 @@ check(p); w_r-next = (struct node*)p; break; +case 8: +if (td.interruptible) { +inc_atomic(); +} +break; +case 9: +case 10: +/* more likely to be less atomic */ +if (td.atomic) { +dec_atomic(); +} +break; } return p; } @@ -469,7 +501,7 @@ td.num_roots = td.num_roots_outside_perform; // done overwritten by the following pop_roots(): // copy_roots(td.roots_outside_perform, td.roots, td.num_roots); - +td.atomic = 0; // may be set differently on abort // refresh td.roots: gcptr end_marker = stm_pop_root(); assert(end_marker == END_MARKER_ON || end_marker == END_MARKER_OFF); @@ -490,14 +522,26 @@ int run_me() { gcptr p = NULL; -while (td.steps_left--0) { +while (td.steps_left--0 || td.atomic) { if (td.steps_left % 8 == 0) fprintf(stdout, #); p = do_step(p); -if (p == (gcptr)-1) -return -1; +if (p == (gcptr)-1) { +if (td.atomic) { +// can't break, well, we could return to perform_transaction +// while being atomic. (TODO) +// may be true when major gc requested: +// assert(stm_should_break_transaction() == 0); +assert(stm_atomic(0) == td.atomic); +p = NULL; +} +else { +assert(stm_atomic(0) == 0); +return -1; +} +} } return 0; } diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -906,6 +906,8 @@ long stm_atomic(long delta) { struct tx_descriptor *d = thread_descriptor; + if (delta) // no atomic-checks +dprintf((stm_atomic(%lu)\n, delta)); d-atomic += delta; assert(d-atomic = 0); update_reads_size_limit(d); diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -198,9 +198,6 @@ return (revision_t)p; } -/* XXX: think about if p-h_original needs a volatile read - and if we need a memory fence (smp_wmb())... */ - spinlock_acquire(d-public_descriptor-collection_lock, 'I'); /* old objects must have an h_original xOR be the original itself. @@ -222,7 +219,6 @@ gcptr O = stmgc_duplicate_old(p); p-h_original = (revision_t)O; p-h_tid |= GCFLAG_HAS_ID; -O-h_tid |= GCFLAG_PUBLIC; if (p-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { gcptr B = (gcptr)p-h_revision; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add build and release versions of demo_random to tests
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r337:d197afc97b0e Date: 2013-07-02 07:53 +0200 http://bitbucket.org/pypy/stmgc/changeset/d197afc97b0e/ Log:add build and release versions of demo_random to tests diff --git a/c4/test/test_zdemo_random.py b/c4/test/test_zdemo_random.py --- a/c4/test/test_zdemo_random.py +++ b/c4/test/test_zdemo_random.py @@ -2,7 +2,7 @@ import os import subprocess -def test_and_run(): +def test_and_run_debug(): path = os.path.dirname(__file__) path = os.path.dirname(path) res = subprocess.call([make, debug-demo_random], cwd=path) @@ -10,4 +10,19 @@ res = subprocess.call([./debug-demo_random], cwd=path) assert not res - +def test_and_run_build(): +path = os.path.dirname(__file__) +path = os.path.dirname(path) +res = subprocess.call([make, build-demo_random], cwd=path) +assert not res +res = subprocess.call([./build-demo_random], cwd=path) +assert not res + +def test_and_run_release(): +path = os.path.dirname(__file__) +path = os.path.dirname(path) +res = subprocess.call([make, release-demo_random], cwd=path) +assert not res +res = subprocess.call([./release-demo_random], cwd=path) +assert not res + ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: this assert can fail
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r338:2040cea49c77 Date: 2013-07-02 12:23 +0200 http://bitbucket.org/pypy/stmgc/changeset/2040cea49c77/ Log:this assert can fail diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -44,7 +44,11 @@ void stmgc_done_nursery(void) { struct tx_descriptor *d = thread_descriptor; -assert(!minor_collect_anything_to_do(d)); +/* someone may have called minor_collect_soon() + inbetween the preceeding minor_collect() and + this assert (committransaction() - + updatechainheads() - stub_malloc() - ...): */ +/* assert(!minor_collect_anything_to_do(d)); */ stm_free(d-nursery_base, GC_NURSERY); gcptrlist_delete(d-old_objects_to_trace); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add stm_thread_local_obj to demo_random.c
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r339:e7d1df97b6f0 Date: 2013-07-03 09:54 +0200 http://bitbucket.org/pypy/stmgc/changeset/e7d1df97b6f0/ Log:add stm_thread_local_obj to demo_random.c diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -293,6 +293,20 @@ td.roots[i] = (gcptr)allocate_node(); } +if (td.thread_seed % 3 == 0) { +stm_thread_local_obj = (gcptr)allocate_node(); +} +else if (td.thread_seed % 3 == 1) { +stm_thread_local_obj = allocate_pseudoprebuilt_with_hash +( + sizeof(struct node), GCTID_STRUCT_NODE, PREBUILT); +((nodeptr)stm_thread_local_obj)-hash = PREBUILT; +} +else { +stm_thread_local_obj = allocate_pseudoprebuilt +(sizeof(struct node), GCTID_STRUCT_NODE); +} + } gcptr rare_events(gcptr p, gcptr _r, gcptr _sr) @@ -432,7 +446,7 @@ w_t-hash = stm_hash((gcptr)w_t); assert(w_t-hash == stm_hash((gcptr)_t)); } -if (w_t-hash = 0 (w_t-hash PREBUILT || +if (w_t-hash = 0 (w_t-hash = PREBUILT || w_t-hash SHARED_ROOTS)) { // should be with predefined hash assert (stm_id((gcptr)w_t) != stm_hash((gcptr)w_t)); @@ -449,8 +463,11 @@ gcptr _r, _sr; int num, k; -num = get_rand(td.num_roots); -_r = td.roots[num]; +num = get_rand(td.num_roots+1); +if (num == 0) +_r = stm_thread_local_obj; +else +_r = td.roots[num - 1]; num = get_rand(SHARED_ROOTS); _sr = shared_roots[num]; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: add _GC_DEBUGPRINTS, comments, and some fairly untested code about tracing h_original in major_collections
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r344:f37e2b89a0fc Date: 2013-07-03 17:03 +0200 http://bitbucket.org/pypy/stmgc/changeset/f37e2b89a0fc/ Log:add _GC_DEBUGPRINTS, comments, and some fairly untested code about tracing h_original in major_collections diff --git a/c4/Makefile b/c4/Makefile --- a/c4/Makefile +++ b/c4/Makefile @@ -21,15 +21,16 @@ C_FILES = et.c lists.c steal.c nursery.c gcpage.c \ stmsync.c dbgmem.c fprintcolor.c -DEBUG = -g -DGC_NURSERY=0x1 -D_GC_DEBUG=1 +DEBUG = -g -DGC_NURSERY=0x1 -D_GC_DEBUG=1 -DDUMP_EXTRA=1 -D_GC_DEBUGPRINTS=1 -# note that we don't say -DNDEBUG, so that asserts should still be compiled it +# note that we don't say -DNDEBUG, so that asserts should still be compiled in +# also, all debug code with extra checks but not the debugprints build-%: %.c ${H_FILES} ${C_FILES} stmgc.c - gcc -pthread -O2 -g $ -o build-$* -Wall stmgc.c -lrt + gcc -pthread -DGC_NURSERY=0x1 -D_GC_DEBUG=1 -g $ -o build-$* -Wall stmgc.c -lrt debug-%: %.c ${H_FILES} ${C_FILES} - gcc -pthread ${DEBUG} $ -o debug-$* -Wall ${C_FILES} -lrt + gcc -pthread -DDUMP_EXTRA=1 ${DEBUG} $ -o debug-$* -Wall ${C_FILES} -lrt release-%: %.c ${H_FILES} ${C_FILES} stmgc.c gcc -pthread -DNDEBUG -O2 -g $ -o release-$* -Wall stmgc.c -lrt diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -105,6 +105,15 @@ *(to++) = *(from++); } +gcptr allocate_old(size_t size, int tid) +{ +gcptr p = stmgcpage_malloc(size); +memset(p, 0, size); +p-h_tid = GCFLAG_OLD | GCFLAG_WRITE_BARRIER | tid; +p-h_revision = -INT_MAX; +return p; +} + gcptr allocate_pseudoprebuilt(size_t size, int tid) { gcptr x = calloc(1, size); @@ -166,6 +175,15 @@ return 0; } +#ifdef _GC_DEBUG +int is_free_old(gcptr p) +{ +fprintf(stdout, \n=== check ===\n); +return (!_stm_can_access_memory((char*)p)) +|| (p-h_tid == DEBUG_WORD(0xDD)); +} +#endif + void check_not_free(gcptr p) { assert(p != NULL); @@ -179,6 +197,16 @@ if (p != NULL) { check_not_free(p); classify(p); // additional asserts +if (p-h_original !(p-h_tid GCFLAG_PREBUILT_ORIGINAL)) { +// must point to valid old object +gcptr id = (gcptr)p-h_original; +assert(id-h_tid GCFLAG_OLD); +check_not_free(id); +#ifdef _GC_DEBUG +if (!is_shared_prebuilt(id) !(id-h_tid GCFLAG_PREBUILT)) +assert(!is_free_old(id)); +#endif +} } } diff --git a/c4/fprintcolor.c b/c4/fprintcolor.c --- a/c4/fprintcolor.c +++ b/c4/fprintcolor.c @@ -5,7 +5,7 @@ { va_list ap; -#ifdef _GC_DEBUG +#ifdef _GC_DEBUGPRINTS dprintf((STM Subsystem: Fatal Error\n)); #else fprintf(stderr, STM Subsystem: Fatal Error\n); @@ -19,7 +19,7 @@ } -#ifdef _GC_DEBUG +#ifdef _GC_DEBUGPRINTS static __thread revision_t tcolor = 0; static revision_t tnextid = 0; diff --git a/c4/fprintcolor.h b/c4/fprintcolor.h --- a/c4/fprintcolor.h +++ b/c4/fprintcolor.h @@ -6,7 +6,7 @@ __attribute__((format (printf, 1, 2), noreturn)); -#ifdef _GC_DEBUG +#ifdef _GC_DEBUGPRINTS #define dprintf(args) threadcolor_printf args int dprintfcolor(void); diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -235,6 +235,15 @@ if (!(obj-h_revision 2)) { /* go visit the more recent version */ obj = (gcptr)obj-h_revision; +if ((gcptr)obj-h_original == prev_obj + !(prev_obj-h_tid GCFLAG_VISITED)) { +assert(0); // why never hit? +// prev_obj is the ID copy +prev_obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; +/* see fix_outdated() */ +prev_obj-h_tid |= GCFLAG_VISITED; +gcptrlist_insert(objects_to_trace, prev_obj); +} } else { /* it's a stub: keep it if it points to a protected version, @@ -244,7 +253,11 @@ */ assert(obj-h_tid GCFLAG_STUB); obj = (gcptr)(obj-h_revision - 2); -if (!(obj-h_tid GCFLAG_PUBLIC)) { +if (!(obj-h_tid GCFLAG_PUBLIC) || !(prev_obj-h_original)) { +assert(prev_obj-h_original); // why never hit? +assert(!(obj-h_tid GCFLAG_PUBLIC)); +/* never?: stub-public where stub is id copy? */ + prev_obj-h_tid |= GCFLAG_VISITED; assert(*pobj == prev_obj); gcptr obj1 = obj; @@ -256,6 +269,9 @@ } if (!(obj-h_revision 3)) { +/* obj is neither a stub nor a most recent revision: + completely ignore obj-h_revision */ + obj = (gcptr)obj-h_revision; assert(obj-h_tid GCFLAG_PUBLIC); prev_obj-h_revision = (revision_t)obj; @@ -274,7 +290,21 @@
[pypy-commit] stmgc default: add test and fix
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r346:38fcfb8212e2 Date: 2013-07-04 10:27 +0200 http://bitbucket.org/pypy/stmgc/changeset/38fcfb8212e2/ Log:add test and fix diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -220,6 +220,11 @@ hash in h_original */ if (id_copy !(obj-h_tid GCFLAG_PREBUILT_ORIGINAL)) { if (!(id_copy-h_tid GCFLAG_PREBUILT_ORIGINAL)) { +id_copy-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; +/* see fix_outdated() */ +id_copy-h_tid |= GCFLAG_VISITED; + +/* XXX: may not always need tracing? */ gcptrlist_insert(objects_to_trace, id_copy); } else { diff --git a/c4/test/support.py b/c4/test/support.py --- a/c4/test/support.py +++ b/c4/test/support.py @@ -298,6 +298,8 @@ undef_macros=['NDEBUG'], define_macros=[('GC_NURSERY', str(16 * WORD)), ('_GC_DEBUG', '2'), +('_GC_DEBUGPRINTS', '1'), +('DUMP_EXTRA', '1'), ('GC_PAGE_SIZE', '1000'), ('GC_MIN', '20'), ('GC_EXPAND', '9'), @@ -576,6 +578,13 @@ if p1.h_tid GCFLAG_PREBUILT_ORIGINAL: lib.stm_add_prebuilt_root(p1) +def delegate_original(p1, p2): +assert p1.h_original == 0 +assert p2.h_original == 0 +assert p1 != p2 +p2.h_original = ffi.cast(revision_t, p1) + + def make_public(p1): Hack at an object returned by oalloc() to force it public. assert classify(p1) == protected diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py --- a/c4/test/test_gcpage.py +++ b/c4/test/test_gcpage.py @@ -200,6 +200,20 @@ assert p3 != p2 assert p3 == lib.stm_write_barrier(p2) +def test_new_version_id_alive(): +p1 = oalloc(HDR); make_public(p1) +p2 = oalloc(HDR); make_public(p2) +delegate(p1, p2) +delegate_original(p1, p2) +p2.h_original = ffi.cast(revision_t, p1) +lib.stm_push_root(p1) +major_collect() +major_collect() +p1b = lib.stm_pop_root() +check_not_free(p1) # id copy +check_not_free(p2) + + def test_new_version_kill_intermediate(): p1 = oalloc(HDR); make_public(p1) p2 = oalloc(HDR); make_public(p2) @@ -249,6 +263,34 @@ print 'p5:', p5 assert rawgetptr(p1, 0) == p5 +def test_new_version_not_kill_intermediate_original(): +p1 = oalloc_refs(1); make_public(p1) +p2 = oalloc(HDR);make_public(p2) +p3 = oalloc(HDR);make_public(p3) +p4 = oalloc(HDR);make_public(p4) +p5 = oalloc(HDR);make_public(p5) +delegate(p2, p3) +delegate(p3, p4) +delegate(p4, p5) +rawsetptr(p1, 0, p3) +delegate_original(p3, p1) +delegate_original(p3, p2) +delegate_original(p3, p4) +delegate_original(p3, p5) + +lib.stm_push_root(p1) +major_collect() +lib.stm_pop_root() +check_not_free(p1) +check_free_old(p2) +check_not_free(p3) # original +check_free_old(p4) +check_not_free(p5) +assert rawgetptr(p1, 0) == p5 +assert follow_original(p1) == p3 +assert follow_original(p5) == p3 + + def test_prebuilt_version_1(): p1 = lib.pseudoprebuilt(HDR, 42 + HDR) check_prebuilt(p1) ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: refactor keeping alive the h_originals in major collections
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r345:7ae6aa7d16af Date: 2013-07-04 09:26 +0200 http://bitbucket.org/pypy/stmgc/changeset/7ae6aa7d16af/ Log:refactor keeping alive the h_originals in major collections diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -212,6 +212,24 @@ static struct GcPtrList objects_to_trace; +static void keep_original_alive(gcptr obj) +{ +/* keep alive the original of a visited object */ +gcptr id_copy = (gcptr)obj-h_original; +/* prebuilt original objects may have a predifined + hash in h_original */ +if (id_copy !(obj-h_tid GCFLAG_PREBUILT_ORIGINAL)) { +if (!(id_copy-h_tid GCFLAG_PREBUILT_ORIGINAL)) { +gcptrlist_insert(objects_to_trace, id_copy); +} +else { +/* prebuilt originals won't get collected anyway + and if they are not reachable in any other way, + we only ever need their location, not their content */ +} +} +} + static void visit(gcptr *pobj) { gcptr obj = *pobj; @@ -226,6 +244,8 @@ obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ obj-h_tid |= GCFLAG_VISITED; gcptrlist_insert(objects_to_trace, obj); + +keep_original_alive(obj); } } else if (obj-h_tid GCFLAG_PUBLIC) { @@ -235,15 +255,6 @@ if (!(obj-h_revision 2)) { /* go visit the more recent version */ obj = (gcptr)obj-h_revision; -if ((gcptr)obj-h_original == prev_obj - !(prev_obj-h_tid GCFLAG_VISITED)) { -assert(0); // why never hit? -// prev_obj is the ID copy -prev_obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; -/* see fix_outdated() */ -prev_obj-h_tid |= GCFLAG_VISITED; -gcptrlist_insert(objects_to_trace, prev_obj); -} } else { /* it's a stub: keep it if it points to a protected version, @@ -253,12 +264,10 @@ */ assert(obj-h_tid GCFLAG_STUB); obj = (gcptr)(obj-h_revision - 2); -if (!(obj-h_tid GCFLAG_PUBLIC) || !(prev_obj-h_original)) { -assert(prev_obj-h_original); // why never hit? -assert(!(obj-h_tid GCFLAG_PUBLIC)); -/* never?: stub-public where stub is id copy? */ +if (!(obj-h_tid GCFLAG_PUBLIC)) { +prev_obj-h_tid |= GCFLAG_VISITED; +keep_original_alive(prev_obj); -prev_obj-h_tid |= GCFLAG_VISITED; assert(*pobj == prev_obj); gcptr obj1 = obj; visit(obj1); /* recursion, but should be only once */ @@ -291,18 +300,11 @@ gcptr B = (gcptr)obj-h_revision; assert(B-h_tid (GCFLAG_PUBLIC | GCFLAG_BACKUP_COPY)); -gcptr id_copy = (gcptr)obj-h_original; -if (id_copy id_copy != B) { -assert(id_copy == (gcptr)B-h_original); +if (obj-h_original (gcptr)obj-h_original != B) { +/* if B is original, it will be visited anyway */ +assert(obj-h_original == B-h_original); assert(!(obj-h_tid GCFLAG_PREBUILT_ORIGINAL)); -if (!(id_copy-h_tid GCFLAG_PREBUILT_ORIGINAL)) { -gcptrlist_insert(objects_to_trace, id_copy); -} -else { -/* prebuilt originals won't get collected anyway - and if they are not reachable in any other way, - we only ever need their location, not their content */ -} +keep_original_alive(obj); } obj-h_tid |= GCFLAG_VISITED; @@ -323,6 +325,7 @@ } } + static void visit_keep(gcptr obj) { if (!(obj-h_tid GCFLAG_VISITED)) { @@ -334,6 +337,7 @@ assert(!(obj-h_revision 2)); visit((gcptr *)obj-h_revision); } +keep_original_alive(obj); } } diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -266,7 +266,7 @@ return fresh_old_copy; } -inline void copy_to_old_id_copy(gcptr obj, gcptr id) +void copy_to_old_id_copy(gcptr obj, gcptr id) { assert(!is_in_nursery(thread_descriptor, id)); assert(id-h_tid GCFLAG_OLD); diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -1,7 +1,7 @@ #include stmimpl.h -inline void copy_to_old_id_copy(gcptr obj, gcptr id); +void copy_to_old_id_copy(gcptr obj, gcptr id); gcptr stm_stub_malloc(struct tx_public_descriptor *pd) { ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: merge
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r350:93309df73f62 Date: 2013-07-05 09:46 +0200 http://bitbucket.org/pypy/stmgc/changeset/93309df73f62/ Log:merge diff --git a/duhton/duhton.c b/duhton/duhton.c --- a/duhton/duhton.c +++ b/duhton/duhton.c @@ -1,20 +1,40 @@ #include duhton.h +#define DEFAULT_NUM_THREADS 4 int main(int argc, char **argv) { -char *filename; -int interactive; -if (argc = 1) { +char *filename = NULL; +int interactive = 1; + int i; + int num_threads = DEFAULT_NUM_THREADS; + + for (i = 1; i argc; ++i) { + if (strcmp(argv[i], --help) == 0) { + printf(Duhton: a simple lisp-like language with STM support\n\n); + printf(Usage: duhton [--help] [--num-threads no] [filename]\n); + printf( --help: this help\n); + printf( --num-threads number: number of threads (default 4)\n\n); + exit(0); + } else if (strcmp(argv[i], --num-threads) == 0) { + if (i == argc - 1) { + printf(ERROR: --num-threads requires a parameter\n); + exit(1); + } + num_threads = atoi(argv[i + 1]); + i++; + } else if (strncmp(argv[i], --, 2) == 0) { + printf(ERROR: unrecognized parameter %s\n, argv[i]); + } else { + filename = argv[i]; + interactive = 0; + } + } +if (!filename) { filename = -; /* stdin */ -interactive = 1; -} -else { -filename = argv[1]; -interactive = 0; -} + } -Du_Initialize(); +Du_Initialize(num_threads); while (1) { if (interactive) { diff --git a/duhton/duhton.h b/duhton/duhton.h --- a/duhton/duhton.h +++ b/duhton/duhton.h @@ -138,7 +138,7 @@ DuObject *rest, int execute_now); DuObject *_Du_GetGlobals(void); -void Du_Initialize(void); +void Du_Initialize(int); void Du_Finalize(void); #define Du_Globals(_Du_GetGlobals()) @@ -182,5 +182,7 @@ } #endif +extern pthread_t *all_threads; +extern int all_threads_count; #endif /* _DUHTON_H_ */ diff --git a/duhton/glob.c b/duhton/glob.c --- a/duhton/glob.c +++ b/duhton/glob.c @@ -1,6 +1,8 @@ #include duhton.h #include sys/select.h +pthread_t *all_threads; +int all_threads_count; static void _du_getargs1(const char *name, DuObject *cons, DuObject *locals, DuObject **a) @@ -561,9 +563,11 @@ return Du_None; } -void Du_Initialize(void) +void Du_Initialize(int num_threads) { stm_initialize(); + all_threads_count = num_threads; + all_threads = (pthread_t*)malloc(sizeof(pthread_t) * num_threads); DuFrame_SetBuiltinMacro(Du_Globals, progn, Du_Progn); DuFrame_SetBuiltinMacro(Du_Globals, setq, du_setq); diff --git a/duhton/transaction.c b/duhton/transaction.c --- a/duhton/transaction.c +++ b/duhton/transaction.c @@ -2,10 +2,6 @@ #include pthread.h #include unistd.h -#ifndef NUM_THREADS -#define NUM_THREADS 4 -#endif - static DuConsObject du_pending_transactions = { DuOBJECT_HEAD_INIT(DUTYPE_CONS), @@ -21,15 +17,13 @@ static void run_all_threads(void) { int i; -pthread_t th[NUM_THREADS]; - -for (i = 0; i NUM_THREADS; i++) { -int status = pthread_create(th[i], NULL, run_thread, NULL); +for (i = 0; i all_threads_count; i++) { +int status = pthread_create(all_threads[i], NULL, run_thread, NULL); if (status != 0) stm_fatalerror(status != 0\n); } -for (i = 0; i NUM_THREADS; i++) { -pthread_join(th[i], NULL); +for (i = 0; i all_threads_count; i++) { +pthread_join(all_threads[i], NULL); } } @@ -88,13 +82,13 @@ else { /* nothing to do, wait */ thread_sleeping++; -if (thread_sleeping == NUM_THREADS) { +if (thread_sleeping == all_threads_count) { pthread_mutex_unlock(mutex_sleep); } stm_commit_transaction(); pthread_mutex_lock(mutex_sleep); stm_begin_inevitable_transaction(); -if (thread_sleeping == NUM_THREADS) { +if (thread_sleeping == all_threads_count) { pthread_mutex_unlock(mutex_sleep); return NULL; } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: fix: don't trace stubs
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r349:de365b519570 Date: 2013-07-05 09:45 +0200 http://bitbucket.org/pypy/stmgc/changeset/de365b519570/ Log:fix: don't trace stubs diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -225,7 +225,8 @@ id_copy-h_tid |= GCFLAG_VISITED; /* XXX: may not always need tracing? */ -gcptrlist_insert(objects_to_trace, id_copy); +if (!(id_copy-h_tid GCFLAG_STUB)) +gcptrlist_insert(objects_to_trace, id_copy); } else { /* prebuilt originals won't get collected anyway diff --git a/duhton/Makefile b/duhton/Makefile --- a/duhton/Makefile +++ b/duhton/Makefile @@ -5,7 +5,7 @@ gcc -pthread -g -O2 -o duhton *.c ../c4/stmgc.c -Wall -lrt duhton_debug: *.c *.h ../c4/*.c ../c4/*.h - gcc -pthread -g -DDu_DEBUG -D_GC_DEBUG=2 -DGC_NURSERY=2048 -o duhton_debug *.c ../c4/stmgc.c -Wall -lrt + gcc -pthread -g -DDu_DEBUG -D_GC_DEBUGPRINTS=1 -DGC_NURSERY=2048 -o duhton_debug *.c ../c4/stmgc.c -Wall -lrt clean: rm -f duhton duhton_debug ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: fix some tests
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65190:b3adf69b07ae Date: 2013-07-05 10:46 +0200 http://bitbucket.org/pypy/pypy/changeset/b3adf69b07ae/ Log:fix some tests diff --git a/pypy/module/thread/stm.py b/pypy/module/thread/stm.py --- a/pypy/module/thread/stm.py +++ b/pypy/module/thread/stm.py @@ -5,7 +5,7 @@ from pypy.module.thread.threadlocals import BaseThreadLocals from pypy.module.thread.error import wrap_thread_error from pypy.interpreter.executioncontext import ExecutionContext -from pypy.interpreter.gateway import Wrappable, W_Root, interp2app +from pypy.interpreter.gateway import W_Root, interp2app from pypy.interpreter.typedef import TypeDef, GetSetProperty, descr_get_dict from rpython.rlib import rthread from rpython.rlib import rstm @@ -122,7 +122,7 @@ # -class STMLocal(Wrappable): +class STMLocal(W_Root): Thread-local data @jit.dont_look_inside diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py --- a/rpython/rlib/rstm.py +++ b/rpython/rlib/rstm.py @@ -28,13 +28,13 @@ def abort_info_pop(count): if we_are_translated(): -stmgcintf.StmOperations.abort_info_pop(count) +pass #stmgcintf.StmOperations.abort_info_pop(count) def charp_inspect_abort_info(): -return stmgcintf.StmOperations.inspect_abort_info() +pass # return stmgcintf.StmOperations.inspect_abort_info() def abort_and_retry(): -stmgcintf.StmOperations.abort_and_retry() +pass # stmgcintf.StmOperations.abort_and_retry() def before_external_call(): llop.stm_commit_transaction(lltype.Void) diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -584,28 +584,30 @@ from rpython.translator.stm.funcgen import op_stm self.__class__.op_stm = op_stm return self.op_stm(op) -OP_STM_INITIALIZE = _OP_STM -OP_STM_FINALIZE = _OP_STM -OP_STM_BECOME_INEVITABLE = _OP_STM -OP_STM_BARRIER = _OP_STM -OP_STM_PTR_EQ = _OP_STM -OP_STM_PUSH_ROOT = _OP_STM -OP_STM_POP_ROOT_INTO = _OP_STM -OP_STM_ALLOCATE = _OP_STM -OP_STM_GET_TID = _OP_STM -OP_STM_HASH = _OP_STM -OP_STM_ID = _OP_STM -OP_STM_COMMIT_TRANSACTION = _OP_STM +OP_STM_INITIALIZE = _OP_STM +OP_STM_FINALIZE = _OP_STM +OP_STM_BECOME_INEVITABLE= _OP_STM +OP_STM_BARRIER = _OP_STM +OP_STM_PTR_EQ = _OP_STM +OP_STM_PUSH_ROOT= _OP_STM +OP_STM_POP_ROOT_INTO= _OP_STM +OP_STM_ALLOCATE = _OP_STM +OP_STM_GET_TID = _OP_STM +OP_STM_HASH = _OP_STM +OP_STM_ID = _OP_STM +OP_STM_COMMIT_TRANSACTION = _OP_STM OP_STM_BEGIN_INEVITABLE_TRANSACTION = _OP_STM -OP_STM_SHOULD_BREAK_TRANSACTION = _OP_STM -OP_STM_SET_TRANSACTION_LENGTH = _OP_STM -OP_STM_CHANGE_ATOMIC = _OP_STM -OP_STM_GET_ATOMIC = _OP_STM -OP_STM_THREADLOCAL_GET = _OP_STM -OP_STM_THREADLOCAL_SET = _OP_STM -OP_STM_PERFORM_TRANSACTION = _OP_STM -OP_STM_ENTER_CALLBACK_CALL = _OP_STM -OP_STM_LEAVE_CALLBACK_CALL = _OP_STM +OP_STM_SHOULD_BREAK_TRANSACTION = _OP_STM +OP_STM_SET_TRANSACTION_LENGTH = _OP_STM +OP_STM_CHANGE_ATOMIC= _OP_STM +OP_STM_GET_ATOMIC = _OP_STM +OP_STM_THREADLOCAL_GET = _OP_STM +OP_STM_THREADLOCAL_SET = _OP_STM +OP_STM_PERFORM_TRANSACTION = _OP_STM +OP_STM_ENTER_CALLBACK_CALL = _OP_STM +OP_STM_LEAVE_CALLBACK_CALL = _OP_STM +OP_STM_MAJOR_COLLECT= _OP_STM +OP_STM_MINOR_COLLECT= _OP_STM def OP_PTR_NONZERO(self, op): diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py --- a/rpython/translator/stm/funcgen.py +++ b/rpython/translator/stm/funcgen.py @@ -159,6 +159,13 @@ arg0 = funcgen.expr(op.args[0]) return 'stm_leave_callback_call(%s);' % (arg0,) +def stm_minor_collect(funcgen, op): +return 'stmgc_minor_collect();' + +def stm_major_collect(funcgen, op): +return 'stmgcpage_possibly_major_collect(1);}' # forced + + def op_stm(funcgen, op): func = globals()[op.opname] diff --git a/rpython/translator/stm/src_stm/gcpage.c b/rpython/translator/stm/src_stm/gcpage.c --- a/rpython/translator/stm/src_stm/gcpage.c +++ b/rpython/translator/stm/src_stm/gcpage.c @@ -226,7 +226,8 @@ id_copy-h_tid |= GCFLAG_VISITED; /* XXX: may not always need tracing? */ -gcptrlist_insert(objects_to_trace, id_copy); +if (!(id_copy-h_tid GCFLAG_STUB)) +gcptrlist_insert(objects_to_trace, id_copy); }
[pypy-commit] pypy stmgc-c4: fix test
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65188:3f384e7615a0 Date: 2013-07-04 11:10 +0200 http://bitbucket.org/pypy/pypy/changeset/3f384e7615a0/ Log:fix test diff --git a/rpython/translator/stm/test/test_inevitable.py b/rpython/translator/stm/test/test_inevitable.py --- a/rpython/translator/stm/test/test_inevitable.py +++ b/rpython/translator/stm/test/test_inevitable.py @@ -160,7 +160,7 @@ extfunc() res = self.interpret_inevitable(f1, []) -assert res == 'direct_call' +assert res == 'extfunc()' def test_rpy_direct_call(self): def f2(): ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: getting tests to run with questionable methods
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65189:4820d8ea75ff Date: 2013-07-05 08:20 +0200 http://bitbucket.org/pypy/pypy/changeset/4820d8ea75ff/ Log:getting tests to run with questionable methods diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -493,11 +493,11 @@ def _setup_barriers_for_stm(self): from rpython.memory.gc import stmgc WBDescr = WriteBarrierDescr -self.P2Rdescr = WBDescr(self, (stmgc.GCFLAG_GLOBAL, 'P2R', +self.P2Rdescr = WBDescr(self, (0, 'P2R', 'stm_DirectReadBarrier')) -self.P2Wdescr = WBDescr(self, (stmgc.GCFLAG_NOT_WRITTEN, 'P2W', +self.P2Wdescr = WBDescr(self, (0, 'P2W', 'stm_WriteBarrier')) -self.R2Wdescr = WBDescr(self, (stmgc.GCFLAG_NOT_WRITTEN, 'R2W', +self.R2Wdescr = WBDescr(self, (0, 'R2W', 'stm_WriteBarrierFromReady')) self.write_barrier_descr = wbdescr: do not use # diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -35,6 +35,7 @@ tdescr = get_size_descr(self.gc_ll_descr, T) tdescr.tid = 5678 tzdescr = get_field_descr(self.gc_ll_descr, T, 'z') +tydescr = get_field_descr(self.gc_ll_descr, T, 'y') # A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py b/rpython/jit/backend/llsupport/test/test_stmrewrite.py --- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py +++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py @@ -1,8 +1,9 @@ from rpython.jit.backend.llsupport.descr import * from rpython.jit.backend.llsupport.gc import * from rpython.jit.metainterp.gc import get_description -from rpython.jit.backend.llsupport.test.test_rewrite import RewriteTests - +from rpython.jit.backend.llsupport.test.test_rewrite import ( +RewriteTests, BaseFakeCPU) +from rpython.rtyper.lltypesystem import lltype, rclass, rffi, llmemory class TestStm(RewriteTests): def setup_method(self, meth): @@ -17,11 +18,12 @@ self.gc_ll_descr = GcLLDescr_framework(gcdescr, None, None, None, really_not_translated=True) # -class FakeCPU(object): +class FakeCPU(BaseFakeCPU): def sizeof(self, STRUCT): descr = SizeDescrWithVTable(104) descr.tid = 9315 return descr + self.cpu = FakeCPU() def check_rewrite(self, frm_operations, to_operations, **namespace): @@ -48,6 +50,8 @@ ) def test_rewrite_setfield_gc_const(self): +TP = lltype.GcArray(lltype.Signed) +NULL = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(TP)) self.check_rewrite( [p1, p2] setfield_gc(ConstPtr(t), p2, descr=tzdescr) @@ -58,7 +62,7 @@ cond_call_gc_wb(p3, 0, descr=P2Wdescr) setfield_gc(p3, p2, descr=tzdescr) jump() -) +, t=NULL) def test_rewrite_setfield_gc_on_local(self): self.check_rewrite( @@ -164,6 +168,8 @@ ) def test_rewrite_getfield_gc_const(self): +TP = lltype.GcArray(lltype.Signed) +NULL = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(TP)) self.check_rewrite( [p1] p2 = getfield_gc(ConstPtr(t), descr=tzdescr) @@ -174,7 +180,7 @@ cond_call_gc_wb(p3, 0, descr=P2Rdescr) p2 = getfield_gc(p3, descr=tzdescr) jump(p2) -) +, t=NULL) # XXX could do better: G2Rdescr def test_rewrite_getarrayitem_gc(self): @@ -300,62 +306,62 @@ def test_getfield_raw(self): self.check_rewrite( [i1, i2] -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=?) keepalive(i3) # random ignored operation -i4 = getfield_raw(i2, descr=?) +i4 = getfield_raw(i2, descr=?) jump(i3, i4) , [i1, i2] $INEV -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=?) keepalive(i3) -i4 = getfield_raw(i2, descr=?) +i4 = getfield_raw(i2, descr=?) jump(i3, i4) ) def test_getfield_raw_over_label(self): self.check_rewrite( [i1, i2] -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=?) label(i1, i2, i3) -
[pypy-commit] pypy stmgc-c4: typo and change to real descrs
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65191:ceb9b8b28bcf Date: 2013-07-05 11:04 +0200 http://bitbucket.org/pypy/pypy/changeset/ceb9b8b28bcf/ Log:typo and change to real descrs diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py b/rpython/jit/backend/llsupport/test/test_stmrewrite.py --- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py +++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py @@ -306,62 +306,62 @@ def test_getfield_raw(self): self.check_rewrite( [i1, i2] -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=tydescr) keepalive(i3) # random ignored operation -i4 = getfield_raw(i2, descr=?) +i4 = getfield_raw(i2, descr=tydescr) jump(i3, i4) , [i1, i2] $INEV -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=tydescr) keepalive(i3) -i4 = getfield_raw(i2, descr=?) +i4 = getfield_raw(i2, descr=tydescr) jump(i3, i4) ) def test_getfield_raw_over_label(self): self.check_rewrite( [i1, i2] -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=tydescr) label(i1, i2, i3) -i4 = getfield_raw(i2, descr=?) +i4 = getfield_raw(i2, descr=tydescr) jump(i3, i4) , [i1, i2] $INEV -i3 = getfield_raw(i1, descr=?) +i3 = getfield_raw(i1, descr=tydescr) label(i1, i2, i3) $INEV -i4 = getfield_raw(i2, descr=?) +i4 = getfield_raw(i2, descr=tydescr) jump(i3, i4) ) def test_getarrayitem_raw(self): self.check_rewrite( [i1, i2] -i3 = getarrayitem_raw(i1, 5, descr=?) -i4 = getarrayitem_raw(i2, i3, descr=?) +i3 = getarrayitem_raw(i1, 5, descr=adescr) +i4 = getarrayitem_raw(i2, i3, descr=adescr) jump(i3, i4) , [i1, i2] $INEV -i3 = getarrayitem_raw(i1, 5, descr=?) -i4 = getarrayitem_raw(i2, i3, descr=?) +i3 = getarrayitem_raw(i1, 5, descr=adescr) +i4 = getarrayitem_raw(i2, i3, descr=adescr) jump(i3, i4) ) def test_rewrite_unrelated_setarrayitem_gcs(self): self.check_rewrite( [p1, i1, p2, p3, i3, p4] -setarrayitem_gc(p1, i1, p2, descr=?) -setarrayitem_gc(p3, i3, p4, descr=?) +setarrayitem_gc(p1, i1, p2, descr=adescr) +setarrayitem_gc(p3, i3, p4, descr=adescr) jump() , [p1, i1, p2, p3, i3, p4] cond_call_gc_wb(p1, 0, descr=P2Wdescr) -setarrayitem_gc(p1, i1, p2, descr=?) +setarrayitem_gc(p1, i1, p2, descr=adescr) cond_call_gc_wb(p3, 0, descr=P2Wdescr) -setarrayitem_gc(p3, i3, p4, descr=?) +setarrayitem_gc(p3, i3, p4, descr=adescr) jump() ) @@ -417,9 +417,9 @@ T = rffi.CArrayPtr(rffi.TIME_T) calldescr2 = get_call_descr(self.gc_ll_descr, [T], rffi.TIME_T) oplist = [ -setfield_raw(i1, i2, descr=?), -setarrayitem_raw(i1, i2, i3, descr=?), -setinteriorfield_raw(i1, i2, i3, descr=?), +setfield_raw(i1, i2, descr=tydescr), +setarrayitem_raw(i1, i2, i3, descr=tydescr), +setinteriorfield_raw(i1, i2, i3, descr=adescr), call_release_gil(123, descr=calldescr2), escape(i1),# a generic unknown operation ] diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py --- a/rpython/translator/stm/funcgen.py +++ b/rpython/translator/stm/funcgen.py @@ -163,7 +163,7 @@ return 'stmgc_minor_collect();' def stm_major_collect(funcgen, op): -return 'stmgcpage_possibly_major_collect(1);}' # forced +return 'stmgcpage_possibly_major_collect(1);' # forced ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: rename of transform2.py to transform.py
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65195:88d375dc39b3 Date: 2013-07-05 13:08 +0200 http://bitbucket.org/pypy/pypy/changeset/88d375dc39b3/ Log:rename of transform2.py to transform.py diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -141,11 +141,11 @@ translator = self.translator if self.config.translation.stm: -from rpython.translator.stm import transform2 +from rpython.translator.stm import transform self.getentrypointptr()# build the wrapper first # ^^ this is needed to make sure we see the no-GC wrapper function # calling the GC entrypoint function. -stmtransformer = transform2.STMTransformer(self.translator) +stmtransformer = transform.STMTransformer(self.translator) stmtransformer.transform() gcpolicyclass = self.get_gcpolicyclass() diff --git a/rpython/translator/stm/test/test_jitdriver.py b/rpython/translator/stm/test/test_jitdriver.py --- a/rpython/translator/stm/test/test_jitdriver.py +++ b/rpython/translator/stm/test/test_jitdriver.py @@ -1,5 +1,5 @@ from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.translator.stm.test.transform2_support import BaseTestTransform +from rpython.translator.stm.test.transform_support import BaseTestTransform from rpython.rlib.jit import JitDriver diff --git a/rpython/translator/stm/test/test_writebarrier.py b/rpython/translator/stm/test/test_writebarrier.py --- a/rpython/translator/stm/test/test_writebarrier.py +++ b/rpython/translator/stm/test/test_writebarrier.py @@ -1,5 +1,5 @@ from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.translator.stm.test.transform2_support import BaseTestTransform +from rpython.translator.stm.test.transform_support import BaseTestTransform class TestTransform(BaseTestTransform): diff --git a/rpython/translator/stm/test/transform2_support.py b/rpython/translator/stm/test/transform_support.py rename from rpython/translator/stm/test/transform2_support.py rename to rpython/translator/stm/test/transform_support.py --- a/rpython/translator/stm/test/transform2_support.py +++ b/rpython/translator/stm/test/transform_support.py @@ -1,7 +1,7 @@ from rpython.rtyper.lltypesystem import lltype, opimpl from rpython.rtyper.llinterp import LLFrame from rpython.rtyper.test.test_llinterp import get_interpreter, clear_tcache -from rpython.translator.stm.transform2 import STMTransformer +from rpython.translator.stm.transform import STMTransformer from rpython.translator.stm.writebarrier import MORE_PRECISE_CATEGORIES from rpython.conftest import option diff --git a/rpython/translator/stm/transform2.py b/rpython/translator/stm/transform.py rename from rpython/translator/stm/transform2.py rename to rpython/translator/stm/transform.py --- a/rpython/translator/stm/transform2.py +++ b/rpython/translator/stm/transform.py @@ -1,3 +1,10 @@ +from rpython.translator.backendopt.writeanalyze import WriteAnalyzer +from rpython.translator.stm.writebarrier import insert_stm_barrier +from rpython.translator.stm.inevitable import insert_turn_inevitable +from rpython.translator.stm.jitdriver import reorganize_around_jit_driver +from rpython.translator.stm.threadlocalref import transform_tlref +from rpython.translator.c.support import log + class STMTransformer(object): @@ -18,38 +25,27 @@ self.print_logs_after_gc() def transform_write_barrier(self): -from rpython.translator.backendopt.writeanalyze import WriteAnalyzer -from rpython.translator.stm.writebarrier import insert_stm_barrier -# self.write_analyzer = WriteAnalyzer(self.translator) for graph in self.translator.graphs: insert_stm_barrier(self, graph) del self.write_analyzer def transform_turn_inevitable(self): -from rpython.translator.stm.inevitable import insert_turn_inevitable -# for graph in self.translator.graphs: insert_turn_inevitable(graph) def transform_jit_driver(self): -from rpython.translator.stm.jitdriver import reorganize_around_jit_driver -# for graph in self.translator.graphs: reorganize_around_jit_driver(self, graph) def transform_threadlocalref(self): -from rpython.translator.stm.threadlocalref import transform_tlref transform_tlref(self.translator) def start_log(self): -from rpython.translator.c.support import log log.info(Software Transactional Memory transformation) def print_logs(self): -from rpython.translator.c.support import log log.info(Software Transactional Memory transformation applied) def print_logs_after_gc(self): -from rpython.translator.c.support import log log.info(Software Transactional
[pypy-commit] pypy stmgc-c4: add new resops COND_CALL_STM_WB and COND_CALL_STM_RB
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65196:675a3d0878f1 Date: 2013-07-05 13:23 +0200 http://bitbucket.org/pypy/pypy/changeset/675a3d0878f1/ Log:add new resops COND_CALL_STM_WB and COND_CALL_STM_RB diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py --- a/rpython/jit/backend/llsupport/stmrewrite.py +++ b/rpython/jit/backend/llsupport/stmrewrite.py @@ -121,8 +121,13 @@ except KeyError: return v_base# no barrier needed args = [v_base, self.c_zero] -self.newops.append(ResOperation(rop.COND_CALL_GC_WB, args, None, +if target_category == 'W': +op = rop.COND_CALL_STM_WB +else: +op = rop.COND_CALL_STM_RB +self.newops.append(ResOperation(op, args, None, descr=write_barrier_descr)) + self.known_category[v_base] = target_category return v_base diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py b/rpython/jit/backend/llsupport/test/test_stmrewrite.py --- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py +++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py @@ -44,7 +44,7 @@ jump() , [p1, p2] -cond_call_gc_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, 0, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) jump() ) @@ -59,7 +59,7 @@ , [p1, p2] p3 = same_as(ConstPtr(t)) -cond_call_gc_wb(p3, 0, descr=P2Wdescr) +cond_call_stm_wb(p3, 0, descr=P2Wdescr) setfield_gc(p3, p2, descr=tzdescr) jump() , t=NULL) @@ -87,9 +87,9 @@ jump() , [p1, p2, p3, p4] -cond_call_gc_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, 0, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) -cond_call_gc_wb(p3, 0, descr=P2Wdescr) +cond_call_stm_wb(p3, 0, descr=P2Wdescr) setfield_gc(p3, p4, descr=tzdescr) jump() ) @@ -102,7 +102,7 @@ jump() , [p1, p2, i3] -cond_call_gc_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, 0, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) setfield_gc(p1, i3, descr=tydescr) jump() @@ -117,10 +117,10 @@ jump(p1) , [p1, p2, i3] -cond_call_gc_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, 0, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) label(p1, i3) -cond_call_gc_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, 0, descr=P2Wdescr) setfield_gc(p1, i3, descr=tydescr) jump(p1) ) @@ -162,7 +162,7 @@ jump(p2) , [p1] -cond_call_gc_wb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, 0, descr=P2Rdescr) p2 = getfield_gc(p1, descr=tzdescr) jump(p2) ) @@ -177,7 +177,7 @@ , [p1] p3 = same_as(ConstPtr(t)) -cond_call_gc_wb(p3, 0, descr=P2Rdescr) +cond_call_stm_rb(p3, 0, descr=P2Rdescr) p2 = getfield_gc(p3, descr=tzdescr) jump(p2) , t=NULL) @@ -190,7 +190,7 @@ jump(i3) , [p1, i2] -cond_call_gc_wb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, 0, descr=P2Rdescr) i3 = getarrayitem_gc(p1, i2, descr=adescr) jump(i3) ) @@ -202,7 +202,7 @@ jump(i3) , [p1, i2] -cond_call_gc_wb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, 0, descr=P2Rdescr) i3 = getinteriorfield_gc(p1, i2, descr=adescr) jump(i3) ) @@ -215,7 +215,7 @@ jump(p2, i2) , [p1] -cond_call_gc_wb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, 0, descr=P2Rdescr) p2 = getfield_gc(p1, descr=tzdescr) i2 = getfield_gc(p1, descr=tydescr) jump(p2, i2) @@ -229,9 +229,9 @@ jump(p2, i2) , [p1] -cond_call_gc_wb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, 0, descr=P2Rdescr) p2 = getfield_gc(p1, descr=tzdescr) -cond_call_gc_wb(p2, 0, descr=P2Rdescr) +cond_call_stm_rb(p2, 0, descr=P2Rdescr) i2 = getfield_gc(p2, descr=tydescr) jump(p2, i2) ) @@ -247,10 +247,10 @@ jump(p1) , [p1] -cond_call_gc_wb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, 0, descr=P2Rdescr) i1 = getfield_gc(p1, descr=tydescr)
[pypy-commit] pypy stmgc-c4: I guess those tests need to be rewritten for STM_WB/RB. Still, remove syntax errors.
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65197:dfde347f3c17 Date: 2013-07-05 13:49 +0200 http://bitbucket.org/pypy/pypy/changeset/dfde347f3c17/ Log:I guess those tests need to be rewritten for STM_WB/RB. Still, remove syntax errors. diff --git a/rpython/jit/backend/llsupport/test/test_gc.py b/rpython/jit/backend/llsupport/test/test_gc.py --- a/rpython/jit/backend/llsupport/test/test_gc.py +++ b/rpython/jit/backend/llsupport/test/test_gc.py @@ -213,7 +213,7 @@ gc_ll_descr = self.gc_ll_descr llop1 = self.llop1 # -rewriter = gc.GcRewriterAssembler(gc_ll_descr, None) +rewriter = GcRewriterAssembler(gc_ll_descr, None) newops = rewriter.newops v_base = BoxPtr() v_value = BoxPtr() diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -4242,3 +4242,14 @@ assert rffi.cast(lltype.Signed, a[0]) == -7654 assert rffi.cast(lltype.Signed, a[1]) == 777 lltype.free(a, flavor='raw') + +class WBDescrForTests(AbstractDescr): +returns_modified_object = False +wb_slowpath = (0, 0, 0, 0) +def get_wb_slowpath(self, c1, c2): +return self.wb_slowpath[c1+2*c2] +def set_wb_slowpath(self, c1, c2, addr): +i = c1+2*c2 +self.wb_slowpath = (self.wb_slowpath[:i] + (addr,) + +self.wb_slowpath[i+1:]) + ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: missing import
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65194:ccb4307abb9c Date: 2013-07-05 12:15 +0200 http://bitbucket.org/pypy/pypy/changeset/ccb4307abb9c/ Log:missing import diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py --- a/rpython/rlib/rstm.py +++ b/rpython/rlib/rstm.py @@ -1,5 +1,5 @@ from rpython.rlib.objectmodel import we_are_translated, specialize -from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper.extregistry import ExtRegistryEntry @@ -31,7 +31,7 @@ pass #stmgcintf.StmOperations.abort_info_pop(count) def charp_inspect_abort_info(): -pass # return stmgcintf.StmOperations.inspect_abort_info() +return rffi.NULL # return stmgcintf.StmOperations.inspect_abort_info() def abort_and_retry(): pass # stmgcintf.StmOperations.abort_and_retry() ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: try to satisfy tests..
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65199:fa4f9e6e4a11 Date: 2013-07-05 14:38 +0200 http://bitbucket.org/pypy/pypy/changeset/fa4f9e6e4a11/ Log:try to satisfy tests.. diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -92,7 +92,7 @@ self._build_wb_slowpath(False, withfloats=True) self._build_wb_slowpath(True, withfloats=True) self._build_propagate_exception_path() -if gc_ll_descr.get_malloc_slowpath_addr is not None: +if gc_ll_descr.get_malloc_slowpath_addr() is not None: # generate few slowpaths for various cases self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed') self.malloc_slowpath_varsize = self._build_malloc_slowpath( diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -241,6 +241,9 @@ return self.malloc_array(arraydescr.basesize, num_elem, arraydescr.itemsize, arraydescr.lendescr.offset) + +def get_malloc_slowpath_addr(self): +return None # # All code below is for the hybrid or minimark GC ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: extract stm barriers from normal write barrier
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65200:f2a6fd3f14de Date: 2013-07-05 15:10 +0200 http://bitbucket.org/pypy/pypy/changeset/f2a6fd3f14de/ Log:extract stm barriers from normal write barrier diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -270,37 +270,24 @@ rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address) return rffi.cast(lltype.Signed, rst_addr) + class WriteBarrierDescr(AbstractDescr): -def __init__(self, gc_ll_descr, stmcat=None): +def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 -self.stmcat = stmcat -self.returns_modified_object = (stmcat is not None) -if not self.returns_modified_object: -self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( -[llmemory.Address], lltype.Void)) -else: -self.WB_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType( -[llmemory.Address], llmemory.Address)) + +self.returns_modified_object = False +self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( +[llmemory.Address], lltype.Void)) + self.fielddescr_tid = gc_ll_descr.fielddescr_tid self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder self.HDRPTR = gc_ll_descr.HDRPTR # -if self.stmcat is not None: -cfunc_name = self.stmcat[2] -self.wb_failing_case_ptr = rffi.llexternal( -cfunc_name, -self.WB_FUNCPTR_MOD.TO.ARGS, -self.WB_FUNCPTR_MOD.TO.RESULT, -sandboxsafe=True, -_nowrapper=True) -# GCClass = gc_ll_descr.GCClass if GCClass is None: # for tests return -if self.stmcat is None: -self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG -else: -self.jit_wb_if_flag = self.stmcat[0] + +self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG self.jit_wb_if_flag_byteofs, self.jit_wb_if_flag_singlebyte = ( self.extract_flag_byte(self.jit_wb_if_flag)) # @@ -320,11 +307,7 @@ self.wb_slowpath = [0, 0, 0, 0] def repr_of_descr(self): -if self.stmcat is None: -return 'wbdescr' -else: -cat = self.stmcat[1] -return cat +return 'wbdescr' def __repr__(self): return 'WriteBarrierDescr %r' % (self.repr_of_descr(),) @@ -395,7 +378,41 @@ if returns_modified_object: return gcref_struct +class STMBarrierDescr(WriteBarrierDescr): +def __init__(self, gc_ll_descr, stmcat, cfunc_name): +WriteBarrierDescr.__init__(self, gc_ll_descr) +self.stmcat = stmcat +self.returns_modified_object = True +self.WB_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType( +[llmemory.Address], llmemory.Address)) +self.wb_failing_case_ptr = rffi.llexternal( +cfunc_name, +self.WB_FUNCPTR_MOD.TO.ARGS, +self.WB_FUNCPTR_MOD.TO.RESULT, +sandboxsafe=True, +_nowrapper=True) + +def repr_of_descr(self): +cat = self.stmcat +return cat + +def _do_barrier(self, gcref_struct, returns_modified_object): +raise NotImplemented + +class STMReadBarrierDescr(STMBarrierDescr): +def __init__(self, gc_ll_descr, stmcat): +assert stmcat == 'P2R' +STMBarrierDescr.__init__(self, gc_ll_descr, stmcat, + 'stm_DirectReadBarrier') + +class STMWriteBarrierDescr(STMBarrierDescr): +def __init__(self, gc_ll_descr, stmcat): +assert stmcat in ['P2W', 'R2W'] +STMBarrierDescr.__init__(self, gc_ll_descr, stmcat, + 'stm_WriteBarrier') + + class GcLLDescr_framework(GcLLDescription): DEBUG = False# forced to True by x86/test/test_zrpy_gc.py kind = 'framework' @@ -494,14 +511,9 @@ self.do_write_barrier = do_write_barrier def _setup_barriers_for_stm(self): -from rpython.memory.gc import stmgc -WBDescr = WriteBarrierDescr -self.P2Rdescr = WBDescr(self, (0, 'P2R', - 'stm_DirectReadBarrier')) -self.P2Wdescr = WBDescr(self, (0, 'P2W', - 'stm_WriteBarrier')) -self.R2Wdescr = WBDescr(self, (0, 'R2W', - 'stm_WriteBarrierFromReady')) +self.P2Rdescr = STMReadBarrierDescr(self, 'P2R') +self.P2Wdescr = STMWriteBarrierDescr(self, 'P2W') +self.R2Wdescr = STMWriteBarrierDescr(self, 'R2W') self.write_barrier_descr = wbdescr: do not use # @specialize.argtype(0) ___ pypy-commit mailing list pypy-commit@python.org
[pypy-commit] pypy stmgc-c4: no fastpath for gc write/read barriers
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65201:43aaaf023f46 Date: 2013-07-05 16:58 +0200 http://bitbucket.org/pypy/pypy/changeset/43aaaf023f46/ Log:no fastpath for gc write/read barriers diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -362,7 +362,7 @@ self.wb_slowpath[withcards + 2 * withfloats] = addr @specialize.arg(2) -def _do_write_barrier(self, gcref_struct, returns_modified_object): +def _do_barrier(self, gcref_struct, returns_modified_object): assert self.returns_modified_object == returns_modified_object hdr_addr = llmemory.cast_ptr_to_adr(gcref_struct) hdr_addr -= self.gcheaderbuilder.size_gc_header @@ -397,20 +397,29 @@ cat = self.stmcat return cat +@specialize.arg(2) def _do_barrier(self, gcref_struct, returns_modified_object): -raise NotImplemented +assert self.returns_modified_object == returns_modified_object +# XXX: fastpath for Read and Write variants +funcptr = self.get_barrier_funcptr(returns_modified_object) +res = funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) +if returns_modified_object: +return llmemory.cast_adr_to_ptr(res, llmemory.GCREF) + class STMReadBarrierDescr(STMBarrierDescr): def __init__(self, gc_ll_descr, stmcat): assert stmcat == 'P2R' STMBarrierDescr.__init__(self, gc_ll_descr, stmcat, - 'stm_DirectReadBarrier') + 'stm_read_barrier') + + class STMWriteBarrierDescr(STMBarrierDescr): def __init__(self, gc_ll_descr, stmcat): assert stmcat in ['P2W', 'R2W'] STMBarrierDescr.__init__(self, gc_ll_descr, stmcat, - 'stm_WriteBarrier') + 'stm_write_barrier') class GcLLDescr_framework(GcLLDescription): @@ -507,7 +516,7 @@ else: self.write_barrier_descr = WriteBarrierDescr(self) def do_write_barrier(gcref_struct, gcref_newptr): -self.write_barrier_descr._do_write_barrier(gcref_struct, False) +self.write_barrier_descr._do_barrier(gcref_struct, False) self.do_write_barrier = do_write_barrier def _setup_barriers_for_stm(self): @@ -524,7 +533,7 @@ descr = self.P2Wdescr else: descr = self.P2Rdescr -return descr._do_write_barrier(gcref, True) +return descr._do_barrier(gcref, True) self.do_stm_barrier = do_stm_barrier def _make_functions(self, really_not_translated): ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: fix
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r371:1183d4c7518c Date: 2013-07-08 11:17 +0200 http://bitbucket.org/pypy/stmgc/changeset/1183d4c7518c/ Log:fix diff --git a/duhton/glob.c b/duhton/glob.c --- a/duhton/glob.c +++ b/duhton/glob.c @@ -271,7 +271,9 @@ DuObject *du_list(DuObject *cons, DuObject *locals) { +_du_save2(cons, locals); DuObject *list = DuList_New(); +_du_restore2(cons, locals); while (cons != Du_None) { _du_read1(cons); DuObject *expr = _DuCons_CAR(cons); @@ -299,7 +301,11 @@ else _du_getargs1(container, cons, locals, obj); -return DuContainer_New(obj); +_du_save2(cons, locals); +DuObject *container = DuContainer_New(obj); +_du_restore2(cons, locals); + +return container; } DuObject *du_get(DuObject *cons, DuObject *locals) ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: backout 840ac0a, demo/trees2.duh seems to crash without tracing
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r372:2b2561c18ea9 Date: 2013-07-08 11:36 +0200 http://bitbucket.org/pypy/stmgc/changeset/2b2561c18ea9/ Log:backout 840ac0a, demo/trees2.duh seems to crash without tracing diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -225,8 +225,8 @@ id_copy-h_tid |= GCFLAG_VISITED; /* XXX: may not always need tracing? */ -//if (!(id_copy-h_tid GCFLAG_STUB)) -//gcptrlist_insert(objects_to_trace, id_copy); +if (!(id_copy-h_tid GCFLAG_STUB)) +gcptrlist_insert(objects_to_trace, id_copy); } else { /* prebuilt originals won't get collected anyway ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: repeat/do write barrier after minor_collection. I think the problem was that minor_collect clears old_objects_to_trace and the object needs to be reregistered there if it
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r373:470bcb38a12e Date: 2013-07-08 13:26 +0200 http://bitbucket.org/pypy/stmgc/changeset/470bcb38a12e/ Log:repeat/do write barrier after minor_collection. I think the problem was that minor_collect clears old_objects_to_trace and the object needs to be reregistered there if it is modified again. diff --git a/duhton/listobject.c b/duhton/listobject.c --- a/duhton/listobject.c +++ b/duhton/listobject.c @@ -75,7 +75,7 @@ void _list_append(DuListObject *ob, DuObject *x) { -_du_write1(ob); +_du_read1(ob); DuTupleObject *olditems = ob-ob_tuple; _du_read1(olditems); @@ -85,6 +85,8 @@ DuTupleObject *newitems = DuTuple_New(newcount); _du_restore3(ob, x, olditems); +_du_write1(ob); + for (i=0; inewcount-1; i++) newitems-ob_items[i] = olditems-ob_items[i]; newitems-ob_items[newcount-1] = x; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: A test that fails. Maybe should fail, waiting for arigato's OK
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r374:ef8442a75174 Date: 2013-07-08 14:37 +0200 http://bitbucket.org/pypy/stmgc/changeset/ef8442a75174/ Log:A test that fails. Maybe should fail, waiting for arigato's OK diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -204,6 +204,36 @@ assert p4 == p2 assert list_of_read_objects() == [p2] +def test_write_barrier_after_minor_collect(): +# maybe should fail. not sure. +p = oalloc_refs(1) +pw = lib.stm_write_barrier(p) + +lib.stm_push_root(pw) +minor_collect() +r = nalloc(HDR) +pw = lib.stm_pop_root() + +assert pw.h_tid GCFLAG_OLD +rawsetptr(pw, 0, r) + +# pw not in old_objects_to_trace. A +# repeated write_barrier before +# rawsetptr() would fix that + +lib.stm_push_root(r) +minor_collect() +r2 = lib.stm_pop_root() +check_nursery_free(r) + +pr = lib.stm_read_barrier(p) +assert r != r2 +# these will fail because pw/pr was +# not traced in the last minor_collect, +# because they were not registered in +# old_objects_to_trace. +assert getptr(pr, 0) != r +assert getptr(pr, 0) == r2 def test_id_young_to_old(): # move out of nursery with shadow original ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: we don't need that extra parameter
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65282:b29a9e46f214 Date: 2013-07-09 10:04 +0200 http://bitbucket.org/pypy/pypy/changeset/b29a9e46f214/ Log:we don't need that extra parameter diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -958,10 +958,10 @@ def execute_cond_call_gc_wb_array(self, descr, a, b, c): py.test.skip(cond_call_gc_wb_array not supported) -def execute_cond_call_stm_wb(self, descr, a, b): +def execute_cond_call_stm_wb(self, descr, a): py.test.skip(cond_call_stm_wb not supported) -def execute_cond_call_stm_rb(self, descr, a, b): +def execute_cond_call_stm_rb(self, descr, a): py.test.skip(cond_call_stm_rb not supported) def execute_keepalive(self, descr, x): diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py --- a/rpython/jit/backend/llsupport/stmrewrite.py +++ b/rpython/jit/backend/llsupport/stmrewrite.py @@ -9,7 +9,7 @@ # # Any SETFIELD_GC, SETARRAYITEM_GC, SETINTERIORFIELD_GC must be done on a # W object. The operation that forces an object p1 to be W is -# COND_CALL_STM_WB(p1, 0, descr=x2Wdescr), for x in 'PGORL'. This +# COND_CALL_STM_WB(p1, descr=x2Wdescr), for x in 'PGORL'. This # COND_CALL_STM_WB is a bit special because if p1 is not W, it *replaces* # its value with the W copy (by changing the register's value and # patching the stack location if any). It's still conceptually the same @@ -120,7 +120,7 @@ write_barrier_descr = mpcat[target_category] except KeyError: return v_base# no barrier needed -args = [v_base, self.c_zero] +args = [v_base,] if target_category == 'W': op = rop.COND_CALL_STM_WB else: diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py b/rpython/jit/backend/llsupport/test/test_stmrewrite.py --- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py +++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py @@ -44,7 +44,7 @@ jump() , [p1, p2] -cond_call_stm_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) jump() ) @@ -59,7 +59,7 @@ , [p1, p2] p3 = same_as(ConstPtr(t)) -cond_call_stm_wb(p3, 0, descr=P2Wdescr) +cond_call_stm_wb(p3, descr=P2Wdescr) setfield_gc(p3, p2, descr=tzdescr) jump() , t=NULL) @@ -87,9 +87,9 @@ jump() , [p1, p2, p3, p4] -cond_call_stm_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) -cond_call_stm_wb(p3, 0, descr=P2Wdescr) +cond_call_stm_wb(p3, descr=P2Wdescr) setfield_gc(p3, p4, descr=tzdescr) jump() ) @@ -102,7 +102,7 @@ jump() , [p1, p2, i3] -cond_call_stm_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) setfield_gc(p1, i3, descr=tydescr) jump() @@ -117,10 +117,10 @@ jump(p1) , [p1, p2, i3] -cond_call_stm_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, descr=P2Wdescr) setfield_gc(p1, p2, descr=tzdescr) label(p1, i3) -cond_call_stm_wb(p1, 0, descr=P2Wdescr) +cond_call_stm_wb(p1, descr=P2Wdescr) setfield_gc(p1, i3, descr=tydescr) jump(p1) ) @@ -162,7 +162,7 @@ jump(p2) , [p1] -cond_call_stm_rb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, descr=P2Rdescr) p2 = getfield_gc(p1, descr=tzdescr) jump(p2) ) @@ -177,7 +177,7 @@ , [p1] p3 = same_as(ConstPtr(t)) -cond_call_stm_rb(p3, 0, descr=P2Rdescr) +cond_call_stm_rb(p3, descr=P2Rdescr) p2 = getfield_gc(p3, descr=tzdescr) jump(p2) , t=NULL) @@ -190,7 +190,7 @@ jump(i3) , [p1, i2] -cond_call_stm_rb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, descr=P2Rdescr) i3 = getarrayitem_gc(p1, i2, descr=adescr) jump(i3) ) @@ -202,7 +202,7 @@ jump(i3) , [p1, i2] -cond_call_stm_rb(p1, 0, descr=P2Rdescr) +cond_call_stm_rb(p1, descr=P2Rdescr) i3 = getinteriorfield_gc(p1, i2, descr=adescr) jump(i3) ) @@ -215,7 +215,7 @@ jump(p2, i2)
[pypy-commit] pypy stmgc-c4: skip stm_barriers; no implementation in runner.py
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65281:5d3354d5a836 Date: 2013-07-08 08:26 +0200 http://bitbucket.org/pypy/pypy/changeset/5d3354d5a836/ Log:skip stm_barriers; no implementation in runner.py diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -958,6 +958,12 @@ def execute_cond_call_gc_wb_array(self, descr, a, b, c): py.test.skip(cond_call_gc_wb_array not supported) +def execute_cond_call_stm_wb(self, descr, a, b): +py.test.skip(cond_call_stm_wb not supported) + +def execute_cond_call_stm_rb(self, descr, a, b): +py.test.skip(cond_call_stm_rb not supported) + def execute_keepalive(self, descr, x): pass diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py --- a/rpython/jit/backend/llsupport/stmrewrite.py +++ b/rpython/jit/backend/llsupport/stmrewrite.py @@ -9,8 +9,8 @@ # # Any SETFIELD_GC, SETARRAYITEM_GC, SETINTERIORFIELD_GC must be done on a # W object. The operation that forces an object p1 to be W is -# COND_CALL_GC_WB(p1, 0, descr=x2Wdescr), for x in 'PGORL'. This -# COND_CALL_GC_WB is a bit special because if p1 is not W, it *replaces* +# COND_CALL_STM_WB(p1, 0, descr=x2Wdescr), for x in 'PGORL'. This +# COND_CALL_STM_WB is a bit special because if p1 is not W, it *replaces* # its value with the W copy (by changing the register's value and # patching the stack location if any). It's still conceptually the same # object, but the pointer is different. diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py --- a/rpython/jit/metainterp/executor.py +++ b/rpython/jit/metainterp/executor.py @@ -345,9 +345,9 @@ if value in (rop.FORCE_TOKEN, rop.CALL_ASSEMBLER, rop.COND_CALL_GC_WB, + rop.COND_CALL_GC_WB_ARRAY, rop.COND_CALL_STM_WB, rop.COND_CALL_STM_RB, - rop.COND_CALL_GC_WB_ARRAY, rop.DEBUG_MERGE_POINT, rop.JIT_DEBUG, rop.SETARRAYITEM_RAW, ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] extradoc extradoc: minor corrections
Author: Remi Meier meier...@student.ethz.ch Branch: extradoc Changeset: r4980:53412cc62d31 Date: 2013-07-09 14:31 +0200 http://bitbucket.org/pypy/extradoc/changeset/53412cc62d31/ Log:minor corrections diff --git a/blog/draft/duhton.rst b/blog/draft/duhton.rst --- a/blog/draft/duhton.rst +++ b/blog/draft/duhton.rst @@ -3,24 +3,24 @@ == As covered in `the previous blog post`_, the STM subproject of PyPy has been -back on the drawing board and the result of this experiment is an STM-aware -garbage collector written in C. This is finished by now, thanks to Armin -and Remi_M work, we have a fully functional garbage collector and STM subsystem +back on the drawing board. The result of this experiment is an STM-aware +garbage collector written in C. This is finished by now, thanks to Armin's +and Remi's work, we have a fully functional garbage collector and a STM system that can be used from any C program with enough effort. Using it is more than a little mundane, since you have to inserts write and read barriers by hand everywhere in your code that reads or writes to garbage collector controlled -memory. Once we finish PyPy integration, those sort of things would be inserted -automatically by STM transformation in the interpreter. +memory. Once we finish PyPy integration, this manual work is done automatically +by the STM transformation in the interpreter. However, to experiment some more, we created a `lisp interpreter`_ -(called duhton), that follows closely CPython's implementation strategy -and for anyone familiar with CPython's source code, it should be pretty +(called Duhton), that follows closely CPython's implementation strategy. +For anyone familiar with CPython's source code, it should be pretty readable. This interpreter works like a normal and very basic lisp variant, -however it comes with ``(transaction`` builtin, that lets you spawn transactions -using STM system. We implemented a few demos that let you play with the +however it comes with a ``transaction`` builtin, that lets you spawn transactions +using the STM system. We implemented a few demos that let you play with the transaction system. All the demos are running without conflicts, which means -there is no conflicting writes to global memory and hence are amenable to -parallelization very well. They exercise: +there are no conflicting writes to global memory and hence the demos are very +amenable to parallelization. They exercise: * arithmetics - ``demo/many_sqare_roots.duh`` @@ -29,6 +29,6 @@ * read-write access to local objects - ``demo/trees2.duh`` With the latter ones being very similar to the classic gcbench. STM-aware -duhton can be found in `the stmgc repo`_, while the STM-less duhton, +Duhton can be found in `the stmgc repo`_, while the STM-less Duhton, that uses refcounting, can be found in `the duhton repo`_ under the ``base`` branch. ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original: seems to be working mostly
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r379:5a4649117329 Date: 2013-07-09 18:22 +0200 http://bitbucket.org/pypy/stmgc/changeset/5a4649117329/ Log:seems to be working mostly diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -945,6 +945,7 @@ revision_t my_lock = d-my_lock; wlog_t *item; + dprintf((acquire_locks\n)); assert(!stm_has_got_any_lock(d)); assert(d-public_descriptor-stolen_objects.size == 0); @@ -957,6 +958,7 @@ revision_t v; retry: assert(R-h_tid GCFLAG_PUBLIC); + assert(R-h_tid GCFLAG_PUBLIC_TO_PRIVATE); v = ACCESS_ONCE(R-h_revision); if (IS_POINTER(v)) /* has a more recent revision */ { @@ -989,7 +991,7 @@ static void CancelLocks(struct tx_descriptor *d) { wlog_t *item; - + dprintf((cancel_locks\n)); if (!g2l_any_entry(d-public_to_private)) return; @@ -1257,7 +1259,7 @@ revision_t cur_time; struct tx_descriptor *d = thread_descriptor; assert(d-active = 1); - + dprintf((CommitTransaction(%p)\n, d)); spinlock_acquire(d-public_descriptor-collection_lock, 'C'); /*committing*/ if (d-public_descriptor-stolen_objects.size != 0) stm_normalize_stolen_objects(d); @@ -1341,6 +1343,7 @@ d-active = 2; d-reads_size_limit_nonatomic = 0; update_reads_size_limit(d); + dprintf((make_inevitable(%p)\n, d)); } static revision_t acquire_inev_mutex_and_mark_global_cur_time( diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -370,8 +370,65 @@ for (; pobj != pend; pobj++) { obj = *pobj; assert(obj-h_tid GCFLAG_PREBUILT_ORIGINAL); -assert(IS_POINTER(obj-h_revision)); -visit((gcptr *)obj-h_revision); +//assert(IS_POINTER(obj-h_revision)); + +gcptr next = (gcptr)obj-h_revision; +/* XXX: do better. visit obj first and then + copy over if possible: */ +if (!(obj-h_revision 1) + (next-h_revision 1) + !(next-h_tid GCFLAG_VISITED) + (next-h_tid GCFLAG_OLD) + !(next-h_tid GCFLAG_PUBLIC_TO_PRIVATE) /* XXX */ + !(obj-h_tid GCFLAG_PUBLIC_TO_PRIVATE)) { + +assert(next-h_original == (revision_t)obj); +assert(next-h_tid GCFLAG_PUBLIC); +assert(!(next-h_tid GCFLAG_STUB)); +assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); +assert(!(next-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); +assert(!(obj-h_tid GCFLAG_BACKUP_COPY)); +assert(!(next-h_tid GCFLAG_BACKUP_COPY)); + + +revision_t pre_hash = obj-h_original; +revision_t old_tid = obj-h_tid; +memcpy(obj, next, stmgc_size(next)); +assert(!((obj-h_tid ^ old_tid) + (GCFLAG_BACKUP_COPY | GCFLAG_STUB +| GCFLAG_PUBLIC | GCFLAG_HAS_ID +| GCFLAG_PRIVATE_FROM_PROTECTED))); +obj-h_original = pre_hash; +obj-h_tid = old_tid; + +fprintf(stdout, copy %p over prebuilt %p\n, next, obj); + +/* will not be freed anyway and visit() only traces + head revision if not visited already */ +obj-h_tid = ~GCFLAG_VISITED; +/* For those visiting later: + XXX: don't: they will think that they are outdated*/ +next-h_revision = (revision_t)obj; +//if (next-h_tid GCFLAG_PUBLIC_TO_PRIVATE) { +// may have already lost it +/* mark somehow so that we can update pub_to_priv + for inevitable transactions and others ignore + it during tracing. Otherwise, inev transactions + will think 'next' is outdated. */ +next-h_tid = ~GCFLAG_OLD; +//} +} +else if (IS_POINTER(obj-h_revision)) { +visit((gcptr *)obj-h_revision); +} + +// prebuilt originals will always be traced +// in visit_keep. And otherwise, they may +// not lose their pub_to_priv flag +// I think because transactions abort +// without clearing the flags. +obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; +gcptrlist_insert(objects_to_trace, obj); } } @@ -410,24 +467,45 @@ /* the current transaction's private copies of public objects */ wlog_t *item; +if (1 || d-active == 2) { +/* inevitable transactions need to have their pub_to_priv + fixed. Otherwise, they'll think their objects got outdated */ +/* XXX: others too, but maybe not worth it */ +struct G2L new_public_to_private; +memset(new_public_to_private, 0, sizeof(struct G2L)); + +fprintf(stdout, start fixup (%p):\n, d); +G2L_LOOP_FORWARD(d-public_to_private, item) { +gcptr R = item-addr; +
[pypy-commit] stmgc copy-over-original: test current approach
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r380:f6e27ee66d12 Date: 2013-07-10 07:54 +0200 http://bitbucket.org/pypy/stmgc/changeset/f6e27ee66d12/ Log:test current approach diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py --- a/c4/test/test_gcpage.py +++ b/c4/test/test_gcpage.py @@ -308,6 +308,23 @@ check_free_old(p2) check_not_free(p3) # XXX replace with p1 +def test_prebuilt_version_2_copy_over_prebuilt(): +p1 = lib.pseudoprebuilt(HDR, 42 + HDR) +p2 = oalloc(HDR); make_public(p2) +p3 = oalloc(HDR); make_public(p3) +delegate(p1, p2) +delegate_original(p1, p2) +delegate(p2, p3) +delegate_original(p1, p3) +major_collect() +# XXX: current approach requires 2 major collections. +# the first to compress the path +# the second to do the copy +major_collect() +check_prebuilt(p1) +check_free_old(p2) +check_free_old(p3) + def test_prebuilt_version_to_protected(): p1 = lib.pseudoprebuilt(HDR, 42 + HDR) p2 = lib.stm_write_barrier(p1) @@ -321,6 +338,24 @@ check_prebuilt(p1) check_not_free(p2) # XXX replace with p1 +def test_prebuilt_version_to_protected_copy_over_prebuilt(): +py.test.skip(current copy-over-prebuilt-original approach +does not work with public_prebuilt-protected) +p1 = lib.pseudoprebuilt(HDR, 42 + HDR) +p2 = lib.stm_write_barrier(p1) +lib.stm_commit_transaction() +lib.stm_begin_inevitable_transaction() +minor_collect() +p2 = lib.stm_read_barrier(p1) +assert p2 != p1 +minor_collect() +major_collect() +major_collect() +print classify(p2) +check_prebuilt(p1) +check_free_old(p2) + + def test_private(): p1 = nalloc(HDR) lib.stm_push_root(p1) ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original: do a bit more
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r381:c1d5e6f19828 Date: 2013-07-10 08:59 +0200 http://bitbucket.org/pypy/stmgc/changeset/c1d5e6f19828/ Log:do a bit more diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -367,68 +367,70 @@ gcptr *pobj = stm_prebuilt_gcroots.items; gcptr *pend = stm_prebuilt_gcroots.items + stm_prebuilt_gcroots.size; gcptr obj; + for (; pobj != pend; pobj++) { obj = *pobj; assert(obj-h_tid GCFLAG_PREBUILT_ORIGINAL); -//assert(IS_POINTER(obj-h_revision)); + +if (IS_POINTER(obj-h_revision)) { +visit((gcptr *)obj-h_revision); +gcptr next = (gcptr)obj-h_revision; + +if (IS_POINTER((revision_t)next) /* needs to be an object */ + (next-h_revision 1) /* needs to be a head rev */ + !(obj-h_tid GCFLAG_PUBLIC_TO_PRIVATE)) { + +/* XXX: WHY? */ +assert(!(next-h_tid GCFLAG_PUBLIC_TO_PRIVATE)); + +assert(next-h_tid GCFLAG_OLD); /* not moved already */ +assert(next-h_original == (revision_t)obj); +assert(next-h_tid GCFLAG_PUBLIC); +assert(!(next-h_tid GCFLAG_STUB)); +assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); +assert(!(next-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); +assert(!(obj-h_tid GCFLAG_BACKUP_COPY)); +assert(!(next-h_tid GCFLAG_BACKUP_COPY)); + +/* copy next over obj but preserve possibly existing + pre-hash value and tid (prebuilt-flag) */ +revision_t pre_hash = obj-h_original; +revision_t old_tid = obj-h_tid; +memcpy(obj, next, stmgc_size(next)); +assert(!((obj-h_tid ^ old_tid) + (GCFLAG_BACKUP_COPY | GCFLAG_STUB +| GCFLAG_PUBLIC | GCFLAG_HAS_ID +| GCFLAG_PRIVATE_FROM_PROTECTED))); +obj-h_original = pre_hash; +obj-h_tid = old_tid; + +fprintf(stdout, copy %p over prebuilt %p\n, next, obj); + +/* Add this copied-over head revision to objects_to_trace + because it (next) was added by the preceeding visit() + but not at its new location (obj): */ +gcptrlist_insert(objects_to_trace, obj); -gcptr next = (gcptr)obj-h_revision; -/* XXX: do better. visit obj first and then - copy over if possible: */ -if (!(obj-h_revision 1) - (next-h_revision 1) - !(next-h_tid GCFLAG_VISITED) - (next-h_tid GCFLAG_OLD) - !(next-h_tid GCFLAG_PUBLIC_TO_PRIVATE) /* XXX */ - !(obj-h_tid GCFLAG_PUBLIC_TO_PRIVATE)) { +/* For those visiting later: */ +next-h_revision = (revision_t)obj; -assert(next-h_original == (revision_t)obj); -assert(next-h_tid GCFLAG_PUBLIC); -assert(!(next-h_tid GCFLAG_STUB)); -assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); -assert(!(next-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); -assert(!(obj-h_tid GCFLAG_BACKUP_COPY)); -assert(!(next-h_tid GCFLAG_BACKUP_COPY)); +/* mark somehow so that we can update pub_to_priv + for inevitable transactions and others ignore + it during tracing. Otherwise, inev transactions + will think 'next' is outdated. */ +next-h_tid = ~GCFLAG_OLD; - -revision_t pre_hash = obj-h_original; -revision_t old_tid = obj-h_tid; -memcpy(obj, next, stmgc_size(next)); -assert(!((obj-h_tid ^ old_tid) - (GCFLAG_BACKUP_COPY | GCFLAG_STUB -| GCFLAG_PUBLIC | GCFLAG_HAS_ID -| GCFLAG_PRIVATE_FROM_PROTECTED))); -obj-h_original = pre_hash; -obj-h_tid = old_tid; +} +/* obj does not need tracing if it can't + be reached from somewhere else*/ +} +else { +gcptrlist_insert(objects_to_trace, obj); +} -fprintf(stdout, copy %p over prebuilt %p\n, next, obj); - -/* will not be freed anyway and visit() only traces - head revision if not visited already */ -obj-h_tid = ~GCFLAG_VISITED; -/* For those visiting later: - XXX: don't: they will think that they are outdated*/ -next-h_revision = (revision_t)obj; -//if (next-h_tid GCFLAG_PUBLIC_TO_PRIVATE) { -// may have already lost it
[pypy-commit] stmgc default: fix writing to write-ready objects after a minor collection
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r382:191c168da60e Date: 2013-07-11 06:40 +0200 http://bitbucket.org/pypy/stmgc/changeset/191c168da60e/ Log:fix writing to write-ready objects after a minor collection diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -125,6 +125,9 @@ } // +/* list for private/protected, old roots that need to be + kept in old_objects_to_trace */ +static __thread struct GcPtrList private_or_protected_roots = {0, 0, NULL}; static inline gcptr create_old_object_copy(gcptr obj) { @@ -204,6 +207,22 @@ (revision_t)END_MARKER_ON)) { /* 'item' is a regular, non-null pointer */ visit_if_young(end); + +/* if old, private or protected, this object needs to be + traced again in the next minor_collect if it is + currently in old_objects_to_trace. Because then + it may be seen as write-ready in the view of + someone: + pw = write_barrier(); push_root(pw); + minor_collect(); pw = pop_root(); // pw still write-ready +*/ +if (item item-h_tid GCFLAG_OLD + !(item-h_tid GCFLAG_WRITE_BARRIER) /* not set in + obj_to_trace*/ + (item-h_tid GCFLAG_PRIVATE_FROM_PROTECTED +|| item-h_revision == stm_private_rev_num)) { +gcptrlist_insert(private_or_protected_roots, item); +} } else if (item != NULL) { if (item == END_MARKER_OFF) @@ -358,6 +377,19 @@ stmgc_trace(obj, visit_if_young); } + +while (gcptrlist_size(private_or_protected_roots) 0) { +gcptr obj = gcptrlist_pop(private_or_protected_roots); +/* if it has the write_barrier flag, clear it so that + it doesn't get inserted twice by a later write-barrier */ +if (obj-h_tid GCFLAG_WRITE_BARRIER) { +/* only insert those that were in old_obj_to_trace + and that we didn't insert already */ +obj-h_tid = ~GCFLAG_WRITE_BARRIER; +gcptrlist_insert(d-old_objects_to_trace, obj); +dprintf((re-add %p to old_objects_to_trace\n, obj)); +} +} } static void fix_list_of_read_objects(struct tx_descriptor *d) @@ -406,7 +438,7 @@ static void teardown_minor_collect(struct tx_descriptor *d) { -assert(gcptrlist_size(d-old_objects_to_trace) == 0); +//assert(gcptrlist_size(d-old_objects_to_trace) == 0); assert(gcptrlist_size(d-public_with_young_copy) == 0); assert(gcptrlist_size(d-public_descriptor-stolen_objects) == 0); diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -205,36 +205,52 @@ assert list_of_read_objects() == [p2] def test_write_barrier_after_minor_collect(): -# maybe should fail. not sure. p = oalloc_refs(1) pw = lib.stm_write_barrier(p) lib.stm_push_root(pw) minor_collect() +lib.stm_push_root(ffi.NULL) +minor_collect() +lib.stm_pop_root() +minor_collect() r = nalloc(HDR) pw = lib.stm_pop_root() assert pw.h_tid GCFLAG_OLD rawsetptr(pw, 0, r) -# pw not in old_objects_to_trace. A -# repeated write_barrier before -# rawsetptr() would fix that - +# pw needs to be readded to old_objects_to_trace +# before the next minor gc in order for this test to pass lib.stm_push_root(r) minor_collect() +minor_collect() +minor_collect() +q = nalloc(HDR) r2 = lib.stm_pop_root() check_nursery_free(r) pr = lib.stm_read_barrier(p) assert r != r2 -# these will fail because pw/pr was -# not traced in the last minor_collect, -# because they were not registered in -# old_objects_to_trace. assert getptr(pr, 0) != r assert getptr(pr, 0) == r2 +# the following shouldn't be done +# because pw was not saved. Just +# here to check that pw gets removed +# from old_objects_to_trace when not found +# on the root stack anymore +rawsetptr(pw, 0, q) +lib.stm_push_root(q) +minor_collect() +q2 = lib.stm_pop_root() +check_nursery_free(q) +pr = lib.stm_read_barrier(p) +assert q != q2 +assert getptr(pr, 0) == q +assert getptr(pr, 0) != q2 + + def test_id_young_to_old(): # move out of nursery with shadow original p = nalloc(HDR) diff --git a/duhton/listobject.c b/duhton/listobject.c --- a/duhton/listobject.c +++ b/duhton/listobject.c @@ -75,7 +75,7 @@ void _list_append(DuListObject *ob, DuObject *x) { -_du_read1(ob); +_du_write1(ob); DuTupleObject *olditems = ob-ob_tuple; _du_read1(olditems); @@ -85,8 +85,6 @@ DuTupleObject *newitems =
[pypy-commit] stmgc copy-over-original: fix bad cleanup :(
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r386:b2090bd31f4d Date: 2013-07-11 08:00 +0200 http://bitbucket.org/pypy/stmgc/changeset/b2090bd31f4d/ Log:fix bad cleanup :( diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -589,7 +589,8 @@ assert(!(obj-h_tid GCFLAG_STUB)); if (!(obj-h_tid GCFLAG_OLD)) { -items[i] = (gcptr)obj-h_revision; +obj = (gcptr)obj-h_revision; +items[i] = obj; } else if (obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { /* Warning: in case the object listed is outdated and has been ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original: merge default
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r383:ee69aa1b8ef3 Date: 2013-07-11 07:13 +0200 http://bitbucket.org/pypy/stmgc/changeset/ee69aa1b8ef3/ Log:merge default diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -125,6 +125,9 @@ } // +/* list for private/protected, old roots that need to be + kept in old_objects_to_trace */ +static __thread struct GcPtrList private_or_protected_roots = {0, 0, NULL}; static inline gcptr create_old_object_copy(gcptr obj) { @@ -204,6 +207,22 @@ (revision_t)END_MARKER_ON)) { /* 'item' is a regular, non-null pointer */ visit_if_young(end); + +/* if old, private or protected, this object needs to be + traced again in the next minor_collect if it is + currently in old_objects_to_trace. Because then + it may be seen as write-ready in the view of + someone: + pw = write_barrier(); push_root(pw); + minor_collect(); pw = pop_root(); // pw still write-ready +*/ +if (item item-h_tid GCFLAG_OLD + !(item-h_tid GCFLAG_WRITE_BARRIER) /* not set in + obj_to_trace*/ + (item-h_tid GCFLAG_PRIVATE_FROM_PROTECTED +|| item-h_revision == stm_private_rev_num)) { +gcptrlist_insert(private_or_protected_roots, item); +} } else if (item != NULL) { if (item == END_MARKER_OFF) @@ -358,6 +377,19 @@ stmgc_trace(obj, visit_if_young); } + +while (gcptrlist_size(private_or_protected_roots) 0) { +gcptr obj = gcptrlist_pop(private_or_protected_roots); +/* if it has the write_barrier flag, clear it so that + it doesn't get inserted twice by a later write-barrier */ +if (obj-h_tid GCFLAG_WRITE_BARRIER) { +/* only insert those that were in old_obj_to_trace + and that we didn't insert already */ +obj-h_tid = ~GCFLAG_WRITE_BARRIER; +gcptrlist_insert(d-old_objects_to_trace, obj); +dprintf((re-add %p to old_objects_to_trace\n, obj)); +} +} } static void fix_list_of_read_objects(struct tx_descriptor *d) @@ -410,7 +442,7 @@ static void teardown_minor_collect(struct tx_descriptor *d) { -assert(gcptrlist_size(d-old_objects_to_trace) == 0); +//assert(gcptrlist_size(d-old_objects_to_trace) == 0); assert(gcptrlist_size(d-public_with_young_copy) == 0); assert(gcptrlist_size(d-public_descriptor-stolen_objects) == 0); diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -205,36 +205,52 @@ assert list_of_read_objects() == [p2] def test_write_barrier_after_minor_collect(): -# maybe should fail. not sure. p = oalloc_refs(1) pw = lib.stm_write_barrier(p) lib.stm_push_root(pw) minor_collect() +lib.stm_push_root(ffi.NULL) +minor_collect() +lib.stm_pop_root() +minor_collect() r = nalloc(HDR) pw = lib.stm_pop_root() assert pw.h_tid GCFLAG_OLD rawsetptr(pw, 0, r) -# pw not in old_objects_to_trace. A -# repeated write_barrier before -# rawsetptr() would fix that - +# pw needs to be readded to old_objects_to_trace +# before the next minor gc in order for this test to pass lib.stm_push_root(r) minor_collect() +minor_collect() +minor_collect() +q = nalloc(HDR) r2 = lib.stm_pop_root() check_nursery_free(r) pr = lib.stm_read_barrier(p) assert r != r2 -# these will fail because pw/pr was -# not traced in the last minor_collect, -# because they were not registered in -# old_objects_to_trace. assert getptr(pr, 0) != r assert getptr(pr, 0) == r2 +# the following shouldn't be done +# because pw was not saved. Just +# here to check that pw gets removed +# from old_objects_to_trace when not found +# on the root stack anymore +rawsetptr(pw, 0, q) +lib.stm_push_root(q) +minor_collect() +q2 = lib.stm_pop_root() +check_nursery_free(q) +pr = lib.stm_read_barrier(p) +assert q != q2 +assert getptr(pr, 0) == q +assert getptr(pr, 0) != q2 + + def test_id_young_to_old(): # move out of nursery with shadow original p = nalloc(HDR) diff --git a/duhton/demo/trees.duh b/duhton/demo/trees.duh --- a/duhton/demo/trees.duh +++ b/duhton/demo/trees.duh @@ -1,15 +1,16 @@ (defun create-tree (n) - (if ( n 1) (list 1) (list (create-tree (/ n 2)) (create-tree (/ n 2 + (if (== n 0) 1 (cons (create-tree (- n 1)) (create-tree (- n 1 ) (defun walk-tree (tree) - (if (== (len tree) 1) (get tree 0) - (+
[pypy-commit] stmgc copy-over-original: typo
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r385:844c3aeccf50 Date: 2013-07-11 07:52 +0200 http://bitbucket.org/pypy/stmgc/changeset/844c3aeccf50/ Log:typo diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -406,7 +406,7 @@ obj-h_original = pre_hash; obj-h_tid = old_tid; -dprintf(stdout, copy %p over prebuilt %p\n, next, obj); +dprintf((copy %p over prebuilt %p\n, next, obj)); /* Add this copied-over head revision to objects_to_trace because it (next) was added by the preceeding visit() ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original: cleanups
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r384:2e860d218333 Date: 2013-07-11 07:48 +0200 http://bitbucket.org/pypy/stmgc/changeset/2e860d218333/ Log:cleanups diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -380,12 +380,14 @@ (next-h_revision 1) /* needs to be a head rev */ !(obj-h_tid GCFLAG_PUBLIC_TO_PRIVATE)) { -/* XXX: WHY? */ +/* XXX: WHY never hit? */ assert(!(next-h_tid GCFLAG_PUBLIC_TO_PRIVATE)); assert(next-h_tid GCFLAG_OLD); /* not moved already */ assert(next-h_original == (revision_t)obj); -assert(next-h_tid GCFLAG_PUBLIC); +assert(next-h_tid GCFLAG_PUBLIC); /* no priv/prot! +otherwise we'd need to fix more lists +like old_objects_to_trace */ assert(!(next-h_tid GCFLAG_STUB)); assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); assert(!(next-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); @@ -404,7 +406,7 @@ obj-h_original = pre_hash; obj-h_tid = old_tid; -fprintf(stdout, copy %p over prebuilt %p\n, next, obj); +dprintf(stdout, copy %p over prebuilt %p\n, next, obj); /* Add this copied-over head revision to objects_to_trace because it (next) was added by the preceeding visit() @@ -422,7 +424,7 @@ } /* obj does not need tracing if it can't - be reached from somewhere else*/ + be reached from somewhere else */ } else { gcptrlist_insert(objects_to_trace, obj); @@ -457,6 +459,9 @@ static void mark_all_stack_roots(void) { struct tx_descriptor *d; +struct G2L new_public_to_private; +memset(new_public_to_private, 0, sizeof(struct G2L)); + for (d = stm_tx_head; d; d = d-tx_next) { assert(!stm_has_got_any_lock(d)); @@ -469,39 +474,36 @@ /* the current transaction's private copies of public objects */ wlog_t *item; -if (1 || d-active == 2) { -/* inevitable transactions need to have their pub_to_priv - fixed. Otherwise, they'll think their objects got outdated */ -/* XXX: others too, but maybe not worth it */ -struct G2L new_public_to_private; -memset(new_public_to_private, 0, sizeof(struct G2L)); -fprintf(stdout, start fixup (%p):\n, d); -G2L_LOOP_FORWARD(d-public_to_private, item) { -gcptr R = item-addr; -gcptr L = item-val; -if (!(R-h_tid GCFLAG_OLD)) { -/* R was copied over its original */ -gcptr new_R = (gcptr)R-h_original; -g2l_insert(new_public_to_private, new_R, L); -G2L_LOOP_DELETE(item); - -if (L-h_revision == (revision_t)R) { -L-h_revision = (revision_t)new_R; -fprintf(stdout, fixup %p to %p - %p\n, R, new_R, L); -} -else -fprintf(stdout, fixup %p to %p - %p\n, R, new_R, L); +/* transactions need to have their pub_to_priv fixed. Otherwise, + they'll think their objects got outdated. Only absolutely + necessary for inevitable transactions (XXX check performance?). */ +dprintf((start fixup (%p):\n, d)); +G2L_LOOP_FORWARD(d-public_to_private, item) { +gcptr R = item-addr; +gcptr L = item-val; +if (!(R-h_tid GCFLAG_OLD)) { +/* R was copied over its original */ +gcptr new_R = (gcptr)R-h_original; +g2l_insert(new_public_to_private, new_R, L); +G2L_LOOP_DELETE(item); + +if (L-h_revision == (revision_t)R) { +L-h_revision = (revision_t)new_R; +dprintf(( fixup %p to %p - %p\n, R, new_R, L)); } -} G2L_LOOP_END; - -/* copy to real pub_to_priv */ -G2L_LOOP_FORWARD(new_public_to_private, item) { -g2l_insert(d-public_to_private, item-addr, item-val); -} G2L_LOOP_END; -g2l_delete_not_used_any_more(new_public_to_private); -} +else +dprintf(( fixup %p to %p - %p\n, R, new_R, L)); +} +} G2L_LOOP_END; +/* copy to real pub_to_priv */ +G2L_LOOP_FORWARD(new_public_to_private, item) { +g2l_insert(d-public_to_private, item-addr, item-val); +} G2L_LOOP_END; +
[pypy-commit] stmgc default: add cache of writeables to demo_random.c and fix a bug
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r387:9c2b50efb633 Date: 2013-07-11 10:13 +0200 http://bitbucket.org/pypy/stmgc/changeset/9c2b50efb633/ Log:add cache of writeables to demo_random.c and fix a bug diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -52,6 +52,12 @@ // global and per-thread-data time_t default_seed; gcptr shared_roots[SHARED_ROOTS]; + +#define CACHE_MASK 65535 +#define CACHE_ENTRIES ((CACHE_MASK + 1) / sizeof(char *)) +#define CACHE_AT(cache, obj) (*(gcptr *)((char *)(cache) \ + + ((revision_t)(obj) CACHE_MASK))) + struct thread_data { unsigned int thread_seed; gcptr roots[MAXROOTS]; @@ -61,6 +67,7 @@ int steps_left; int interruptible; int atomic; +revision_t writeable[CACHE_ENTRIES]; }; __thread struct thread_data td; @@ -140,6 +147,7 @@ } } +__thread revision_t temp_cache[CACHE_ENTRIES]; void pop_roots() { int i; @@ -148,6 +156,8 @@ td.roots[i] = stm_pop_root(); check(td.roots[i]); } +/* some objects may have changed positions */ +memset(td.writeable, 0, sizeof(td.writeable)); } void del_root(int idx) @@ -227,6 +237,7 @@ if (p != NULL) { check(p); w = stm_write_barrier(p); +CACHE_AT(td.writeable, w) = w; check(w); assert(is_private(w)); } @@ -298,6 +309,8 @@ void setup_thread() { int i; +memset(td, 0, sizeof(struct thread_data)); + td.thread_seed = default_seed++; td.steps_left = STEPS_PER_THREAD; td.interruptible = 0; @@ -395,7 +408,10 @@ break; case 7: // set 'p' as *next in one of the roots check(_r); -w_r = (nodeptr)write_barrier(_r); +if (CACHE_AT(td.writeable, _r) == _r) +w_r = (nodeptr)_r; +else +w_r = (nodeptr)write_barrier(_r); check((gcptr)w_r); check(p); w_r-next = (struct node*)p; @@ -454,7 +470,10 @@ assert(w_t-id == stm_id((gcptr)_t)); } else { -w_t = (nodeptr)write_barrier(_t); +if (CACHE_AT(td.writeable, _t) == _t) +w_t = (nodeptr)_t; +else +w_t = (nodeptr)write_barrier(_t); w_t-id = stm_id((gcptr)w_t); assert(w_t-id == stm_id((gcptr)_t)); } @@ -470,7 +489,10 @@ assert(w_t-hash == stm_hash((gcptr)_t)); } else { -w_t = (nodeptr)write_barrier(_t); +if (CACHE_AT(td.writeable, _t) == _t) +w_t = (nodeptr)_t; +else +w_t = (nodeptr)write_barrier(_t); w_t-hash = stm_hash((gcptr)w_t); assert(w_t-hash == stm_hash((gcptr)_t)); } @@ -538,6 +560,8 @@ td.interruptible = 0; pop_roots(); + +memset(td.writeable, 0, sizeof(td.writeable)); } @@ -558,6 +582,7 @@ stm_push_root(end_marker); int p = run_me(); + if (p == -1) // maybe restart transaction return get_rand(3) != 1; @@ -567,6 +592,10 @@ int run_me() { gcptr p = NULL; + +// clear cache of writeables: +memset(td.writeable, 0, sizeof(td.writeable)); + while (td.steps_left--0 || td.atomic) { if (td.steps_left % 8 == 0) fprintf(stdout, #); diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -207,8 +207,8 @@ (revision_t)END_MARKER_ON)) { /* 'item' is a regular, non-null pointer */ visit_if_young(end); - -/* if old, private or protected, this object needs to be +item = *end; +/* if private or protected, this object needs to be traced again in the next minor_collect if it is currently in old_objects_to_trace. Because then it may be seen as write-ready in the view of @@ -216,7 +216,7 @@ pw = write_barrier(); push_root(pw); minor_collect(); pw = pop_root(); // pw still write-ready */ -if (item item-h_tid GCFLAG_OLD +if (item !(item-h_tid GCFLAG_WRITE_BARRIER) /* not set in obj_to_trace*/ (item-h_tid GCFLAG_PRIVATE_FROM_PROTECTED diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -250,6 +250,25 @@ assert getptr(pr, 0) == q assert getptr(pr, 0) != q2 +def test_write_barrier_after_minor_collect_young_to_old(): +p = nalloc_refs(1) +pw = lib.stm_write_barrier(p) + +lib.stm_push_root(pw) +minor_collect() +r = nalloc(HDR) +pw = lib.stm_pop_root() + +check_nursery_free(p) +assert pw.h_tid GCFLAG_OLD +rawsetptr(pw, 0, r) + +
[pypy-commit] stmgc copy-over-original: merge default
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r388:dba9439565bd Date: 2013-07-11 10:14 +0200 http://bitbucket.org/pypy/stmgc/changeset/dba9439565bd/ Log:merge default diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -52,6 +52,12 @@ // global and per-thread-data time_t default_seed; gcptr shared_roots[SHARED_ROOTS]; + +#define CACHE_MASK 65535 +#define CACHE_ENTRIES ((CACHE_MASK + 1) / sizeof(char *)) +#define CACHE_AT(cache, obj) (*(gcptr *)((char *)(cache) \ + + ((revision_t)(obj) CACHE_MASK))) + struct thread_data { unsigned int thread_seed; gcptr roots[MAXROOTS]; @@ -61,6 +67,7 @@ int steps_left; int interruptible; int atomic; +revision_t writeable[CACHE_ENTRIES]; }; __thread struct thread_data td; @@ -140,6 +147,7 @@ } } +__thread revision_t temp_cache[CACHE_ENTRIES]; void pop_roots() { int i; @@ -148,6 +156,8 @@ td.roots[i] = stm_pop_root(); check(td.roots[i]); } +/* some objects may have changed positions */ +memset(td.writeable, 0, sizeof(td.writeable)); } void del_root(int idx) @@ -227,6 +237,7 @@ if (p != NULL) { check(p); w = stm_write_barrier(p); +CACHE_AT(td.writeable, w) = w; check(w); assert(is_private(w)); } @@ -298,6 +309,8 @@ void setup_thread() { int i; +memset(td, 0, sizeof(struct thread_data)); + td.thread_seed = default_seed++; td.steps_left = STEPS_PER_THREAD; td.interruptible = 0; @@ -395,7 +408,10 @@ break; case 7: // set 'p' as *next in one of the roots check(_r); -w_r = (nodeptr)write_barrier(_r); +if (CACHE_AT(td.writeable, _r) == _r) +w_r = (nodeptr)_r; +else +w_r = (nodeptr)write_barrier(_r); check((gcptr)w_r); check(p); w_r-next = (struct node*)p; @@ -454,7 +470,10 @@ assert(w_t-id == stm_id((gcptr)_t)); } else { -w_t = (nodeptr)write_barrier(_t); +if (CACHE_AT(td.writeable, _t) == _t) +w_t = (nodeptr)_t; +else +w_t = (nodeptr)write_barrier(_t); w_t-id = stm_id((gcptr)w_t); assert(w_t-id == stm_id((gcptr)_t)); } @@ -470,7 +489,10 @@ assert(w_t-hash == stm_hash((gcptr)_t)); } else { -w_t = (nodeptr)write_barrier(_t); +if (CACHE_AT(td.writeable, _t) == _t) +w_t = (nodeptr)_t; +else +w_t = (nodeptr)write_barrier(_t); w_t-hash = stm_hash((gcptr)w_t); assert(w_t-hash == stm_hash((gcptr)_t)); } @@ -538,6 +560,8 @@ td.interruptible = 0; pop_roots(); + +memset(td.writeable, 0, sizeof(td.writeable)); } @@ -558,6 +582,7 @@ stm_push_root(end_marker); int p = run_me(); + if (p == -1) // maybe restart transaction return get_rand(3) != 1; @@ -567,6 +592,10 @@ int run_me() { gcptr p = NULL; + +// clear cache of writeables: +memset(td.writeable, 0, sizeof(td.writeable)); + while (td.steps_left--0 || td.atomic) { if (td.steps_left % 8 == 0) fprintf(stdout, #); diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -207,8 +207,8 @@ (revision_t)END_MARKER_ON)) { /* 'item' is a regular, non-null pointer */ visit_if_young(end); - -/* if old, private or protected, this object needs to be +item = *end; +/* if private or protected, this object needs to be traced again in the next minor_collect if it is currently in old_objects_to_trace. Because then it may be seen as write-ready in the view of @@ -216,7 +216,7 @@ pw = write_barrier(); push_root(pw); minor_collect(); pw = pop_root(); // pw still write-ready */ -if (item item-h_tid GCFLAG_OLD +if (item !(item-h_tid GCFLAG_WRITE_BARRIER) /* not set in obj_to_trace*/ (item-h_tid GCFLAG_PRIVATE_FROM_PROTECTED diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -250,6 +250,25 @@ assert getptr(pr, 0) == q assert getptr(pr, 0) != q2 +def test_write_barrier_after_minor_collect_young_to_old(): +p = nalloc_refs(1) +pw = lib.stm_write_barrier(p) + +lib.stm_push_root(pw) +minor_collect() +r = nalloc(HDR) +pw = lib.stm_pop_root() + +check_nursery_free(p) +assert pw.h_tid GCFLAG_OLD +rawsetptr(pw, 0, r) + +lib.stm_push_root(pw) +
[pypy-commit] stmgc copy-over-original: free objects that are copied over prebuilts in the same major collection
Author: Remi Meier meier...@student.ethz.ch Branch: copy-over-original Changeset: r392:ea61566d33cd Date: 2013-07-11 12:12 +0200 http://bitbucket.org/pypy/stmgc/changeset/ea61566d33cd/ Log:free objects that are copied over prebuilts in the same major collection diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -223,6 +223,7 @@ id_copy-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ id_copy-h_tid |= GCFLAG_VISITED; +assert(id_copy-h_tid GCFLAG_OLD); /* XXX: may not always need tracing? */ if (!(id_copy-h_tid GCFLAG_STUB)) @@ -249,6 +250,7 @@ if (!(obj-h_tid GCFLAG_VISITED)) { obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ obj-h_tid |= GCFLAG_VISITED; +assert(obj-h_tid GCFLAG_OLD); gcptrlist_insert(objects_to_trace, obj); keep_original_alive(obj); @@ -272,6 +274,7 @@ obj = (gcptr)(obj-h_revision - 2); if (!(obj-h_tid GCFLAG_PUBLIC)) { prev_obj-h_tid |= GCFLAG_VISITED; +assert(prev_obj-h_tid GCFLAG_OLD); keep_original_alive(prev_obj); assert(*pobj == prev_obj); @@ -315,6 +318,9 @@ obj-h_tid |= GCFLAG_VISITED; B-h_tid |= GCFLAG_VISITED; +assert(obj-h_tid GCFLAG_OLD); +assert(B-h_tid GCFLAG_OLD); + assert(!(obj-h_tid GCFLAG_STUB)); assert(!(B-h_tid GCFLAG_STUB)); gcptrlist_insert2(objects_to_trace, obj, B); @@ -337,6 +343,7 @@ if (!(obj-h_tid GCFLAG_VISITED)) { obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ obj-h_tid |= GCFLAG_VISITED; +assert(obj-h_tid GCFLAG_OLD); gcptrlist_insert(objects_to_trace, obj); if (IS_POINTER(obj-h_revision)) { @@ -379,20 +386,14 @@ if (IS_POINTER((revision_t)next) /* needs to be an object */ (next-h_revision 1) /* needs to be a head rev */ !(obj-h_tid GCFLAG_PUBLIC_TO_PRIVATE)) { - -/* XXX: WHY never hit? */ -assert(!(next-h_tid GCFLAG_PUBLIC_TO_PRIVATE)); - + +/* next may have had PUBLIC_TO_PRIVATE, but that was + cleared in the preceeding visit() */ assert(next-h_tid GCFLAG_OLD); /* not moved already */ assert(next-h_original == (revision_t)obj); assert(next-h_tid GCFLAG_PUBLIC); /* no priv/prot! otherwise we'd need to fix more lists like old_objects_to_trace */ -assert(!(next-h_tid GCFLAG_STUB)); -assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); -assert(!(next-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); -assert(!(obj-h_tid GCFLAG_BACKUP_COPY)); -assert(!(next-h_tid GCFLAG_BACKUP_COPY)); /* copy next over obj but preserve possibly existing pre-hash value and tid (prebuilt-flag) */ @@ -420,8 +421,7 @@ for inevitable transactions and others ignore it during tracing. Otherwise, inev transactions will think 'next' is outdated. */ -next-h_tid = ~GCFLAG_OLD; - +next-h_tid = ~(GCFLAG_OLD | GCFLAG_VISITED); } /* obj does not need tracing if it can't be reached from somewhere else */ @@ -571,6 +571,11 @@ items[i] = items[--d-private_from_protected.size]; } } + +/* In old_objects_to_trace there can be a now invalid object + NO: never happens because only priv/prot objects can still + be in old_objects_to_trace after the forced minor_collection. + And we do not copy such objects over prebuilts. */ /* If we're aborting this transaction anyway, we don't need to do * more here. @@ -756,6 +761,7 @@ gcptr p = item-addr; if (p-h_tid GCFLAG_VISITED) { p-h_tid = ~GCFLAG_VISITED; +assert(p-h_tid GCFLAG_OLD); } else { G2L_LOOP_DELETE(item); diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py --- a/c4/test/test_gcpage.py +++ b/c4/test/test_gcpage.py @@ -323,9 +323,6 @@ check_prebuilt(p1) assert lib.stm_hash(p1) == 99 check_free_old(p2) -check_not_free(p3) -# XXX: takes another major collection to free p3 -major_collect() check_free_old(p3) def test_prebuilt_version_to_protected(): ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: merge
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r394:19e89845f0a0 Date: 2013-07-11 17:36 +0200 http://bitbucket.org/pypy/stmgc/changeset/19e89845f0a0/ Log:merge diff --git a/duhton/glob.c b/duhton/glob.c --- a/duhton/glob.c +++ b/duhton/glob.c @@ -199,7 +199,7 @@ DuObject *du_div(DuObject *cons, DuObject *locals) { int result = 0; - int first = 1; +int first = 1; while (cons != Du_None) { _du_read1(cons); @@ -208,12 +208,12 @@ _du_save2(next, locals); DuObject *obj = Du_Eval(expr, locals); - if (first) { - result = DuInt_AsInt(obj); - first = 0; - } else { - result /= DuInt_AsInt(obj); - } +if (first) { +result = DuInt_AsInt(obj); +first = 0; +} else { +result /= DuInt_AsInt(obj); +} _du_restore2(next, locals); cons = next; @@ -612,8 +612,8 @@ void Du_Initialize(int num_threads) { stm_initialize(); - all_threads_count = num_threads; - all_threads = (pthread_t*)malloc(sizeof(pthread_t) * num_threads); +all_threads_count = num_threads; +all_threads = (pthread_t*)malloc(sizeof(pthread_t) * num_threads); DuFrame_SetBuiltinMacro(Du_Globals, progn, Du_Progn); DuFrame_SetBuiltinMacro(Du_Globals, setq, du_setq); @@ -621,7 +621,7 @@ DuFrame_SetBuiltinMacro(Du_Globals, +, du_add); DuFrame_SetBuiltinMacro(Du_Globals, -, du_sub); DuFrame_SetBuiltinMacro(Du_Globals, *, du_mul); - DuFrame_SetBuiltinMacro(Du_Globals, /, du_div); +DuFrame_SetBuiltinMacro(Du_Globals, /, du_div); DuFrame_SetBuiltinMacro(Du_Globals, , du_lt); DuFrame_SetBuiltinMacro(Du_Globals, =, du_le); DuFrame_SetBuiltinMacro(Du_Globals, ==, du_eq); @@ -642,12 +642,12 @@ DuFrame_SetBuiltinMacro(Du_Globals, defun, du_defun); DuFrame_SetBuiltinMacro(Du_Globals, car, du_car); DuFrame_SetBuiltinMacro(Du_Globals, cdr, du_cdr); - DuFrame_SetBuiltinMacro(Du_Globals, cons, du_cons); +DuFrame_SetBuiltinMacro(Du_Globals, cons, du_cons); DuFrame_SetBuiltinMacro(Du_Globals, not, du_not); DuFrame_SetBuiltinMacro(Du_Globals, transaction, du_transaction); DuFrame_SetBuiltinMacro(Du_Globals, sleepms, du_sleepms); DuFrame_SetBuiltinMacro(Du_Globals, defined?, du_defined); - DuFrame_SetBuiltinMacro(Du_Globals, pair?, du_pair); +DuFrame_SetBuiltinMacro(Du_Globals, pair?, du_pair); DuFrame_SetBuiltinMacro(Du_Globals, assert, du_assert); DuFrame_SetSymbolStr(Du_Globals, None, Du_None); } diff --git a/duhton/test/test_cons.py b/duhton/test/test_cons.py --- a/duhton/test/test_cons.py +++ b/duhton/test/test_cons.py @@ -10,6 +10,8 @@ def test_pair(): assert run((print (pair? 1))) == 0\n assert run((print (pair? (cons 1 2 == 1\n +assert run((setq x (cons 1 2)) (print (pair? x))) == 1\n +assert run((setq x 42) (print (pair? x))) == 0\n def test_car_cdr(): assert run((print (car (quote (2 3) == 2\n diff --git a/duhton/test/test_int.py b/duhton/test/test_int.py --- a/duhton/test/test_int.py +++ b/duhton/test/test_int.py @@ -20,6 +20,10 @@ assert evaluate((* 2 3 7)) == 42 assert evaluate((* (+ 5 1) (+ 6 1))) == 42 +def test_div(): +assert evaluate((/ 11 2)) == 5 +assert evaluate((/ 29 2 3)) == 4 + def test_cmp(): assert evaluate(( 6 6)) == 0 assert evaluate((= 6 6)) == 1 ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: improve demo_random
Author: Remi Meier meier...@student.ethz.ch Branch: Changeset: r393:d791f50ecec8 Date: 2013-07-11 17:36 +0200 http://bitbucket.org/pypy/stmgc/changeset/d791f50ecec8/ Log:improve demo_random diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -137,7 +137,7 @@ return x; } -void push_roots() +void push_roots(int with_cache) { int i; for (i = 0; i td.num_roots; i++) { @@ -145,19 +145,35 @@ if (td.roots[i]) stm_push_root(td.roots[i]); } + +if (with_cache) { +stm_push_root(NULL); +for (i = 0; i CACHE_ENTRIES; i++) { +if (td.writeable[i]) +stm_push_root((gcptr)td.writeable[i]); +} +} } -__thread revision_t temp_cache[CACHE_ENTRIES]; -void pop_roots() +void pop_roots(int with_cache) { int i; +/* some objects may have changed positions */ +memset(td.writeable, 0, sizeof(td.writeable)); + +if (with_cache) { +gcptr obj = stm_pop_root(); +while (obj) { +CACHE_AT(td.writeable, obj) = obj; +obj = stm_pop_root(); +} +} + for (i = td.num_roots - 1; i = 0; i--) { if (td.roots[i]) td.roots[i] = stm_pop_root(); check(td.roots[i]); } -/* some objects may have changed positions */ -memset(td.writeable, 0, sizeof(td.writeable)); } void del_root(int idx) @@ -170,9 +186,9 @@ nodeptr allocate_node() { nodeptr r; -push_roots(); +push_roots(1); r = (nodeptr)stm_allocate(sizeof(struct node), GCTID_STRUCT_NODE); -pop_roots(); +pop_roots(1); return r; } @@ -354,22 +370,22 @@ { int k = get_rand(100); if (k 10) { -push_roots(); +push_roots(1); stm_push_root(p); stm_become_inevitable(fun); p = stm_pop_root(); -pop_roots(); +pop_roots(1); } else if (k 40) { -push_roots(); +push_roots(1); stmgc_minor_collect(); -pop_roots(); +pop_roots(1); p = NULL; } else if (k 41 DO_MAJOR_COLLECTS) { fprintf(stdout, major collect\n); -push_roots(); +push_roots(1); stmgcpage_possibly_major_collect(1); -pop_roots(); +pop_roots(1); p = NULL; } return p; @@ -534,8 +550,9 @@ p = id_hash_events(p, _r, _sr); else if (k 8) p = rare_events(p, _r, _sr); -else if (get_rand(3) == 1) { +else if (get_rand(20) == 1) { // transaction break +fprintf(stdout, |); if (td.interruptible) return (gcptr)-1; // break current transaction_break(); @@ -547,7 +564,7 @@ void transaction_break() { -push_roots(); +push_roots(0); td.interruptible = 1; copy_roots(td.roots, td.roots_outside_perform, td.num_roots); @@ -559,9 +576,9 @@ copy_roots(td.roots_outside_perform, td.roots, td.num_roots); td.interruptible = 0; -pop_roots(); +pop_roots(0); -memset(td.writeable, 0, sizeof(td.writeable)); +/* done by pop_roots() memset(td.writeable, 0, sizeof(td.writeable)); */ } @@ -576,8 +593,8 @@ assert(end_marker == END_MARKER_ON || end_marker == END_MARKER_OFF); arg1 = stm_pop_root(); assert(arg1 == NULL); -pop_roots(); -push_roots(); +pop_roots(0); +push_roots(0); stm_push_root(arg1); stm_push_root(end_marker); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: hopefully in the right direction: now a single cond_call_stm_b because there may be many more variants in the future.
Author: Remi Meier meier...@student.ethz.ch Branch: stmgc-c4 Changeset: r65346:e1aa4591dc07 Date: 2013-07-11 18:12 +0200 http://bitbucket.org/pypy/pypy/changeset/e1aa4591dc07/ Log:hopefully in the right direction: now a single cond_call_stm_b because there may be many more variants in the future. diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -958,11 +958,8 @@ def execute_cond_call_gc_wb_array(self, descr, a, b, c): py.test.skip(cond_call_gc_wb_array not supported) -def execute_cond_call_stm_wb(self, descr, a): -py.test.skip(cond_call_stm_wb not supported) - -def execute_cond_call_stm_rb(self, descr, a): -py.test.skip(cond_call_stm_rb not supported) +def execute_cond_call_stm_b(self, descr, a): +py.test.skip(cond_call_stm_b not supported) def execute_keepalive(self, descr, x): pass diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -270,23 +270,43 @@ rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address) return rffi.cast(lltype.Signed, rst_addr) +class GcRootMap_stm(object): +is_shadow_stack = False # XXX: should it have an is_stmgc? -class WriteBarrierDescr(AbstractDescr): +def __init__(self, gcdescr): +pass + +def register_asm_addr(self, start, mark): +pass + +def get_root_stack_top_addr(self): +rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address) +return rffi.cast(lltype.Signed, rst_addr) + + +class BarrierDescr(AbstractDescr): def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 self.returns_modified_object = False -self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( +self.FUNCPTR = lltype.Ptr(lltype.FuncType( [llmemory.Address], lltype.Void)) -self.fielddescr_tid = gc_ll_descr.fielddescr_tid self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder self.HDRPTR = gc_ll_descr.HDRPTR -# + +def repr_of_descr(self): +raise NotImplementedError + +def __repr(self): +raise NotImplementedError + +class WriteBarrierDescr(BarrierDescr): +def __init__(self, gc_ll_descr): +BarrierDescr.__init__(self, gc_ll_descr) +self.fielddescr_tid = gc_ll_descr.fielddescr_tid + GCClass = gc_ll_descr.GCClass -if GCClass is None: # for tests -return - self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG self.jit_wb_if_flag_byteofs, self.jit_wb_if_flag_singlebyte = ( self.extract_flag_byte(self.jit_wb_if_flag)) @@ -325,14 +345,9 @@ return (i, struct.unpack('b', value[i])[0]) def get_barrier_funcptr(self, returns_modified_object): -assert returns_modified_object == self.returns_modified_object -llop1 = self.llop1 -if returns_modified_object: -funcptr = self.wb_failing_case_ptr -else: -FUNCTYPE = self.WB_FUNCPTR -funcptr = llop1.get_write_barrier_failing_case(FUNCTYPE) -return funcptr +assert not returns_modified_object +FUNCTYPE = self.FUNCPTR +return llop1.get_write_barrier_failing_case(FUNCTYPE) def get_write_barrier_fn(self, cpu, returns_modified_object): # must pass in 'self.returns_modified_object', to make sure that @@ -343,16 +358,13 @@ def get_write_barrier_from_array_fn(self, cpu): # returns a function with arguments [array, index, newvalue] -assert not self.returns_modified_object llop1 = self.llop1 funcptr = llop1.get_write_barrier_from_array_failing_case( -self.WB_FUNCPTR) +self.FUNCPTR) funcaddr = llmemory.cast_ptr_to_adr(funcptr) return cpu.cast_adr_to_int(funcaddr)# this may return 0 def has_write_barrier_from_array(self, cpu): -if self.returns_modified_object: -return False return self.get_write_barrier_from_array_fn(cpu) != 0 def get_wb_slowpath(self, withcards, withfloats): @@ -372,15 +384,11 @@ # the GC, and call it immediately funcptr = self.get_barrier_funcptr(returns_modified_object) res = funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) -if returns_modified_object: -return llmemory.cast_adr_to_ptr(res, llmemory.GCREF) -else: -if returns_modified_object: -return gcref_struct -class STMBarrierDescr(WriteBarrierDescr): + +class STMBarrierDescr(BarrierDescr): def __init__(self, gc_ll_descr, stmcat, cfunc_name): -WriteBarrierDescr.__init__(self, gc_ll_descr) +BarrierDescr.__init__(self, gc_ll_descr)
[pypy-commit] pypy stmgc-c4: remove R2W for now; introduce is_stm on GcRootMap
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65374:add171e74fe2 Date: 2013-07-12 08:29 +0200 http://bitbucket.org/pypy/pypy/changeset/add171e74fe2/ Log:remove R2W for now; introduce is_stm on GcRootMap diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -250,6 +250,7 @@ class GcRootMap_asmgcc(object): is_shadow_stack = False +is_stm = False def __init__(self, gcdescr): pass @@ -259,7 +260,8 @@ class GcRootMap_shadowstack(object): is_shadow_stack = True - +is_stm = False + def __init__(self, gcdescr): pass @@ -271,8 +273,9 @@ return rffi.cast(lltype.Signed, rst_addr) class GcRootMap_stm(object): -is_shadow_stack = True # XXX: should it have an is_stmgc? - +is_shadow_stack = True +is_stm = True + def __init__(self, gcdescr): pass @@ -535,7 +538,6 @@ def _setup_barriers_for_stm(self): self.P2Rdescr = STMReadBarrierDescr(self, 'P2R') self.P2Wdescr = STMWriteBarrierDescr(self, 'P2W') -self.R2Wdescr = STMWriteBarrierDescr(self, 'R2W') self.write_barrier_descr = wbdescr: do not use # @specialize.argtype(0) diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py --- a/rpython/jit/backend/llsupport/stmrewrite.py +++ b/rpython/jit/backend/llsupport/stmrewrite.py @@ -34,7 +34,7 @@ 'P': {'R': self.gc_ll_descr.P2Rdescr, 'W': self.gc_ll_descr.P2Wdescr, }, -'R': {'W': self.gc_ll_descr.R2Wdescr, +'R': {'W': self.gc_ll_descr.P2Wdescr, }, 'W': {}, } diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py b/rpython/jit/backend/llsupport/test/test_stmrewrite.py --- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py +++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py @@ -250,7 +250,7 @@ cond_call_stm_b(p1, descr=P2Rdescr) i1 = getfield_gc(p1, descr=tydescr) i2 = int_add(i1, 1) -cond_call_stm_b(p1, descr=R2Wdescr) +cond_call_stm_b(p1, descr=P2Wdescr) setfield_gc(p1, i2, descr=tydescr) jump(p1) ) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1020,12 +1020,16 @@ def _reload_frame_if_necessary(self, mc, align_stack=False): gcrootmap = self.cpu.gc_ll_descr.gcrootmap -if gcrootmap: -if gcrootmap.is_shadow_stack: -rst = gcrootmap.get_root_stack_top_addr() -mc.MOV(ecx, heap(rst)) -mc.MOV(ebp, mem(ecx, -WORD)) -wbdescr = self.cpu.gc_ll_descr.write_barrier_descr +if gcrootmap and gcrootmap.is_shadow_stack: +rst = gcrootmap.get_root_stack_top_addr() +mc.MOV(ecx, heap(rst)) +mc.MOV(ebp, mem(ecx, -WORD)) + +if gcrootmap and gcrootmap.is_stm: +wbdescr = self.cpu.gc_ll_descr.P2Wdescr +else: +wbdescr = self.cpu.gc_ll_descr.write_barrier_descr + if gcrootmap and wbdescr: # frame never uses card marking, so we enforce this is not # an array ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: break less stuff
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65373:de492c4ceb35 Date: 2013-07-12 07:47 +0200 http://bitbucket.org/pypy/pypy/changeset/de492c4ceb35/ Log:break less stuff diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -271,7 +271,7 @@ return rffi.cast(lltype.Signed, rst_addr) class GcRootMap_stm(object): -is_shadow_stack = False # XXX: should it have an is_stmgc? +is_shadow_stack = True # XXX: should it have an is_stmgc? def __init__(self, gcdescr): pass @@ -289,9 +289,6 @@ self.llop1 = gc_ll_descr.llop1 self.returns_modified_object = False -self.FUNCPTR = lltype.Ptr(lltype.FuncType( -[llmemory.Address], lltype.Void)) - self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder self.HDRPTR = gc_ll_descr.HDRPTR @@ -305,6 +302,8 @@ def __init__(self, gc_ll_descr): BarrierDescr.__init__(self, gc_ll_descr) self.fielddescr_tid = gc_ll_descr.fielddescr_tid +self.FUNCPTR = lltype.Ptr(lltype.FuncType( +[llmemory.Address], lltype.Void)) GCClass = gc_ll_descr.GCClass self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG @@ -347,7 +346,7 @@ def get_barrier_funcptr(self, returns_modified_object): assert not returns_modified_object FUNCTYPE = self.FUNCPTR -return llop1.get_write_barrier_failing_case(FUNCTYPE) +return self.llop1.get_write_barrier_failing_case(FUNCTYPE) def get_write_barrier_fn(self, cpu, returns_modified_object): # must pass in 'self.returns_modified_object', to make sure that @@ -383,7 +382,7 @@ # get a pointer to the 'remember_young_pointer' function from # the GC, and call it immediately funcptr = self.get_barrier_funcptr(returns_modified_object) -res = funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) +funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) class STMBarrierDescr(BarrierDescr): @@ -391,13 +390,13 @@ BarrierDescr.__init__(self, gc_ll_descr) self.stmcat = stmcat self.returns_modified_object = True -self.WB_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType( +self.B_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType( [llmemory.Address], llmemory.Address)) -self.wb_failing_case_ptr = rffi.llexternal( +self.b_failing_case_ptr = rffi.llexternal( cfunc_name, -self.WB_FUNCPTR_MOD.TO.ARGS, -self.WB_FUNCPTR_MOD.TO.RESULT, +self.B_FUNCPTR_MOD.TO.ARGS, +self.B_FUNCPTR_MOD.TO.RESULT, sandboxsafe=True, _nowrapper=True) @@ -409,7 +408,7 @@ def get_barrier_funcptr(self, returns_modified_object): assert returns_modified_object -return self.wb_failing_case_ptr +return self.b_failing_case_ptr @specialize.arg(2) def _do_barrier(self, gcref_struct, returns_modified_object): ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: progress on stm barriers (without fastpath) and GC without malloc fastpaths (nursery)
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65375:21bde4788254 Date: 2013-07-12 16:47 +0200 http://bitbucket.org/pypy/pypy/changeset/21bde4788254/ Log:progress on stm barriers (without fastpath) and GC without malloc fastpaths (nursery) diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -81,27 +81,34 @@ self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn) self._build_failure_recovery(False, withfloats=False) self._build_failure_recovery(True, withfloats=False) -self._build_wb_slowpath(False) -self._build_wb_slowpath(True) -self._build_wb_slowpath(False, for_frame=True) +if gc_ll_descr.stm: +descrs = [gc_ll_descr.P2Rdescr, gc_ll_descr.P2Wdescr] +else: +descrs = [gc_ll_descr.write_barrier_descr] +for d in descrs: +self._build_b_slowpath(d, False) +self._build_b_slowpath(d, True) +self._build_b_slowpath(d, False, for_frame=True) # only one of those self.build_frame_realloc_slowpath() if self.cpu.supports_floats: self._build_failure_recovery(False, withfloats=True) self._build_failure_recovery(True, withfloats=True) -self._build_wb_slowpath(False, withfloats=True) -self._build_wb_slowpath(True, withfloats=True) +for d in descrs: +self._build_b_slowpath(d, False, withfloats=True) +self._build_b_slowpath(d, True, withfloats=True) self._build_propagate_exception_path() + if gc_ll_descr.get_malloc_slowpath_addr() is not None: # generate few slowpaths for various cases self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed') self.malloc_slowpath_varsize = self._build_malloc_slowpath( kind='var') -if hasattr(gc_ll_descr, 'malloc_str'): +if gc_ll_descr.get_malloc_slowpath_addr() is not None and hasattr(gc_ll_descr, 'malloc_str'): self.malloc_slowpath_str = self._build_malloc_slowpath(kind='str') else: self.malloc_slowpath_str = None -if hasattr(gc_ll_descr, 'malloc_unicode'): +if gc_ll_descr.get_malloc_slowpath_addr() is not None and hasattr(gc_ll_descr, 'malloc_unicode'): self.malloc_slowpath_unicode = self._build_malloc_slowpath( kind='unicode') else: diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -294,12 +294,42 @@ self.returns_modified_object = False self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder self.HDRPTR = gc_ll_descr.HDRPTR +self.b_slowpath = [0, 0, 0, 0] def repr_of_descr(self): raise NotImplementedError def __repr(self): raise NotImplementedError + +def get_b_slowpath(self, num): +return self.b_slowpath[num] + +def set_b_slowpath(self, num, addr): +self.b_slowpath[num] = addr + +def get_barrier_funcptr(self, returns_modified_object): +raise NotImplementedError + +def get_barrier_fn(self, cpu, returns_modified_object): +# must pass in 'self.returns_modified_object', to make sure that +# the callers are fixed for this case +funcptr = self.get_barrier_funcptr(returns_modified_object) +funcaddr = llmemory.cast_ptr_to_adr(funcptr) +return cpu.cast_adr_to_int(funcaddr) + +def get_barrier_from_array_fn(self, cpu): +# returns a function with arguments [array, index, newvalue] +llop1 = self.llop1 +funcptr = llop1.get_write_barrier_from_array_failing_case( +self.FUNCPTR) +funcaddr = llmemory.cast_ptr_to_adr(funcptr) +return cpu.cast_adr_to_int(funcaddr)# this may return 0 + +def has_barrier_from_array(self, cpu): +return self.get_barrier_from_array_fn(cpu) != 0 + + class WriteBarrierDescr(BarrierDescr): def __init__(self, gc_ll_descr): @@ -325,8 +355,6 @@ assert self.jit_wb_cards_set_singlebyte == -0x80 else: self.jit_wb_cards_set = 0 -# -self.wb_slowpath = [0, 0, 0, 0] def repr_of_descr(self): return 'wbdescr' @@ -351,30 +379,6 @@ FUNCTYPE = self.FUNCPTR return self.llop1.get_write_barrier_failing_case(FUNCTYPE) -def get_write_barrier_fn(self, cpu, returns_modified_object): -# must pass in 'self.returns_modified_object', to make sure that -# the callers are fixed for this case -funcptr = self.get_barrier_funcptr(returns_modified_object) -funcaddr = llmemory.cast_ptr_to_adr(funcptr) -
[pypy-commit] pypy stmgc-c4: satisfy some tests
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65401:d11b7c7058b0 Date: 2013-07-15 12:17 +0200 http://bitbucket.org/pypy/pypy/changeset/d11b7c7058b0/ Log:satisfy some tests diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py @@ -75,11 +75,18 @@ from rpython.translator.c import genc # t = TranslationContext() -t.config.translation.gc = gc +gcrootfinder = kwds['gcrootfinder'] +if gcrootfinder == 'stm': +t.config.translation.stm = True +t.config.translation.gc = 'stmgc' +else: +t.config.translation.gc = gc +# if gc != 'boehm': t.config.translation.gcremovetypeptr = True for name, value in kwds.items(): setattr(t.config.translation, name, value) + ann = t.buildannotator() ann.build_types(f, [s_list_of_strings], main_entry_point=True) t.buildrtyper().specialize() diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2188,7 +2188,7 @@ operations = [ ResOperation(rop.COND_CALL_GC_WB, [p0, ConstInt(0)], None, descr=WriteBarrierDescr()), -ResOperation(rop.FINISH, [p0], None, descr=BasicFailDescr(1)) +ResOperation(rop.FINISH, [p0], None, descr=BasicFinalDescr(0)) ] inputargs = [p0] looptoken = JitCellToken() @@ -4246,10 +4246,9 @@ class WBDescrForTests(AbstractDescr): returns_modified_object = False b_slowpath = (0, 0, 0, 0) -def get_b_slowpath(self, c1, c2): -return self.b_slowpath[c1+2*c2] -def set_b_slowpath(self, c1, c2, addr): -i = c1+2*c2 -self.b_slowpath = (self.b_slowpath[:i] + (addr,) + -self.b_slowpath[i+1:]) +def get_b_slowpath(self, c1): +return self.b_slowpath[c1] +def set_b_slowpath(self, c1, addr): +self.b_slowpath = (self.b_slowpath[:c1] + (addr,) + +self.b_slowpath[c1+1:]) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1032,19 +1032,22 @@ cb.emit_no_collect() def _reload_frame_if_necessary(self, mc, align_stack=False): -gcrootmap = self.cpu.gc_ll_descr.gcrootmap +gc_ll_descr = self.cpu.gc_ll_descr +gcrootmap = gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() mc.MOV(ecx, heap(rst)) mc.MOV(ebp, mem(ecx, -WORD)) if gcrootmap and gcrootmap.is_stm: -wbdescr = self.cpu.gc_ll_descr.P2Wdescr +if not hasattr(gc_ll_descr, 'P2Wdescr'): +raise Exception(unreachable code) +wbdescr = gc_ll_descr.P2Wdescr self._stm_barrier_fastpath(mc, wbdescr, [ebp], is_frame=True, align_stack=align_stack) return -wbdescr = self.cpu.gc_ll_descr.write_barrier_descr +wbdescr = gc_ll_descr.write_barrier_descr if gcrootmap and wbdescr: # frame never uses card marking, so we enforce this is not # an array diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -825,7 +825,7 @@ def consider_call_malloc_nursery_varsize_frame(self, op): gc_ll_descr = self.assembler.cpu.gc_ll_descr -assert gc_ll_descr.max_size_of_young_obj is not None +assert gc_ll_descr.get_malloc_slowpath_addr() is not None # ^^^ if this returns None, don't translate the rest of this function # size_box = op.getarg(0) @@ -850,10 +850,8 @@ def consider_call_malloc_nursery_varsize(self, op): gc_ll_descr = self.assembler.cpu.gc_ll_descr -assert gc_ll_descr.max_size_of_young_obj is not None -# ^^^ if this returns None, don't translate the rest of this function -# -if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): +if not hasattr(gc_ll_descr, 'max_size_of_young_obj') \ + or gc_ll_descr.max_size_of_young_obj is None: raise Exception(unreachable code) # for boehm, this function should never be called arraydescr = op.getdescr() diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/x86/test/test_zrpy_gc.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc.py @@ -1,5 +1,9
[pypy-commit] pypy stmgc-c4: forgot OP_STM_GET_ROOT_STACK_TOP in funcgen
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65400:7a372f0f9000 Date: 2013-07-15 08:35 +0200 http://bitbucket.org/pypy/pypy/changeset/7a372f0f9000/ Log:forgot OP_STM_GET_ROOT_STACK_TOP in funcgen diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -591,6 +591,7 @@ OP_STM_PTR_EQ = _OP_STM OP_STM_PUSH_ROOT= _OP_STM OP_STM_POP_ROOT_INTO= _OP_STM +OP_STM_GET_ROOT_STACK_TOP = _OP_STM OP_STM_ALLOCATE = _OP_STM OP_STM_GET_TID = _OP_STM OP_STM_HASH = _OP_STM ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy stmgc-c4: fix and add more tests
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65402:586771804a5c Date: 2013-07-15 16:16 +0200 http://bitbucket.org/pypy/pypy/changeset/586771804a5c/ Log:fix and add more tests diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -315,6 +315,9 @@ exc0, exc1 = None, None if descr is None: return + +if is_stm and withcards: +return if not withcards: func = descr.get_barrier_fn(self.cpu, diff --git a/rpython/memory/gctransform/test/test_framework.py b/rpython/memory/gctransform/test/test_framework.py --- a/rpython/memory/gctransform/test/test_framework.py +++ b/rpython/memory/gctransform/test/test_framework.py @@ -23,7 +23,7 @@ class transformerclass(ShadowStackFrameworkGCTransformer): root_stack_depth = 100 -def test_framework_simple(): +def test_framework_simple(gc=minimark): def g(x): return x + 1 class A(object): @@ -37,7 +37,10 @@ from rpython.translator.c.genc import CStandaloneBuilder t = rtype(entrypoint, [s_list_of_strings]) -t.config.translation.gc = minimark +if gc == stmgc: +t.config.translation.stm = True +t.config.translation.gc = gc + cbuild = CStandaloneBuilder(t, entrypoint, t.config, gcpolicy=FrameworkGcPolicy2) db = cbuild.generate_graphs_for_llinterp() @@ -54,6 +57,9 @@ assert res == 2 +def test_framework_simple_stm(): +test_framework_simple(stmgc) + def test_cancollect(): S = lltype.GcStruct('S', ('x', lltype.Signed)) def g(): @@ -94,7 +100,7 @@ gg = graphof(t, g) assert CollectAnalyzer(t).analyze_direct_call(gg) -def test_no_collect(): +def test_no_collect(gc=minimark): from rpython.rlib import rgc from rpython.translator.c.genc import CStandaloneBuilder @@ -109,12 +115,17 @@ return g() + 2 t = rtype(entrypoint, [s_list_of_strings]) -t.config.translation.gc = minimark +if gc == stmgc: +t.config.translation.stm = True +t.config.translation.gc = gc cbuild = CStandaloneBuilder(t, entrypoint, t.config, gcpolicy=FrameworkGcPolicy2) db = cbuild.generate_graphs_for_llinterp() -def test_no_collect_detection(): +def test_no_collect_stm(): +test_no_collect(stmgc) + +def test_no_collect_detection(gc=minimark): from rpython.rlib import rgc from rpython.translator.c.genc import CStandaloneBuilder @@ -133,13 +144,18 @@ return g() + 2 t = rtype(entrypoint, [s_list_of_strings]) -t.config.translation.gc = minimark +if gc == stmgc: +t.config.translation.stm = True +t.config.translation.gc = gc cbuild = CStandaloneBuilder(t, entrypoint, t.config, gcpolicy=FrameworkGcPolicy2) f = py.test.raises(Exception, cbuild.generate_graphs_for_llinterp) expected = 'no_collect' function can trigger collection: function g at assert str(f.value).startswith(expected) +def test_no_collect_detection_stm(): +test_no_collect_detection(stmgc) + class WriteBarrierTransformer(ShadowStackFrameworkGCTransformer): clean_sets = {} GC_PARAMS = {} diff --git a/rpython/rlib/rstack.py b/rpython/rlib/rstack.py --- a/rpython/rlib/rstack.py +++ b/rpython/rlib/rstack.py @@ -20,10 +20,10 @@ includes=['src/stack.h'], separate_module_files=[srcdir / 'stack.c', srcdir / 'threadlocal.c']) -def llexternal(name, args, res, _callable=None): +def llexternal(name, args, res, _callable=None, **kwds): return rffi.llexternal(name, args, res, compilation_info=compilation_info, sandboxsafe=True, _nowrapper=True, - _callable=_callable) + _callable=_callable, **kwds) _stack_get_end = llexternal('LL_stack_get_end', [], lltype.Signed, lambda: 0) @@ -34,7 +34,8 @@ lambda frac: None) _stack_too_big_slowpath = llexternal('LL_stack_too_big_slowpath', [lltype.Signed], lltype.Char, - lambda cur: '\x00') + lambda cur: '\x00', + transactionsafe=True) # the following is used by the JIT _stack_get_end_adr = llexternal('LL_stack_get_end_adr', [], lltype.Signed) _stack_get_length_adr= llexternal('LL_stack_get_length_adr',[], lltype.Signed) ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: fix one bug and use a big stub in case it is also needed as the h_original of an object
Author: Remi Meier remi.me...@gmail.com Branch: Changeset: r399:6d83a39b28cf Date: 2013-07-15 17:16 +0200 http://bitbucket.org/pypy/stmgc/changeset/6d83a39b28cf/ Log:fix one bug and use a big stub in case it is also needed as the h_original of an object diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -75,7 +75,7 @@ // helper functions int classify(gcptr p); void check(gcptr p); - +int in_nursery(gcptr obj); static int is_private(gcptr P) { return (P-h_revision == stm_private_rev_num) || @@ -226,8 +226,7 @@ if (p-h_original !(p-h_tid GCFLAG_PREBUILT_ORIGINAL)) { // must point to valid old object gcptr id = (gcptr)p-h_original; -assert(id-h_tid GCFLAG_OLD); -check_not_free(id); +assert(!in_nursery(id)); #ifdef _GC_DEBUG if (!is_shared_prebuilt(id) !(id-h_tid GCFLAG_PREBUILT)) assert(!is_free_old(id)); diff --git a/c4/extra.c b/c4/extra.c --- a/c4/extra.c +++ b/c4/extra.c @@ -107,10 +107,12 @@ else { /* must create shadow original object XXX: or use backup, if exists */ - -/* XXX use stmgcpage_malloc() directly, we don't need to copy - * the contents yet */ -gcptr O = stmgc_duplicate_old(p); +gcptr O = (gcptr)stmgcpage_malloc(stmgc_size(p)); +memcpy(O, p, stmgc_size(p)); /* at least major collections + depend on some content of id_copy. + remove after fixing that XXX */ +O-h_tid |= GCFLAG_OLD; + p-h_original = (revision_t)O; p-h_tid |= GCFLAG_HAS_ID; diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -39,7 +39,21 @@ goto done; not_found: -stub = stm_stub_malloc(sd-foreign_pd); +if (!obj-h_original !(obj-h_tid GCFLAG_OLD)) { +/* There shouldn't be a public, young object without + a h_original. But there can be priv/protected ones. + We have a young protected copy without an h_original + The stub we allocate will be the h_original, but + it must be big enough to be copied over by a major + collection later. */ +assert(!(obj-h_tid GCFLAG_PUBLIC)); + +stub = (gcptr)stmgcpage_malloc(stmgc_size(obj)); +STUB_THREAD(stub) = sd-foreign_pd; +} +else { +stub = stm_stub_malloc(sd-foreign_pd); +} stub-h_tid = (obj-h_tid STM_USER_TID_MASK) | GCFLAG_PUBLIC | GCFLAG_STUB | GCFLAG_OLD; @@ -51,10 +65,9 @@ stub-h_original = (revision_t)obj; } else { -/* There shouldn't be a public, young object without - a h_original. But there can be protected ones. */ -assert(!(obj-h_tid GCFLAG_PUBLIC)); -obj-h_original = (revision_t)stub; +/* this is the big-stub case described above */ +obj-h_original = (revision_t)stub; +stub-h_original = 0; /* stub_malloc does not set to 0... */ if (obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED) { ((gcptr)obj-h_revision)-h_original = (revision_t)stub; } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original2: new approach doing the work of copying over h_original in visit()
Author: Remi Meier remi.me...@gmail.com Branch: copy-over-original2 Changeset: r401:7c2e94ae8bf1 Date: 2013-07-16 13:33 +0200 http://bitbucket.org/pypy/stmgc/changeset/7c2e94ae8bf1/ Log:new approach doing the work of copying over h_original in visit() diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -945,6 +945,7 @@ revision_t my_lock = d-my_lock; wlog_t *item; + dprintf((acquire_locks\n)); assert(!stm_has_got_any_lock(d)); assert(d-public_descriptor-stolen_objects.size == 0); @@ -957,6 +958,7 @@ revision_t v; retry: assert(R-h_tid GCFLAG_PUBLIC); + assert(R-h_tid GCFLAG_PUBLIC_TO_PRIVATE); v = ACCESS_ONCE(R-h_revision); if (IS_POINTER(v)) /* has a more recent revision */ { @@ -989,7 +991,7 @@ static void CancelLocks(struct tx_descriptor *d) { wlog_t *item; - + dprintf((cancel_locks\n)); if (!g2l_any_entry(d-public_to_private)) return; @@ -1257,7 +1259,7 @@ revision_t cur_time; struct tx_descriptor *d = thread_descriptor; assert(d-active = 1); - + dprintf((CommitTransaction(%p)\n, d)); spinlock_acquire(d-public_descriptor-collection_lock, 'C'); /*committing*/ if (d-public_descriptor-stolen_objects.size != 0) stm_normalize_stolen_objects(d); @@ -1341,6 +1343,7 @@ d-active = 2; d-reads_size_limit_nonatomic = 0; update_reads_size_limit(d); + dprintf((make_inevitable(%p)\n, d)); } static revision_t acquire_inev_mutex_and_mark_global_cur_time( diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -223,6 +223,7 @@ id_copy-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ id_copy-h_tid |= GCFLAG_VISITED; +assert(id_copy-h_tid GCFLAG_OLD); /* XXX: may not always need tracing? */ if (!(id_copy-h_tid GCFLAG_STUB)) @@ -236,6 +237,55 @@ } } +static gcptr copy_over_original(gcptr obj) +{ +assert(!(obj-h_tid GCFLAG_VISITED)); +assert(!(obj-h_tid GCFLAG_STUB)); + +if (obj-h_tid GCFLAG_PUBLIC /* XXX: required? */ + !(obj-h_tid GCFLAG_PREBUILT_ORIGINAL) + obj-h_original) { + +gcptr id_copy = (gcptr)obj-h_original; +assert(!(id_copy-h_revision 1)); /* not head-revision itself */ +if (!(id_copy-h_tid GCFLAG_PUBLIC)) +assert(0); +/* return NULL; *//* could be priv_from_protected with + where backup is stolen and its h-original + points to it. */ + +assert(stmgc_size(id_copy) == stmgc_size(obj)); +/* prehash may be specific hash value for prebuilts, or 0 */ +revision_t prehash = id_copy-h_original; +assert(IMPLIES(prehash, id_copy-h_tid GCFLAG_PREBUILT_ORIGINAL)); +/* old_tid may have prebuilt_original flags that should not be lost */ +revision_t old_tid = id_copy-h_tid; + +memcpy(id_copy, obj, stmgc_size(obj)); +assert(!((id_copy-h_tid ^ old_tid) + (GCFLAG_BACKUP_COPY //| GCFLAG_STUB, id_copy may be stub +| GCFLAG_PUBLIC | GCFLAG_HAS_ID +| GCFLAG_PRIVATE_FROM_PROTECTED))); +id_copy-h_original = prehash; +id_copy-h_tid = old_tid ~GCFLAG_VISITED; /* will be visited next */ + +dprintf((copy %p over %p\n, obj, id_copy)); + +/* for those visiting later: */ +obj-h_revision = (revision_t)id_copy; + +/* mark as not old for transactions to fix their + public_to_private. Otherwise, inevitable transactions + would think their public obj was modified (also for + other transactions, but they can abort) */ +obj-h_tid = ~GCFLAG_OLD; + +return id_copy; +} + +return NULL; +} + static void visit(gcptr *pobj) { gcptr obj = *pobj; @@ -248,7 +298,26 @@ assert(!(obj-h_tid GCFLAG_STUB)); if (!(obj-h_tid GCFLAG_VISITED)) { obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ + +gcptr next = copy_over_original(obj); +if (next) { +revision_t loc = (revision_t)pobj - offsetof(struct stm_object_s, + h_revision); +if ((gcptr)loc != next) +/* we don't want to set h_revision of 'next' to + 'next' itself, it was already set by + copy_over_original to a global head revision */ +*pobj = next; +obj = next; + +assert(obj-h_revision 1); +assert(!(obj-h_tid GCFLAG_VISITED)); +goto restart; +} + obj-h_tid |= GCFLAG_VISITED; +assert(obj-h_tid GCFLAG_OLD); + gcptrlist_insert(objects_to_trace, obj); keep_original_alive(obj); @@
[pypy-commit] stmgc copy-over-original2: uncomment jumping forward in visit() again
Author: Remi Meier remi.me...@gmail.com Branch: copy-over-original2 Changeset: r403:7c66774a3b43 Date: 2013-07-16 14:40 +0200 http://bitbucket.org/pypy/stmgc/changeset/7c66774a3b43/ Log:uncomment jumping forward in visit() again diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -354,14 +354,14 @@ } } -/* if (!(obj-h_revision 3)) { */ -/* /\* obj is neither a stub nor a most recent revision: */ -/*completely ignore obj-h_revision *\/ */ +if (!(obj-h_revision 3)) { +/* obj is neither a stub nor a most recent revision: + completely ignore obj-h_revision */ -/* obj = (gcptr)obj-h_revision; */ -/* assert(obj-h_tid GCFLAG_PUBLIC); */ -/* prev_obj-h_revision = (revision_t)obj; */ -/* } */ +obj = (gcptr)obj-h_revision; +assert(obj-h_tid GCFLAG_PUBLIC); +prev_obj-h_revision = (revision_t)obj; +} *pobj = obj; goto restart; } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original2: update comment
Author: Remi Meier remi.me...@gmail.com Branch: copy-over-original2 Changeset: r402:a127a39f6967 Date: 2013-07-16 14:29 +0200 http://bitbucket.org/pypy/stmgc/changeset/a127a39f6967/ Log:update comment diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -637,6 +637,7 @@ assert(!(obj-h_tid GCFLAG_STUB)); if (!(obj-h_tid GCFLAG_OLD)) { +assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); obj = (gcptr)obj-h_revision; items[i] = obj; } @@ -650,9 +651,7 @@ assert(IS_POINTER(obj-h_revision)); obj = (gcptr)obj-h_revision; -/* backup copies will never be candidates for copy over - prebuilts, because there is always the priv-from-prot - object inbetween */ +/* the backup-ptr should already be updated: */ assert(obj-h_tid GCFLAG_OLD); } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original2: use NURSERY_MOVED instead of ~OLD when copying an object over its original during major collections
Author: Remi Meier remi.me...@gmail.com Branch: copy-over-original2 Changeset: r404:74ae9fa5621f Date: 2013-07-16 14:57 +0200 http://bitbucket.org/pypy/stmgc/changeset/74ae9fa5621f/ Log:use NURSERY_MOVED instead of ~OLD when copying an object over its original during major collections diff --git a/c4/gcpage.c b/c4/gcpage.c --- a/c4/gcpage.c +++ b/c4/gcpage.c @@ -223,7 +223,7 @@ id_copy-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ id_copy-h_tid |= GCFLAG_VISITED; -assert(id_copy-h_tid GCFLAG_OLD); +assert(!(id_copy-h_tid GCFLAG_NURSERY_MOVED)); /* XXX: may not always need tracing? */ if (!(id_copy-h_tid GCFLAG_STUB)) @@ -274,11 +274,11 @@ /* for those visiting later: */ obj-h_revision = (revision_t)id_copy; -/* mark as not old for transactions to fix their +/* mark as MOVED for transactions to fix their public_to_private. Otherwise, inevitable transactions would think their public obj was modified (also for other transactions, but they can abort) */ -obj-h_tid = ~GCFLAG_OLD; +obj-h_tid |= GCFLAG_NURSERY_MOVED; return id_copy; } @@ -316,7 +316,7 @@ } obj-h_tid |= GCFLAG_VISITED; -assert(obj-h_tid GCFLAG_OLD); +assert(!(obj-h_tid GCFLAG_NURSERY_MOVED)); gcptrlist_insert(objects_to_trace, obj); @@ -341,7 +341,7 @@ obj = (gcptr)(obj-h_revision - 2); if (!(obj-h_tid GCFLAG_PUBLIC)) { prev_obj-h_tid |= GCFLAG_VISITED; -assert(prev_obj-h_tid GCFLAG_OLD); +assert(!(prev_obj-h_tid GCFLAG_NURSERY_MOVED)); keep_original_alive(prev_obj); @@ -385,10 +385,10 @@ } obj-h_tid |= GCFLAG_VISITED; -assert(obj-h_tid GCFLAG_OLD); +assert(!(obj-h_tid GCFLAG_NURSERY_MOVED)); assert(!(obj-h_tid GCFLAG_STUB)); -if (B-h_tid GCFLAG_OLD) { +if (!(B-h_tid GCFLAG_NURSERY_MOVED)) { B-h_tid |= GCFLAG_VISITED; assert(!(B-h_tid GCFLAG_STUB)); gcptrlist_insert2(objects_to_trace, obj, B); @@ -418,7 +418,7 @@ if (!(obj-h_tid GCFLAG_VISITED)) { obj-h_tid = ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */ obj-h_tid |= GCFLAG_VISITED; -assert(obj-h_tid GCFLAG_OLD); +assert(!(obj-h_tid GCFLAG_NURSERY_MOVED)); gcptrlist_insert(objects_to_trace, obj); if (IS_POINTER(obj-h_revision)) { @@ -516,7 +516,7 @@ G2L_LOOP_FORWARD(d-public_to_private, item) { gcptr R = item-addr; gcptr L = item-val; -if (!(R-h_tid GCFLAG_OLD)) { +if (R-h_tid GCFLAG_NURSERY_MOVED) { /* R was copied over its original */ gcptr new_R = (gcptr)R-h_original; /* gcptrlist_insert(objects_to_trace, new_R); */ @@ -600,7 +600,7 @@ gcptr obj = items[i]; assert(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED); /* we don't copy private / protected objects over prebuilts (yet) */ -assert(obj-h_tid GCFLAG_OLD); +assert(!(obj-h_tid GCFLAG_NURSERY_MOVED)); if (!(obj-h_tid GCFLAG_VISITED)) { /* forget 'obj' */ @@ -615,7 +615,7 @@ items = d-old_objects_to_trace.items; for (i = d-old_objects_to_trace.size - 1; i = 0; i--) { gcptr obj = items[i]; -assert(obj-h_tid GCFLAG_OLD); +assert(!(obj-h_tid GCFLAG_NURSERY_MOVED)); assert(obj-h_tid GCFLAG_VISITED); } #endif @@ -636,7 +636,7 @@ gcptr obj = items[i]; assert(!(obj-h_tid GCFLAG_STUB)); -if (!(obj-h_tid GCFLAG_OLD)) { +if (obj-h_tid GCFLAG_NURSERY_MOVED) { assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); obj = (gcptr)obj-h_revision; items[i] = obj; @@ -652,7 +652,7 @@ obj = (gcptr)obj-h_revision; /* the backup-ptr should already be updated: */ -assert(obj-h_tid GCFLAG_OLD); +assert(!(obj-h_tid GCFLAG_NURSERY_MOVED)); } revision_t v = obj-h_revision; @@ -695,7 +695,7 @@ G2L_LOOP_FORWARD(d-public_to_private, item) { assert(item-addr-h_tid GCFLAG_VISITED); assert(item-val-h_tid GCFLAG_VISITED); -assert(item-addr-h_tid GCFLAG_OLD); +assert(!(item-addr-h_tid GCFLAG_NURSERY_MOVED)); assert(item-addr-h_tid GCFLAG_PUBLIC); /* assert(is_private(item-val)); but in the other thread, which becomes: */ ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc copy-over-original2: rename GCFLAG_NURSERY_MOVED to GCFLAG_MOVED
Author: Remi Meier remi.me...@gmail.com Branch: copy-over-original2 Changeset: r405:9a584030a9e6 Date: 2013-07-16 15:08 +0200 http://bitbucket.org/pypy/stmgc/changeset/9a584030a9e6/ Log:rename GCFLAG_NURSERY_MOVED to GCFLAG_MOVED diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -302,7 +302,7 @@ } else { if (in_nursery(p)) { -assert(p-h_tid GCFLAG_NURSERY_MOVED); +assert(p-h_tid GCFLAG_MOVED); assert(!(p-h_revision 1)); } return C_PUBLIC; diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -122,7 +122,7 @@ gcptr P_prev = P; P = (gcptr)v; assert((P-h_tid GCFLAG_PUBLIC) || - (P_prev-h_tid GCFLAG_NURSERY_MOVED)); + (P_prev-h_tid GCFLAG_MOVED)); v = ACCESS_ONCE(P-h_revision); @@ -214,7 +214,7 @@ add_in_recent_reads_cache: /* The risks are that the following assert fails, because the flag was added just now by a parallel thread during stealing... */ - /*assert(!(P-h_tid GCFLAG_NURSERY_MOVED));*/ + /*assert(!(P-h_tid GCFLAG_MOVED));*/ fxcache_add(d-recent_reads_cache, P); return P; @@ -257,7 +257,7 @@ */ if (P-h_tid GCFLAG_PUBLIC) { - if (P-h_tid GCFLAG_NURSERY_MOVED) + if (P-h_tid GCFLAG_MOVED) { P = (gcptr)P-h_revision; assert(P-h_tid GCFLAG_PUBLIC); @@ -389,7 +389,7 @@ while (v = P-h_revision, IS_POINTER(v)) { - if (P-h_tid GCFLAG_NURSERY_MOVED) + if (P-h_tid GCFLAG_MOVED) dprintf((nursery_moved )); if (v 2) @@ -486,7 +486,7 @@ static gcptr LocalizePublic(struct tx_descriptor *d, gcptr R) { assert(R-h_tid GCFLAG_PUBLIC); - assert(!(R-h_tid GCFLAG_NURSERY_MOVED)); + assert(!(R-h_tid GCFLAG_MOVED)); #ifdef _GC_DEBUG wlog_t *entry; @@ -581,7 +581,7 @@ Add R into the list 'public_with_young_copy', unless W is actually an old object, in which case we need to record W. */ - if (R-h_tid GCFLAG_NURSERY_MOVED) + if (R-h_tid GCFLAG_MOVED) { /* Bah, the object turned into this kind of stub, possibly while we were waiting for the collection_lock, because it @@ -671,8 +671,8 @@ continue; } } - else if ((R-h_tid (GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED)) -== (GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED)) + else if ((R-h_tid (GCFLAG_PUBLIC | GCFLAG_MOVED)) +== (GCFLAG_PUBLIC | GCFLAG_MOVED)) { /* such an object is identical to the one it points to (stolen protected young object with h_revision pointing @@ -1084,7 +1084,7 @@ assert(!(L-h_tid GCFLAG_VISITED)); assert(!(L-h_tid GCFLAG_PUBLIC_TO_PRIVATE)); assert(!(L-h_tid GCFLAG_PREBUILT_ORIGINAL)); - assert(!(L-h_tid GCFLAG_NURSERY_MOVED)); + assert(!(L-h_tid GCFLAG_MOVED)); assert(L-h_revision != localrev); /* modified by AcquireLocks() */ #ifdef DUMP_EXTRA @@ -1131,7 +1131,7 @@ assert(R-h_tid GCFLAG_PUBLIC); assert(R-h_tid GCFLAG_PUBLIC_TO_PRIVATE); - assert(!(R-h_tid GCFLAG_NURSERY_MOVED)); + assert(!(R-h_tid GCFLAG_MOVED)); assert(R-h_revision != localrev); #ifdef DUMP_EXTRA @@ -1226,7 +1226,7 @@ assert(!(B-h_tid GCFLAG_BACKUP_COPY)); P-h_tid |= GCFLAG_PUBLIC; assert(!(P-h_tid GCFLAG_HAS_ID)); - if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_NURSERY_MOVED; + if (!(P-h_tid GCFLAG_OLD)) P-h_tid |= GCFLAG_MOVED; /* P becomes a public outdated object. It may create an exception documented in doc-objects.txt: a public but young object. It's still fine because it should only be seen by diff --git a/c4/et.h b/c4/et.h --- a/c4/et.h +++ b/c4/et.h @@ -46,7 +46,7 @@ * the list 'old_objects_to_trace'; it is set again at the next minor * collection. * - * GCFLAG_NURSERY_MOVED is used temporarily during minor collections. + * GCFLAG_MOVED is used temporarily during minor/major collections. * * GCFLAG_STUB is set for debugging on stub objects made by stealing or * by major collections. 'p_stub-h_revision' might be a value @@ -67,7 +67,7 @@ static const revision_t GCFLAG_PREBUILT_ORIGINAL = STM_FIRST_GCFLAG 3; static const revision_t GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG 4; // in stmgc.h: GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG 5; -static const revision_t GCFLAG_NURSERY_MOVED = STM_FIRST_GCFLAG 6; +static const revision_t GCFLAG_MOVED = STM_FIRST_GCFLAG 6; static const revision_t GCFLAG_BACKUP_COPY /*debug*/ = STM_FIRST_GCFLAG 7; static const revision_t GCFLAG_STUB /*debug*/ =
[pypy-commit] pypy stmgc-c4: fighting layers to make it work
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65424:8a3c2efecdca Date: 2013-07-17 11:22 +0200 http://bitbucket.org/pypy/pypy/changeset/8a3c2efecdca/ Log:fighting layers to make it work diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -628,7 +628,7 @@ descr = op.getdescr() fail_descr = cast_instance_to_gcref(descr) # we know it does not move, but well -rgc._make_sure_does_not_move(fail_descr) +fail_descr = rgc._make_sure_does_not_move(fail_descr) fail_descr = rffi.cast(lltype.Signed, fail_descr) if op.numargs() == 1: loc = self.make_sure_var_in_reg(op.getarg(0)) diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -222,7 +222,7 @@ raise AssertionError(kind) gcref = cast_instance_to_gcref(value) -rgc._make_sure_does_not_move(gcref) +gcref = rgc._make_sure_does_not_move(gcref) value = rffi.cast(lltype.Signed, gcref) je_location = self._call_assembler_check_descr(value, tmploc) # diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -107,9 +107,12 @@ gcrefs_output_list.append(new_p) if op.is_guard() or op.getopnum() == rop.FINISH: -llref = cast_instance_to_gcref(op.getdescr()) +# the only ops with descrs that get recorded in a trace +from rpython.jit.metainterp.history import AbstractDescr +descr = op.getdescr() +llref = cast_instance_to_gcref(descr) new_llref = rgc._make_sure_does_not_move(llref) -new_d = rgc.try_cast_gcref_to_instance(llref.__class__, new_llref) +new_d = rgc.try_cast_gcref_to_instance(AbstractDescr, new_llref) op.setdescr(new_d) gcrefs_output_list.append(new_llref) @@ -298,7 +301,7 @@ self.returns_modified_object = False self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder self.HDRPTR = gc_ll_descr.HDRPTR -self.b_slowpath = [0, 0, 0, 0] +self.b_slowpath = [0, 0, 0, 0, 0] def repr_of_descr(self): raise NotImplementedError diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -368,7 +368,7 @@ descr = op.getdescr() fail_descr = cast_instance_to_gcref(descr) # we know it does not move, but well -rgc._make_sure_does_not_move(fail_descr) +fail_descr = rgc._make_sure_does_not_move(fail_descr) fail_descr = rffi.cast(lltype.Signed, fail_descr) if op.numargs() == 1: loc = self.make_sure_var_in_reg(op.getarg(0)) diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -65,21 +65,25 @@ return llop.stm_get_tid(llgroup.HALFWORD, obj) def get_hdr_tid(self, addr): -return llmemory.cast_adr_to_int(addr + self.H_TID) +return llmemory.cast_adr_to_ptr(addr + self.H_TID, rffi.SIGNEDP) def get_hdr_revision(self, addr): -return llmemory.cast_adr_to_int(addr + self.H_REVISION) - +return llmemory.cast_adr_to_ptr(addr + self.H_REVISION, rffi.SIGNEDP) + def get_hdr_original(self, addr): -return llmemory.cast_adr_to_int(addr + self.H_ORIGINAL) +return llmemory.cast_adr_to_ptr(addr + self.H_ORIGINAL, rffi.SIGNEDP) -def get_original_object(self, obj): -if bool(self.get_hdr_tid(obj) GCFLAG_PREBUILT_ORIGINAL): +def get_original_copy(self, obj): +addr = llmemory.cast_ptr_to_adr(obj) +if bool(self.get_hdr_tid(addr)[0] GCFLAG_PREBUILT_ORIGINAL): return obj -orig = self.get_hdr_original(obj) +# +orig = self.get_hdr_original(addr)[0] if orig == 0: return obj -return llmemory.cast_int_to_adr(orig) +# +return llmemory.cast_adr_to_ptr(llmemory.cast_int_to_adr(orig), + llmemory.GCREF) def init_gc_object_immortal(self, addr, typeid16, flags=0): assert flags == 0 @@ -117,7 +121,7 @@ def can_move(self, obj): Means the reference will stay valid, except if not seen by the GC, then it can get collected. -tid = self.get_hdr_tid(obj) +tid = self.get_hdr_tid(obj)[0] if bool(tid GCFLAG_OLD): return False return True diff --git
[pypy-commit] pypy stmgc-c4: prepare for fastpath for ptr_eq and fix slowpath of stm-barriers
Author: Remi Meier remi.me...@gmail.com Branch: stmgc-c4 Changeset: r65454:ef39cd09001d Date: 2013-07-18 08:30 +0200 http://bitbucket.org/pypy/pypy/changeset/ef39cd09001d/ Log:prepare for fastpath for ptr_eq and fix slowpath of stm-barriers diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -89,6 +89,11 @@ self._build_b_slowpath(d, False) self._build_b_slowpath(d, True) self._build_b_slowpath(d, False, for_frame=True) +# only for stm: +if hasattr(gc_ll_descr, 'stm_ptr_eq_FUNCPTR'): +self._build_ptr_eq_slowpath() +else: +self.ptr_eq_slowpath = None # only one of those self.build_frame_realloc_slowpath() if self.cpu.supports_floats: diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -110,6 +110,8 @@ # the only ops with descrs that get recorded in a trace from rpython.jit.metainterp.history import AbstractDescr descr = op.getdescr() +if not we_are_translated() and descr is None: +return llref = cast_instance_to_gcref(descr) new_llref = rgc._make_sure_does_not_move(llref) new_d = rgc.try_cast_gcref_to_instance(AbstractDescr, new_llref) diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py --- a/rpython/jit/backend/llsupport/stmrewrite.py +++ b/rpython/jit/backend/llsupport/stmrewrite.py @@ -173,12 +173,4 @@ return isinstance(box, ConstPtr) and not box.value def handle_ptr_eq(self, op): -if self._is_null(op.getarg(0)) or self._is_null(op.getarg(1)): -self.newops.append(op) -return -args = op.getarglist() -result = op.result -if op.getopnum() in (rop.PTR_EQ, rop.INSTANCE_PTR_EQ): -self._do_stm_call('stm_ptr_eq', args, result) -else: -self._do_stm_call('stm_ptr_ne', args, result) +self.newops.append(op) diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py b/rpython/jit/backend/llsupport/test/test_stmrewrite.py --- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py +++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py @@ -517,7 +517,7 @@ jump(i1) , [p1, p2] -i1 = call(ConstClass(stm_ptr_eq), p1, p2, descr=stm_ptr_eq_descr) +i1 = ptr_eq(p1, p2) jump(i1) ) @@ -528,7 +528,7 @@ jump(i1) , [p1, p2] -i1 = call(ConstClass(stm_ptr_eq), p1, p2, descr=stm_ptr_eq_descr) +i1 = instance_ptr_eq(p1, p2) jump(i1) ) @@ -539,7 +539,7 @@ jump(i1) , [p1, p2] -i1 = call(ConstClass(stm_ptr_ne), p1, p2, descr=stm_ptr_ne_descr) +i1 = ptr_ne(p1, p2) jump(i1) ) @@ -550,7 +550,7 @@ jump(i1) , [p1, p2] -i1 = call(ConstClass(stm_ptr_ne), p1, p2, descr=stm_ptr_ne_descr) +i1 = instance_ptr_ne(p1, p2) jump(i1) ) diff --git a/rpython/jit/backend/x86/arch.py b/rpython/jit/backend/x86/arch.py --- a/rpython/jit/backend/x86/arch.py +++ b/rpython/jit/backend/x86/arch.py @@ -21,6 +21,7 @@ #| scratch | #| space | #++== aligned to 16 bytes +# STACK TOP # All the rest of the data is in a GC-managed variable-size frame. # This frame object's address is always stored in the register EBP/RBP. diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -309,6 +309,61 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.stack_check_slowpath = rawstart + +def _build_ptr_eq_slowpath(self): +cpu = self.cpu +is_stm = cpu.gc_ll_descr.stm +assert is_stm + +func = cpu.gc_ll_descr.get_malloc_fn_addr('stm_ptr_eq') +# +# This builds a helper function called from the slow path of +# ptr_eq/ne. It must save all registers, and optionally +# all XMM registers. It takes a single argument just pushed +# on the stack even on X86_64. It must restore stack alignment +# accordingly. +mc = codebuf.MachineCodeBlockWrapper() +# +self._push_all_regs_to_frame(mc, [], withfloats=False, + callee_only=True) +# +if IS_X86_32: +# ||val2|val1|retaddr| growing-, || aligned +
[pypy-commit] stmgc weakref: try to add weakrefs to demo_random.c
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r408:e203655b8773 Date: 2013-07-18 10:18 +0200 http://bitbucket.org/pypy/stmgc/changeset/e203655b8773/ Log:try to add weakrefs to demo_random.c diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -25,27 +25,46 @@ // SUPPORT #define GCTID_STRUCT_NODE 123 +#define GCTID_WEAKREF 122 + +struct node; +typedef struct node * nodeptr; +struct weak_node { +struct stm_object_s hdr; +nodeptr node; +}; +typedef struct weak_node * weaknodeptr; +#define WEAKNODE_SIZE sizeof(struct weak_node) struct node { struct stm_object_s hdr; long value; revision_t id; revision_t hash; -struct node *next; +nodeptr next; +weaknodeptr weakref; }; -typedef struct node * nodeptr; + + size_t stmcb_size(gcptr ob) { -assert(stm_get_tid(ob) == GCTID_STRUCT_NODE); -return sizeof(struct node); +if (stm_get_tid(ob) == GCTID_STRUCT_NODE) +return sizeof(struct node); +else if (stm_get_tid(ob) == GCTID_WEAKREF) +return WEAKNODE_SIZE; +assert(0); } + void stmcb_trace(gcptr ob, void visit(gcptr *)) { nodeptr n; +if (stm_get_tid(ob) == GCTID_WEAKREF) +return; assert(stm_get_tid(ob) == GCTID_STRUCT_NODE); n = (nodeptr)ob; visit((gcptr *)n-next); +visit((gcptr *)n-weakref); } @@ -105,6 +124,21 @@ return (int)(rand_r(td.thread_seed) % (unsigned int)max); } +gcptr get_random_root() +{ +int num = get_rand(td.num_roots + 1); +if (num == 0) +return stm_thread_local_obj; +else +return td.roots[num - 1]; +} + +gcptr get_random_shared_root() +{ +int num = get_rand(SHARED_ROOTS); +return shared_roots[num]; +} + void copy_roots(gcptr *from, gcptr *to, int num) { int i; @@ -192,6 +226,27 @@ return r; } + +weaknodeptr allocate_weaknodeptr(nodeptr to) +{ +weaknodeptr w; +push_roots(1); +w = (weaknodeptr)stm_weakref_allocate(WEAKNODE_SIZE, GCTID_WEAKREF, + (gcptr)to); +pop_roots(1); +return w; +} + +void set_weakref(nodeptr n, nodeptr to) +{ +stm_push_root((gcptr)n); +weaknodeptr w = allocate_weaknodeptr(to); +n = (nodeptr)stm_pop_root(); +n = (nodeptr)stm_write_barrier((gcptr)n); +n-weakref = w; +dprintf((set_weakref %p - %p - %p\n, n, w, to)); +} + int is_shared_prebuilt(gcptr p) { int i; @@ -448,6 +503,46 @@ return p; } +gcptr weakref_events(gcptr p, gcptr _r, gcptr _sr) +{ +nodeptr t; +weaknodeptr w; +gcptr ptrs[] = {_r, _sr}; + +int i = get_rand(2); +int k = get_rand(3); +switch (k) { +case 0: // check weakref +t = (nodeptr)read_barrier(ptrs[i]); +w = t-weakref; +if(w) { +if (w-node) { +assert(stm_get_tid((gcptr)w) == GCTID_WEAKREF); +check((gcptr)w-node); +return (gcptr)w-node; +} +else { +t-weakref = NULL; +} +} +p = NULL; +break; +case 1: // set weakref to something +if (p) +set_weakref((nodeptr)_r, (nodeptr)p); +else +set_weakref((nodeptr)_r, (nodeptr)get_random_root()); +p = NULL; +break; +case 2: // set weakref on shared roots +set_weakref((nodeptr)_sr, (nodeptr)get_random_shared_root()); +p = NULL; +break; +} +return p; +} + + gcptr shared_roots_events(gcptr p, gcptr _r, gcptr _sr) { nodeptr w_sr; @@ -462,7 +557,7 @@ break; case 2: w_sr = (nodeptr)write_barrier(_sr); -w_sr-next = (nodeptr)shared_roots[get_rand(SHARED_ROOTS)]; +w_sr-next = (nodeptr)get_random_shared_root(); break; } return p; @@ -527,18 +622,12 @@ gcptr do_step(gcptr p) { gcptr _r, _sr; -int num, k; +int k; -num = get_rand(td.num_roots+1); -if (num == 0) -_r = stm_thread_local_obj; -else -_r = td.roots[num - 1]; - -num = get_rand(SHARED_ROOTS); -_sr = shared_roots[num]; +_r = get_random_root(); +_sr = get_random_shared_root(); -k = get_rand(9); +k = get_rand(11); check(p); assert(thread_descriptor-active); @@ -550,6 +639,8 @@ p = id_hash_events(p, _r, _sr); else if (k 8) p = rare_events(p, _r, _sr); +else if (k 10) +p = weakref_events(p, _r, _sr); else if (get_rand(20) == 1) { // transaction break fprintf(stdout, |); diff --git a/c4/weakref.c b/c4/weakref.c --- a/c4/weakref.c +++ b/c4/weakref.c @@ -5,11 +5,14 @@ gcptr stm_weakref_allocate(size_t size, unsigned long tid, gcptr obj) { +stm_push_root(obj); gcptr weakref = stm_allocate(size, tid); +obj = stm_pop_root(); assert(!(weakref-h_tid GCFLAG_OLD)); /* 'size' too big? */ assert(stmgc_size(weakref)
[pypy-commit] stmgc weakref: implementing immutables and trying to fix the stealing of weakrefs
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r409:1cf2347f286d Date: 2013-07-18 14:45 +0200 http://bitbucket.org/pypy/stmgc/changeset/1cf2347f286d/ Log:implementing immutables and trying to fix the stealing of weakrefs diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -516,8 +516,8 @@ t = (nodeptr)read_barrier(ptrs[i]); w = t-weakref; if(w) { +assert(stm_get_tid((gcptr)w) == GCTID_WEAKREF); if (w-node) { -assert(stm_get_tid((gcptr)w) == GCTID_WEAKREF); check((gcptr)w-node); return (gcptr)w-node; } diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -545,6 +545,7 @@ gcptr stm_WriteBarrier(gcptr P) { + assert(!(P-h_tid GCFLAG_IMMUTABLE)); if (is_private(P)) { /* If we have GCFLAG_WRITE_BARRIER in P, then list it into diff --git a/c4/et.h b/c4/et.h --- a/c4/et.h +++ b/c4/et.h @@ -72,6 +72,8 @@ static const revision_t GCFLAG_STUB /*debug*/ = STM_FIRST_GCFLAG 8; static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG 9; static const revision_t GCFLAG_HAS_ID = STM_FIRST_GCFLAG 10; +static const revision_t GCFLAG_IMMUTABLE = STM_FIRST_GCFLAG 11; + /* this value must be reflected in PREBUILT_FLAGS in stmgc.h */ #define GCFLAG_PREBUILT (GCFLAG_VISITED | \ @@ -89,6 +91,8 @@ BACKUP_COPY, \ STUB, \ PRIVATE_FROM_PROTECTED, \ + HAS_ID, \ + IMMUTABLE, \ NULL } #define IS_POINTER(v)(!((v) 1)) /* even-valued number */ diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -101,6 +101,13 @@ return P; } +gcptr stm_allocate_immutable(size_t size, unsigned long tid) +{ +gcptr P = stm_allocate(size, tid); +P-h_tid |= GCFLAG_IMMUTABLE; +return P; +} + gcptr stmgc_duplicate(gcptr P) { size_t size = stmgc_size(P); diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -21,9 +21,47 @@ { gcptr stub, obj = *pobj; if (obj == NULL || (obj-h_tid (GCFLAG_PUBLIC | GCFLAG_OLD)) == -(GCFLAG_PUBLIC | GCFLAG_OLD)) + (GCFLAG_PUBLIC | GCFLAG_OLD)) return; +if (obj-h_tid GCFLAG_IMMUTABLE) { +assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); +/* old or young protected! mark as PUBLIC */ +if (!(obj-h_tid GCFLAG_PUBLIC)) { +if (!(obj-h_tid GCFLAG_OLD)) { +gcptr O; + +if (obj-h_tid GCFLAG_HAS_ID) { +/* use id-copy for us */ +O = (gcptr)obj-h_original; +obj-h_tid = ~GCFLAG_HAS_ID; +stm_copy_to_old_id_copy(obj, O); +O-h_original = 0; +} else { +O = stmgc_duplicate_old(obj); + +/* young and without original? */ +if (!(obj-h_original)) +obj-h_original = (revision_t)O; +} +obj-h_revision = (revision_t)O; + +O-h_tid |= GCFLAG_PUBLIC; +obj-h_tid |= (GCFLAG_NURSERY_MOVED | GCFLAG_PUBLIC); +/* here it is fine if it stays in read caches because + the object is immutable anyway and there are no + write_barriers allowed. */ + +dprintf((steal prot immutable - public: %p | %p\n, obj, O)); +stub = obj; +goto done; +} +dprintf((prot immutable - public: %p\n, obj)); +obj-h_tid |= GCFLAG_PUBLIC; +} +return; +} + /* we use 'all_stubs', a dictionary, in order to try to avoid duplicate stubs for the same object. XXX maybe it would be better to use a fast approximative cache that stays around for diff --git a/c4/stmgc.h b/c4/stmgc.h --- a/c4/stmgc.h +++ b/c4/stmgc.h @@ -29,6 +29,9 @@ /* allocate an object out of the local nursery */ gcptr stm_allocate(size_t size, unsigned long tid); +/* allocate an object that is be immutable. it cannot be changed with + a stm_write_barrier() or after the next commit */ +gcptr stm_allocate_immutable(size_t size, unsigned long tid); /* returns a never changing hash for the object */ revision_t stm_hash(gcptr); diff --git a/c4/weakref.c b/c4/weakref.c --- a/c4/weakref.c +++ b/c4/weakref.c @@ -6,7 +6,7 @@ gcptr stm_weakref_allocate(size_t size, unsigned long tid, gcptr obj) { stm_push_root(obj); -gcptr weakref = stm_allocate(size, tid); +gcptr weakref = stm_allocate_immutable(size, tid); obj = stm_pop_root();
[pypy-commit] stmgc weakref: typo that doesn't change much
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r410:212e6e027030 Date: 2013-07-18 14:49 +0200 http://bitbucket.org/pypy/stmgc/changeset/212e6e027030/ Log:typo that doesn't change much diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -53,7 +53,7 @@ write_barriers allowed. */ dprintf((steal prot immutable - public: %p | %p\n, obj, O)); -stub = obj; +stub = O; goto done; } dprintf((prot immutable - public: %p\n, obj)); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc weakref: and there was a bug in demo_random
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r412:324c3f18bbad Date: 2013-07-18 16:11 +0200 http://bitbucket.org/pypy/stmgc/changeset/324c3f18bbad/ Log:and there was a bug in demo_random diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -506,7 +506,7 @@ gcptr weakref_events(gcptr p, gcptr _r, gcptr _sr) { nodeptr t; -weaknodeptr w; +weaknodeptr w, ww; gcptr ptrs[] = {_r, _sr}; int i = get_rand(2); @@ -516,10 +516,11 @@ t = (nodeptr)read_barrier(ptrs[i]); w = t-weakref; if(w) { -assert(stm_get_tid((gcptr)w) == GCTID_WEAKREF); -if (w-node) { -check((gcptr)w-node); -return (gcptr)w-node; +ww = stm_read_barrier(w); +assert(stm_get_tid((gcptr)ww) == GCTID_WEAKREF); +if (ww-node) { +check((gcptr)ww-node); +return (gcptr)ww-node; } else { t-weakref = NULL; diff --git a/c4/weakref.c b/c4/weakref.c --- a/c4/weakref.c +++ b/c4/weakref.c @@ -18,7 +18,6 @@ /* Minor collection */ - static int is_in_nursery(struct tx_descriptor *d, gcptr obj) { return (d-nursery_base = (char*)obj ((char*)obj) d-nursery_end); ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc weakref: clean it up a bit
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r411:ff8c751610ca Date: 2013-07-18 15:41 +0200 http://bitbucket.org/pypy/stmgc/changeset/ff8c751610ca/ Log:clean it up a bit diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -26,39 +26,47 @@ if (obj-h_tid GCFLAG_IMMUTABLE) { assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); +if (obj-h_tid GCFLAG_PUBLIC) { +/* young public */ +assert(obj-h_tid GCFLAG_NURSERY_MOVED); +assert(IS_POINTER(obj-h_revision)); +stub = (gcptr)obj-h_revision; +goto done; +} + /* old or young protected! mark as PUBLIC */ -if (!(obj-h_tid GCFLAG_PUBLIC)) { -if (!(obj-h_tid GCFLAG_OLD)) { -gcptr O; +if (!(obj-h_tid GCFLAG_OLD)) { +/* young protected */ +gcptr O; + +if (obj-h_tid GCFLAG_HAS_ID) { +/* use id-copy for us */ +O = (gcptr)obj-h_original; +obj-h_tid = ~GCFLAG_HAS_ID; +stm_copy_to_old_id_copy(obj, O); +O-h_original = 0; +} else { +O = stmgc_duplicate_old(obj); -if (obj-h_tid GCFLAG_HAS_ID) { -/* use id-copy for us */ -O = (gcptr)obj-h_original; -obj-h_tid = ~GCFLAG_HAS_ID; -stm_copy_to_old_id_copy(obj, O); -O-h_original = 0; -} else { -O = stmgc_duplicate_old(obj); - -/* young and without original? */ -if (!(obj-h_original)) -obj-h_original = (revision_t)O; -} -obj-h_revision = (revision_t)O; - -O-h_tid |= GCFLAG_PUBLIC; -obj-h_tid |= (GCFLAG_NURSERY_MOVED | GCFLAG_PUBLIC); -/* here it is fine if it stays in read caches because - the object is immutable anyway and there are no - write_barriers allowed. */ - -dprintf((steal prot immutable - public: %p | %p\n, obj, O)); -stub = O; -goto done; +/* young and without original? */ +if (!(obj-h_original)) +obj-h_original = (revision_t)O; } -dprintf((prot immutable - public: %p\n, obj)); -obj-h_tid |= GCFLAG_PUBLIC; +obj-h_revision = (revision_t)O; + +O-h_tid |= GCFLAG_PUBLIC; +obj-h_tid |= (GCFLAG_NURSERY_MOVED | GCFLAG_PUBLIC); +/* here it is fine if it stays in read caches because + the object is immutable anyway and there are no + write_barriers allowed. */ +dprintf((steal prot immutable - public: %p - %p\n, obj, O)); +stub = O; +goto done; } +/* old protected: */ +dprintf((prot immutable - public: %p\n, obj)); +obj-h_tid |= GCFLAG_PUBLIC; + return; } ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc weakref: add stm_dbg_get_hdr_str() that prints the flags and tid of an object
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r414:560fad6b4f7f Date: 2013-07-19 07:57 +0200 http://bitbucket.org/pypy/stmgc/changeset/560fad6b4f7f/ Log:add stm_dbg_get_hdr_str() that prints the flags and tid of an object diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -516,7 +516,7 @@ t = (nodeptr)read_barrier(ptrs[i]); w = t-weakref; if(w) { -ww = stm_read_barrier(w); +ww = (weaknodeptr)stm_read_barrier((gcptr)w); assert(stm_get_tid((gcptr)ww) == GCTID_WEAKREF); if (ww-node) { check((gcptr)ww-node); diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -6,6 +6,28 @@ */ #include stmimpl.h +#ifdef _GC_DEBUG +char tmp_buf[128]; +char* stm_dbg_get_hdr_str(gcptr obj) +{ +char *cur; +char *flags[] = GC_FLAG_NAMES; +int i; + +i = 0; +cur = tmp_buf; +while (flags[i]) { +if (obj-h_tid (STM_FIRST_GCFLAG i)) { +cur += sprintf(cur, %s|, flags[i]); +} +i++; +} +cur += sprintf(cur, tid=%ld\n, stm_get_tid(obj)); +return tmp_buf; +} +#endif + + __thread struct tx_descriptor *thread_descriptor = NULL; diff --git a/c4/et.h b/c4/et.h --- a/c4/et.h +++ b/c4/et.h @@ -200,4 +200,7 @@ void DescriptorInit(void); void DescriptorDone(void); +#ifdef _GC_DEBUG +char* stm_dbg_get_hdr_str(gcptr obj); +#endif #endif /* _ET_H */ ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc weakref: more debug output
Author: Remi Meier remi.me...@gmail.com Branch: weakref Changeset: r418:983bb16c726a Date: 2013-07-19 11:46 +0200 http://bitbucket.org/pypy/stmgc/changeset/983bb16c726a/ Log:more debug output diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -16,13 +16,14 @@ i = 0; cur = tmp_buf; +cur += sprintf(cur, %p:, obj); while (flags[i]) { if (obj-h_tid (STM_FIRST_GCFLAG i)) { cur += sprintf(cur, %s|, flags[i]); } i++; } -cur += sprintf(cur, tid=%ld\n, stm_get_tid(obj)); +cur += sprintf(cur, tid=%ld, stm_get_tid(obj)); return tmp_buf; } #endif diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -27,10 +27,11 @@ if (obj-h_tid GCFLAG_IMMUTABLE) { assert(!(obj-h_tid GCFLAG_PRIVATE_FROM_PROTECTED)); if (obj-h_tid GCFLAG_PUBLIC) { -/* young public */ +/* young public, replace with stolen old copy */ assert(obj-h_tid GCFLAG_NURSERY_MOVED); assert(IS_POINTER(obj-h_revision)); stub = (gcptr)obj-h_revision; +assert(!IS_POINTER(stub-h_revision)); /* not outdated */ goto done; } @@ -52,10 +53,10 @@ if (!(obj-h_original)) obj-h_original = (revision_t)O; } +obj-h_tid |= (GCFLAG_NURSERY_MOVED | GCFLAG_PUBLIC); obj-h_revision = (revision_t)O; O-h_tid |= GCFLAG_PUBLIC; -obj-h_tid |= (GCFLAG_NURSERY_MOVED | GCFLAG_PUBLIC); /* here it is fine if it stays in read caches because the object is immutable anyway and there are no write_barriers allowed. */ diff --git a/c4/weakref.c b/c4/weakref.c --- a/c4/weakref.c +++ b/c4/weakref.c @@ -41,9 +41,13 @@ if (is_in_nursery(d, pointing_to)) { if (pointing_to-h_tid GCFLAG_NURSERY_MOVED) { +dprintf((weakref ptr moved %p-%p\n, + WEAKREF_PTR(weakref, size), + (gcptr)pointing_to-h_revision)); WEAKREF_PTR(weakref, size) = (gcptr)pointing_to-h_revision; } else { +dprintf((weakref lost ptr %p\n, WEAKREF_PTR(weakref, size))); WEAKREF_PTR(weakref, size) = NULL; continue; /* no need to remember this weakref any longer */ } @@ -143,6 +147,10 @@ assert(pointing_to != NULL); if (is_partially_visited(pointing_to)) { pointing_to = stmgcpage_visit(pointing_to); +dprintf((mweakref ptr moved %p-%p\n, + WEAKREF_PTR(weakref, size), + pointing_to)); + assert(pointing_to-h_tid GCFLAG_VISITED); WEAKREF_PTR(weakref, size) = pointing_to; } @@ -169,6 +177,7 @@ if (pointing_to-h_tid GCFLAG_VISITED) { continue; /* the target stays alive, the weakref remains */ } +dprintf((mweakref lost ptr %p\n, WEAKREF_PTR(weakref, size))); WEAKREF_PTR(weakref, size) = NULL; /* the target dies */ } /* remove this weakref from the list */ ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: more backout
Author: Remi Meier remi.me...@gmail.com Branch: Changeset: r420:d7b329c4c608 Date: 2013-07-19 11:52 +0200 http://bitbucket.org/pypy/stmgc/changeset/d7b329c4c608/ Log:more backout diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -358,19 +358,6 @@ stmgc_trace(obj, visit_if_young); } - -while (gcptrlist_size(private_or_protected_roots) 0) { -gcptr obj = gcptrlist_pop(private_or_protected_roots); -/* if it has the write_barrier flag, clear it so that - it doesn't get inserted twice by a later write-barrier */ -if (obj-h_tid GCFLAG_WRITE_BARRIER) { -/* only insert those that were in old_obj_to_trace - and that we didn't insert already */ -obj-h_tid = ~GCFLAG_WRITE_BARRIER; -gcptrlist_insert(d-old_objects_to_trace, obj); -dprintf((re-add %p to old_objects_to_trace\n, obj)); -} -} } static void fix_list_of_read_objects(struct tx_descriptor *d) ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc default: demo_random should not use the writeables cache anymore, since that is invalid again
Author: Remi Meier remi.me...@gmail.com Branch: Changeset: r421:5f6c08c9274a Date: 2013-07-19 12:06 +0200 http://bitbucket.org/pypy/stmgc/changeset/5f6c08c9274a/ Log:demo_random should not use the writeables cache anymore, since that is invalid again diff --git a/c4/demo_random.c b/c4/demo_random.c --- a/c4/demo_random.c +++ b/c4/demo_random.c @@ -53,11 +53,6 @@ time_t default_seed; gcptr shared_roots[SHARED_ROOTS]; -#define CACHE_MASK 65535 -#define CACHE_ENTRIES ((CACHE_MASK + 1) / sizeof(char *)) -#define CACHE_AT(cache, obj) (*(gcptr *)((char *)(cache) \ - + ((revision_t)(obj) CACHE_MASK))) - struct thread_data { unsigned int thread_seed; gcptr roots[MAXROOTS]; @@ -67,7 +62,6 @@ int steps_left; int interruptible; int atomic; -revision_t writeable[CACHE_ENTRIES]; }; __thread struct thread_data td; @@ -137,7 +131,7 @@ return x; } -void push_roots(int with_cache) +void push_roots() { int i; for (i = 0; i td.num_roots; i++) { @@ -145,30 +139,11 @@ if (td.roots[i]) stm_push_root(td.roots[i]); } - -if (with_cache) { -stm_push_root(NULL); -for (i = 0; i CACHE_ENTRIES; i++) { -if (td.writeable[i]) -stm_push_root((gcptr)td.writeable[i]); -} -} } -void pop_roots(int with_cache) +void pop_roots() { int i; -/* some objects may have changed positions */ -memset(td.writeable, 0, sizeof(td.writeable)); - -if (with_cache) { -gcptr obj = stm_pop_root(); -while (obj) { -CACHE_AT(td.writeable, obj) = obj; -obj = stm_pop_root(); -} -} - for (i = td.num_roots - 1; i = 0; i--) { if (td.roots[i]) td.roots[i] = stm_pop_root(); @@ -186,9 +161,9 @@ nodeptr allocate_node() { nodeptr r; -push_roots(1); +push_roots(); r = (nodeptr)stm_allocate(sizeof(struct node), GCTID_STRUCT_NODE); -pop_roots(1); +pop_roots(); return r; } @@ -252,7 +227,6 @@ if (p != NULL) { check(p); w = stm_write_barrier(p); -CACHE_AT(td.writeable, w) = w; check(w); assert(is_private(w)); } @@ -369,22 +343,22 @@ { int k = get_rand(100); if (k 10) { -push_roots(1); +push_roots(); stm_push_root(p); stm_become_inevitable(fun); p = stm_pop_root(); -pop_roots(1); +pop_roots(); } else if (k 40) { -push_roots(1); +push_roots(); stmgc_minor_collect(); -pop_roots(1); +pop_roots(); p = NULL; } else if (k 41 DO_MAJOR_COLLECTS) { fprintf(stdout, major collect\n); -push_roots(1); +push_roots(); stmgcpage_possibly_major_collect(1); -pop_roots(1); +pop_roots(); p = NULL; } return p; @@ -423,10 +397,7 @@ break; case 7: // set 'p' as *next in one of the roots check(_r); -if (CACHE_AT(td.writeable, _r) == _r) -w_r = (nodeptr)_r; -else -w_r = (nodeptr)write_barrier(_r); +w_r = (nodeptr)write_barrier(_r); check((gcptr)w_r); check(p); w_r-next = (struct node*)p; @@ -485,10 +456,7 @@ assert(w_t-id == stm_id((gcptr)_t)); } else { -if (CACHE_AT(td.writeable, _t) == _t) -w_t = (nodeptr)_t; -else -w_t = (nodeptr)write_barrier(_t); +w_t = (nodeptr)write_barrier(_t); w_t-id = stm_id((gcptr)w_t); assert(w_t-id == stm_id((gcptr)_t)); } @@ -504,10 +472,7 @@ assert(w_t-hash == stm_hash((gcptr)_t)); } else { -if (CACHE_AT(td.writeable, _t) == _t) -w_t = (nodeptr)_t; -else -w_t = (nodeptr)write_barrier(_t); +w_t = (nodeptr)write_barrier(_t); w_t-hash = stm_hash((gcptr)w_t); assert(w_t-hash == stm_hash((gcptr)_t)); } @@ -563,7 +528,7 @@ void transaction_break() { -push_roots(0); +push_roots(); td.interruptible = 1; copy_roots(td.roots, td.roots_outside_perform, td.num_roots); @@ -575,9 +540,7 @@ copy_roots(td.roots_outside_perform, td.roots, td.num_roots); td.interruptible = 0; -pop_roots(0); - -/* done by pop_roots() memset(td.writeable, 0, sizeof(td.writeable)); */ +pop_roots(); } @@ -592,8 +555,8 @@ assert(end_marker == END_MARKER_ON || end_marker == END_MARKER_OFF); arg1 = stm_pop_root(); assert(arg1 == NULL); -pop_roots(0); -push_roots(0); +pop_roots(); +push_roots(); stm_push_root(arg1); stm_push_root(end_marker); @@ -609,9 +572,6 @@ { gcptr p = NULL; -// clear cache of writeables: -memset(td.writeable, 0,
[pypy-commit] stmgc default: Backed out changeset: 191c168da60e (readding of objects during minor collections to old_objects_to_trace)
Author: Remi Meier remi.me...@gmail.com Branch: Changeset: r419:ff208391e85c Date: 2013-07-19 11:51 +0200 http://bitbucket.org/pypy/stmgc/changeset/ff208391e85c/ Log:Backed out changeset: 191c168da60e (readding of objects during minor collections to old_objects_to_trace) diff --git a/c4/nursery.c b/c4/nursery.c --- a/c4/nursery.c +++ b/c4/nursery.c @@ -125,9 +125,6 @@ } // -/* list for private/protected, old roots that need to be - kept in old_objects_to_trace */ -static __thread struct GcPtrList private_or_protected_roots = {0, 0, NULL}; static inline gcptr create_old_object_copy(gcptr obj) { @@ -207,22 +204,6 @@ (revision_t)END_MARKER_ON)) { /* 'item' is a regular, non-null pointer */ visit_if_young(end); -item = *end; -/* if private or protected, this object needs to be - traced again in the next minor_collect if it is - currently in old_objects_to_trace. Because then - it may be seen as write-ready in the view of - someone: - pw = write_barrier(); push_root(pw); - minor_collect(); pw = pop_root(); // pw still write-ready -*/ -if (item - !(item-h_tid GCFLAG_WRITE_BARRIER) /* not set in - obj_to_trace*/ - (item-h_tid GCFLAG_PRIVATE_FROM_PROTECTED -|| item-h_revision == stm_private_rev_num)) { -gcptrlist_insert(private_or_protected_roots, item); -} } else if (item != NULL) { if (item == END_MARKER_OFF) @@ -545,15 +526,10 @@ d-num_read_objects_known_old); assert(gcptrlist_size(d-private_from_protected) = d-num_private_from_protected_known_old); -#if 0 -/* we could here force the following, but there is little point - and it's a bad idea to do things in this function that is - compiled only in debug mode */ d-num_read_objects_known_old = gcptrlist_size(d-list_of_read_objects); d-num_private_from_protected_known_old = gcptrlist_size(d-private_from_protected); -#endif return 0; } else { diff --git a/c4/test/test_et.py b/c4/test/test_et.py --- a/c4/test/test_et.py +++ b/c4/test/test_et.py @@ -205,6 +205,7 @@ assert list_of_read_objects() == [p2] def test_write_barrier_after_minor_collect(): +# should fail p = oalloc_refs(1) pw = lib.stm_write_barrier(p) @@ -220,8 +221,10 @@ assert pw.h_tid GCFLAG_OLD rawsetptr(pw, 0, r) -# pw needs to be readded to old_objects_to_trace -# before the next minor gc in order for this test to pass +# pw not in old_objects_to_trace. A +# repeated write_barrier before +# rawsetptr() would fix that + lib.stm_push_root(r) minor_collect() minor_collect() @@ -232,24 +235,13 @@ pr = lib.stm_read_barrier(p) assert r != r2 +# these will fail because pw/pr was +# not traced in the last minor_collect, +# because they were not registered in +# old_objects_to_trace. assert getptr(pr, 0) != r assert getptr(pr, 0) == r2 -# the following shouldn't be done -# because pw was not saved. Just -# here to check that pw gets removed -# from old_objects_to_trace when not found -# on the root stack anymore -rawsetptr(pw, 0, q) -lib.stm_push_root(q) -minor_collect() -q2 = lib.stm_pop_root() -check_nursery_free(q) -pr = lib.stm_read_barrier(p) -assert q != q2 -assert getptr(pr, 0) == q -assert getptr(pr, 0) != q2 - def test_write_barrier_after_minor_collect_young_to_old(): p = nalloc_refs(1) pw = lib.stm_write_barrier(p) diff --git a/duhton/listobject.c b/duhton/listobject.c --- a/duhton/listobject.c +++ b/duhton/listobject.c @@ -75,7 +75,7 @@ void _list_append(DuListObject *ob, DuObject *x) { -_du_write1(ob); +_du_read1(ob); DuTupleObject *olditems = ob-ob_tuple; _du_read1(olditems); @@ -85,6 +85,8 @@ DuTupleObject *newitems = DuTuple_New(newcount); _du_restore3(ob, x, olditems); +_du_write1(ob); + for (i=0; inewcount-1; i++) newitems-ob_items[i] = olditems-ob_items[i]; newitems-ob_items[newcount-1] = x; ___ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit