From 2e7daad62ee243556b67109535ddfacfb11a0160 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 1 Jul 2018 16:53:15 +0300 Subject: [PATCH] New public API (PTR_STORE_AND_DIRTY) to simplify store-and-dirty operation * cord/cordbscs.c (CORD_cat_char_star, CORD_cat, CORD_from_fn_inner, CORD_substr_closure): Replace the last store to the heap-allocated object, GC_END_STUBBORN_CHANGE() and GC_reachable_here() with GC_PTR_STORE_AND_DIRTY() call. * cord/tests/de.c (prune_map, add_map, replace_line): Likewise. * include/gc_inline.h (GC_CONS): Likewise. * tests/disclaim_test.c (pair_dct, pair_new): Likewise. * tests/test.c [!VERY_SMALL_CONFIG] (cons): Likewise. * tests/test.c (small_cons, small_cons_uncollectable, reverse_test_inner, mktree): Likewise. * tests/test.c [GC_GCJ_SUPPORT] (gcj_cons): Likewise. * tests/test.c [GC_PTHREADS && !SMALL_CONFIG && !GC_DEBUG] (alloc8bytes): Likewise. * tests/test.c [!NO_TYPED_TEST] (typed_test): Likewise. * tests/test_cpp.cc (main): Likewise. * dbg_mlc.c (GC_debug_ptr_store_and_dirty): Implement. * mallocx.c (GC_ptr_store_and_dirty): Likewise. * include/gc.h (GC_PTR_STORE_AND_DIRTY): New public macro. * include/gc.h (GC_debug_ptr_store_and_dirty, GC_ptr_store_and_dirty): Declare new public API function; add comment. * tests/test.c (reverse_test_inner): Remove tmp local variable. * tests/test.c (mktree): Remove right_left local variable. --- cord/cordbscs.c | 16 +++-------- cord/tests/de.c | 12 ++------ dbg_mlc.c | 7 +++++ include/gc.h | 10 +++++++ include/gc_inline.h | 4 +-- mallocx.c | 7 +++++ tests/disclaim_test.c | 8 ++---- tests/test.c | 78 ++++++++++++--------------------------------------- tests/test_cpp.cc | 4 +-- 9 files changed, 53 insertions(+), 93 deletions(-) diff --git a/cord/cordbscs.c b/cord/cordbscs.c index 7979ff7..117dd9f 100644 --- a/cord/cordbscs.c +++ b/cord/cordbscs.c @@ -231,10 +231,8 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) result->left_len = (unsigned char)lenx; result->len = (word)result_len; result->left = x; - result->right = y; - GC_END_STUBBORN_CHANGE(result); + GC_PTR_STORE_AND_DIRTY(&result->right, y); GC_reachable_here(x); - GC_reachable_here(y); if (depth >= MAX_DEPTH) { return(CORD_balance((CORD)result)); } else { @@ -275,10 +273,8 @@ CORD CORD_cat(CORD x, CORD y) result->left_len = (unsigned char)lenx; result->len = (word)result_len; result->left = x; - result->right = y; - GC_END_STUBBORN_CHANGE(result); + GC_PTR_STORE_AND_DIRTY(&result->right, y); GC_reachable_here(x); - GC_reachable_here(y); if (depth >= MAX_DEPTH) { return(CORD_balance((CORD)result)); } else { @@ -318,9 +314,7 @@ static CordRep *CORD_from_fn_inner(CORD_fn fn, void * client_data, size_t len) /* depth is already 0 */ result->len = (word)len; result->fn = fn; - result->client_data = client_data; - GC_END_STUBBORN_CHANGE(result); - GC_reachable_here(client_data); + GC_PTR_STORE_AND_DIRTY(&result->client_data, client_data); return (CordRep *)result; } } @@ -369,10 +363,8 @@ CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f) CordRep * result; if (sa == 0) OUT_OF_MEMORY; - sa->sa_cord = (CordRep *)x; sa->sa_index = i; - GC_END_STUBBORN_CHANGE(sa); - GC_reachable_here(x); + GC_PTR_STORE_AND_DIRTY(&sa->sa_cord, x); result = CORD_from_fn_inner(f, (void *)sa, n); if ((CORD)result != CORD_EMPTY && 0 == result -> function.null) result -> function.header = SUBSTR_HDR; diff --git a/cord/tests/de.c b/cord/tests/de.c index 522da91..2fd8c48 100644 --- a/cord/tests/de.c +++ b/cord/tests/de.c @@ -139,9 +139,7 @@ void prune_map(void) if (map -> line < start_line - LINES && map -> previous != 0) { line_map pred = map -> previous -> previous; - map -> previous = pred; - GC_END_STUBBORN_CHANGE(map); - GC_reachable_here(pred); + GC_PTR_STORE_AND_DIRTY(&map->previous, pred); } map = map -> previous; } while (map != 0); @@ -158,9 +156,7 @@ void add_map(int line_arg, size_t pos) new_map -> line = line_arg; new_map -> pos = pos; cur_map = current_map; - new_map -> previous = cur_map; - GC_END_STUBBORN_CHANGE(new_map); - GC_reachable_here(cur_map); + GC_PTR_STORE_AND_DIRTY(&new_map->previous, cur_map); current_map = new_map; current_map_size++; } @@ -260,9 +256,7 @@ void replace_line(int i, CORD s) addch(c); } } - screen[i] = s; - GC_END_STUBBORN_CHANGE(screen + i); - GC_reachable_here(s); + GC_PTR_STORE_AND_DIRTY(screen + i, s); } } #else diff --git a/dbg_mlc.c b/dbg_mlc.c index 0471662..50eda33 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -630,6 +630,13 @@ GC_API void GC_CALL GC_debug_end_stubborn_change(const void *p) GC_end_stubborn_change(q); } +GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void *p, const void *q) +{ + *(void **)GC_is_visible(p) = GC_is_valid_displacement((void *)q); + GC_debug_end_stubborn_change(p); + REACHABLE_AFTER_DIRTY(q); +} + GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS) { diff --git a/include/gc.h b/include/gc.h index cfe9f6b..fd3e426 100644 --- a/include/gc.h +++ b/include/gc.h @@ -960,6 +960,7 @@ GC_API /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2) void * GC_CALL # define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \ GC_debug_register_finalizer_unreachable(p, f, d, of, od) # define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p) +# define GC_PTR_STORE_AND_DIRTY(p, q) GC_debug_ptr_store_and_dirty(p, q) # define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \ GC_general_register_disappearing_link(link, \ GC_base((/* no const */ void *)(obj))) @@ -986,6 +987,7 @@ GC_API /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2) void * GC_CALL # define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \ GC_register_finalizer_unreachable(p, f, d, of, od) # define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p) +# define GC_PTR_STORE_AND_DIRTY(p, q) GC_ptr_store_and_dirty(p, q) # define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \ GC_general_register_disappearing_link(link, obj) # define GC_REGISTER_LONG_LINK(link, obj) \ @@ -1635,6 +1637,14 @@ GC_API void GC_CALL GC_dump_finalization(void); # define GC_PTR_STORE(p, q) (*(void **)(p) = (void *)(q)) #endif +/* GC_PTR_STORE_AND_DIRTY(p,q) is equivalent to GC_PTR_STORE(p,q) */ +/* followed by GC_END_STUBBORN_CHANGE(p) and GC_reachable_here(q) */ +/* (assuming p and q do not have side effects). */ +GC_API void GC_CALL GC_ptr_store_and_dirty(void * /* p */, + const void * /* q */); +GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void * /* p */, + const void * /* q */); + /* Functions called to report pointer checking errors */ GC_API void (GC_CALLBACK * GC_same_obj_print_proc)(void * /* p */, void * /* q */); diff --git a/include/gc_inline.h b/include/gc_inline.h index 6527c3e..9dc783d 100644 --- a/include/gc_inline.h +++ b/include/gc_inline.h @@ -194,10 +194,8 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \ if ((result) != NULL) { \ *(void **)(result) = l; \ - ((void **)(result))[1] = r; \ - GC_end_stubborn_change(result); \ + GC_PTR_STORE_AND_DIRTY((void **)(result) + 1, r); \ GC_reachable_here(l); \ - GC_reachable_here(r); \ } \ } while (0) diff --git a/mallocx.c b/mallocx.c index 6888609..a318d5b 100644 --- a/mallocx.c +++ b/mallocx.c @@ -628,3 +628,10 @@ GC_API void GC_CALL GC_end_stubborn_change(const void *p) { GC_dirty(p); /* entire object */ } + +GC_API void GC_CALL GC_ptr_store_and_dirty(void *p, const void *q) +{ + *(const void **)p = q; + GC_dirty(p); + REACHABLE_AFTER_DIRTY(q); +} diff --git a/tests/disclaim_test.c b/tests/disclaim_test.c index 0a67892..5176bee 100644 --- a/tests/disclaim_test.c +++ b/tests/disclaim_test.c @@ -126,10 +126,8 @@ void GC_CALLBACK pair_dct(void *obj, void *cd) /* Invalidate it. */ memset(p->magic, '*', sizeof(p->magic)); p->checksum = 0; - p->car = (pair_t)cd; p->cdr = NULL; - GC_end_stubborn_change(p); - GC_reachable_here(cd); + GC_ptr_store_and_dirty(&p->car, cd); } pair_t @@ -148,10 +146,8 @@ pair_new(pair_t car, pair_t cdr) memcpy(p->magic, pair_magic, sizeof(p->magic)); p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0); p->car = car; - p->cdr = cdr; - GC_end_stubborn_change(p); + GC_ptr_store_and_dirty(&p->cdr, cdr); GC_reachable_here(car); - GC_reachable_here(cdr); # ifdef DEBUG_DISCLAIM_DESTRUCT printf("Construct %p = (%p, %p)\n", (void *)p, (void *)p->car, (void *)p->cdr); diff --git a/tests/test.c b/tests/test.c index 9a9780b..bda3834 100644 --- a/tests/test.c +++ b/tests/test.c @@ -324,10 +324,8 @@ sexpr cons (sexpr x, sexpr y) r = (sexpr)((char *)r + (my_extra & ~7)); # endif r -> sexpr_car = x; - r -> sexpr_cdr = y; - GC_END_STUBBORN_CHANGE(r); + GC_PTR_STORE_AND_DIRTY(&r->sexpr_cdr, y); GC_reachable_here(x); - GC_reachable_here(y); return r; } # endif @@ -382,10 +380,8 @@ sexpr small_cons (sexpr x, sexpr y) CHECK_OUT_OF_MEMORY(r); AO_fetch_and_add1(&collectable_count); r -> sexpr_car = x; - r -> sexpr_cdr = y; - GC_END_STUBBORN_CHANGE(r); + GC_PTR_STORE_AND_DIRTY(&r->sexpr_cdr, y); GC_reachable_here(x); - GC_reachable_here(y); return r; } @@ -410,10 +406,8 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y) CHECK_OUT_OF_MEMORY(r); AO_fetch_and_add1(&uncollectable_count); - r -> sexpr_car = x; r -> sexpr_cdr = (sexpr)(~(GC_word)y); - GC_END_STUBBORN_CHANGE(r); - GC_reachable_here(x); + GC_PTR_STORE_AND_DIRTY(&r->sexpr_car, x); return r; } @@ -430,10 +424,8 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y) CHECK_OUT_OF_MEMORY(r); result = (sexpr)(r + 1); result -> sexpr_car = x; - result -> sexpr_cdr = y; - GC_END_STUBBORN_CHANGE(r); + GC_PTR_STORE_AND_DIRTY(&result->sexpr_cdr, y); GC_reachable_here(x); - GC_reachable_here(y); return result; } #endif /* GC_GCJ_SUPPORT */ @@ -715,7 +707,6 @@ void *GC_CALLBACK reverse_test_inner(void *data) sexpr d; sexpr e; sexpr *f, *g, *h; - sexpr tmp; if (data == 0) { /* This stack frame is not guaranteed to be scanned. */ @@ -753,42 +744,27 @@ void *GC_CALLBACK reverse_test_inner(void *data) f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(f); AO_fetch_and_add1(&realloc_count); - tmp = ints(1,17); - f[5] = tmp; - GC_END_STUBBORN_CHANGE(f + 5); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(f + 5, ints(1, 17)); AO_fetch_and_add1(&collectable_count); g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr)); test_generic_malloc_or_special(g); g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(g); AO_fetch_and_add1(&realloc_count); - tmp = ints(1,18); - g[799] = tmp; - GC_END_STUBBORN_CHANGE(g + 799); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(g + 799, ints(1, 18)); AO_fetch_and_add1(&collectable_count); h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr)); h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(h); AO_fetch_and_add1(&realloc_count); # ifdef GC_GCJ_SUPPORT - tmp = gcj_ints(1,200); - h[1999] = tmp; - GC_END_STUBBORN_CHANGE(h + 1999); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(h + 1999, gcj_ints(1, 200)); for (i = 0; i < 51; ++i) { - tmp = gcj_reverse(h[1999]); - h[1999] = tmp; - GC_END_STUBBORN_CHANGE(h + 1999); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(h + 1999, gcj_reverse(h[1999])); } /* Leave it as the reversed list for now. */ # else - tmp = ints(1,200); - h[1999] = tmp; - GC_END_STUBBORN_CHANGE(h + 1999); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(h + 1999, ints(1, 200)); # endif /* Try to force some collections and reuse of small list elements */ for (i = 0; i < 10; i++) { @@ -837,10 +813,7 @@ void *GC_CALLBACK reverse_test_inner(void *data) check_ints(f[5], 1,17); check_ints(g[799], 1,18); # ifdef GC_GCJ_SUPPORT - tmp = gcj_reverse(h[1999]); - h[1999] = tmp; - GC_END_STUBBORN_CHANGE(h + 1999); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(h + 1999, gcj_reverse(h[1999])); # endif check_ints(h[1999], 1,200); # ifndef THREADS @@ -922,18 +895,13 @@ tn * mktree(int n) result -> lchild = left = mktree(n - 1); result -> rchild = right = mktree(n - 1); if (AO_fetch_and_add1(&extra_count) % 17 == 0 && n >= 2) { - tn * tmp, * right_left; + tn * tmp; CHECK_OUT_OF_MEMORY(left); tmp = left -> rchild; CHECK_OUT_OF_MEMORY(right); - right_left = right -> lchild; - left -> rchild = right_left; - right -> lchild = tmp; - GC_END_STUBBORN_CHANGE(left); - GC_reachable_here(right_left); - GC_END_STUBBORN_CHANGE(right); - GC_reachable_here(tmp); + GC_PTR_STORE_AND_DIRTY(&left->rchild, right->lchild); + GC_PTR_STORE_AND_DIRTY(&right->lchild, tmp); } if (AO_fetch_and_add1(&extra_count) % 119 == 0) { # ifndef GC_NO_FINALIZATION @@ -1084,10 +1052,8 @@ void * alloc8bytes(void) CHECK_OUT_OF_MEMORY(my_free_list); } next = GC_NEXT(my_free_list); - *my_free_list_ptr = next; + GC_PTR_STORE_AND_DIRTY(my_free_list_ptr, next); GC_NEXT(my_free_list) = 0; - GC_END_STUBBORN_CHANGE(my_free_list_ptr); - GC_reachable_here(next); AO_fetch_and_add1(&collectable_count); return(my_free_list); # endif @@ -1231,26 +1197,20 @@ void typed_test(void) newP = (GC_word *)GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2); CHECK_OUT_OF_MEMORY(newP); newP[0] = 17; - newP[1] = (GC_word)old; - GC_END_STUBBORN_CHANGE(newP); - GC_reachable_here(old); + GC_PTR_STORE_AND_DIRTY(newP + 1, old); old = newP; AO_fetch_and_add1(&collectable_count); newP = (GC_word*)GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3); CHECK_OUT_OF_MEMORY(newP); newP[0] = 17; - newP[1] = (GC_word)old; - GC_END_STUBBORN_CHANGE(newP); - GC_reachable_here(old); + GC_PTR_STORE_AND_DIRTY(newP + 1, old); old = newP; AO_fetch_and_add1(&collectable_count); newP = (GC_word *)GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word), d1); CHECK_OUT_OF_MEMORY(newP); newP[0] = 17; - newP[1] = (GC_word)old; - GC_END_STUBBORN_CHANGE(newP); - GC_reachable_here(old); + GC_PTR_STORE_AND_DIRTY(newP + 1, old); old = newP; AO_fetch_and_add1(&collectable_count); if (i & 0xff) { @@ -1267,9 +1227,7 @@ void typed_test(void) } CHECK_OUT_OF_MEMORY(newP); newP[0] = 17; - newP[1] = (GC_word)old; - GC_END_STUBBORN_CHANGE(newP); - GC_reachable_here(old); + GC_PTR_STORE_AND_DIRTY(newP + 1, old); old = newP; } for (i = 0; i < 20000; i++) { diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 43f034b..f97be6f 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -319,9 +319,7 @@ void* Undisguise( GC_word i ) { fprintf(stderr, "Out of memory!\n"); exit(3); } - *xptr = x; - GC_END_STUBBORN_CHANGE(xptr); - GC_reachable_here(x); + GC_PTR_STORE_AND_DIRTY(xptr, x); x = 0; # endif if (argc != 2 -- 2.7.4